aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-04-13 21:44:01 -0700
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-04-13 21:46:02 -0700
commit1788503892d27027b584542c2966daac06308c93 (patch)
treefaa2dd545957bb40ca39d9ae96959d6c34ff7fe5
parent95aa76b9fae3747a72c2db460d42c38b7faaee2a (diff)
downloadbun-1788503892d27027b584542c2966daac06308c93.tar.gz
bun-1788503892d27027b584542c2966daac06308c93.tar.zst
bun-1788503892d27027b584542c2966daac06308c93.zip
[bun dev] Fix CSS HMR bug
-rw-r--r--src/bundler.zig79
-rw-r--r--src/css_scanner.zig30
-rw-r--r--src/runtime/hmr.ts29
3 files changed, 67 insertions, 71 deletions
diff --git a/src/bundler.zig b/src/bundler.zig
index 486d38595..307ab3c97 100644
--- a/src/bundler.zig
+++ b/src/bundler.zig
@@ -2374,38 +2374,40 @@ pub const Bundler = struct {
import_path_format,
);
+ const written = brk: {
+ if (bundler.options.hot_module_reloading) {
+ break :brk (try CSSBundlerHMR.bundle(
+ file_path.text,
+ bundler.fs,
+ writer,
+ watcher,
+ &bundler.resolver.caches.fs,
+ filepath_hash,
+ file_descriptor,
+ allocator,
+ bundler.log,
+ &bundler.linker,
+ origin,
+ )).written;
+ } else {
+ break :brk (try CSSBundler.bundle(
+ file_path.text,
+ bundler.fs,
+ writer,
+ watcher,
+ &bundler.resolver.caches.fs,
+ filepath_hash,
+ file_descriptor,
+ allocator,
+ bundler.log,
+ &bundler.linker,
+ origin,
+ )).written;
+ }
+ };
+
return BuildResolveResultPair{
- .written = brk: {
- if (bundler.options.hot_module_reloading) {
- break :brk (try CSSBundlerHMR.bundle(
- file_path.text,
- bundler.fs,
- writer,
- watcher,
- &bundler.resolver.caches.fs,
- filepath_hash,
- file_descriptor,
- allocator,
- bundler.log,
- &bundler.linker,
- origin,
- )).written;
- } else {
- break :brk (try CSSBundler.bundle(
- file_path.text,
- bundler.fs,
- writer,
- watcher,
- &bundler.resolver.caches.fs,
- filepath_hash,
- file_descriptor,
- allocator,
- bundler.log,
- &bundler.linker,
- origin,
- )).written;
- }
- },
+ .written = written,
.input_fd = file_descriptor,
};
},
@@ -2603,12 +2605,18 @@ pub const Bundler = struct {
origin: URL,
};
var build_ctx = CSSBuildContext{ .origin = bundler.options.origin };
+
+ const BufferedWriter = std.io.CountingWriter(std.io.BufferedWriter(8096, std.fs.File.Writer));
const CSSWriter = Css.NewWriter(
- std.fs.File,
+ BufferedWriter.Writer,
@TypeOf(&bundler.linker),
import_path_format,
CSSBuildContext,
);
+ var buffered_writer = BufferedWriter{
+ .child_stream = .{ .unbuffered_writer = file.writer() },
+ .bytes_written = 0,
+ };
const entry = bundler.resolver.caches.fs.readFile(
bundler.fs,
file_path.text,
@@ -2620,16 +2628,19 @@ pub const Bundler = struct {
const _file = Fs.File{ .path = file_path, .contents = entry.contents };
var source = try logger.Source.initFile(_file, bundler.allocator);
source.contents_is_recycled = !cache_files;
+
var css_writer = CSSWriter.init(
&source,
- file,
+ buffered_writer.writer(),
&bundler.linker,
bundler.log,
);
+
css_writer.buildCtx = build_ctx;
try css_writer.run(bundler.log, bundler.allocator);
- output_file.size = css_writer.written;
+ try css_writer.ctx.context.child_stream.flush();
+ output_file.size = css_writer.ctx.context.bytes_written;
var file_op = options.OutputFile.FileOperation.fromFile(file.handle, file_path.pretty);
file_op.fd = file.handle;
diff --git a/src/css_scanner.zig b/src/css_scanner.zig
index 8d89a9cfd..19b1dcaa8 100644
--- a/src/css_scanner.zig
+++ b/src/css_scanner.zig
@@ -874,7 +874,6 @@ pub fn NewWriter(
ctx: WriterType,
linker: LinkerType,
source: *const logger.Source,
- written: usize = 0,
buildCtx: BuildContextType = undefined,
log: *logger.Log,
@@ -888,7 +887,6 @@ pub fn NewWriter(
.ctx = ctx,
.linker = linker,
.source = source,
- .written = 0,
.log = log,
};
}
@@ -944,24 +942,22 @@ pub fn NewWriter(
switch (quote) {
.none => {
try writer.ctx.writeAll(str);
- writer.written += str.len;
+
return;
},
.single => {
try writer.ctx.writeAll("'");
- writer.written += 1;
+
try writer.ctx.writeAll(str);
- writer.written += str.len;
+
try writer.ctx.writeAll("'");
- writer.written += 1;
},
.double => {
try writer.ctx.writeAll("\"");
- writer.written += 1;
+
try writer.ctx.writeAll(str);
- writer.written += str.len;
+
try writer.ctx.writeAll("\"");
- writer.written += 1;
},
}
}
@@ -970,31 +966,25 @@ pub fn NewWriter(
switch (text.quote) {
.none => {
try writer.ctx.writeAll("url(");
- writer.written += "url(".len;
},
.single => {
try writer.ctx.writeAll("url('");
- writer.written += "url('".len;
},
.double => {
try writer.ctx.writeAll("url(\"");
- writer.written += "url(\"".len;
},
}
try writer.ctx.writeAll(url_str);
- writer.written += url_str.len;
+
switch (text.quote) {
.none => {
try writer.ctx.writeAll(")");
- writer.written += ")".len;
},
.single => {
try writer.ctx.writeAll("')");
- writer.written += "')".len;
},
.double => {
try writer.ctx.writeAll("\")");
- writer.written += "\")".len;
},
}
}
@@ -1074,7 +1064,6 @@ pub fn NewWriter(
);
try writer.ctx.writeAll("@import ");
- writer.written += "@import ".len;
if (import.url) {
try writer.writeURL(url_str, import.text);
@@ -1083,14 +1072,10 @@ pub fn NewWriter(
}
try writer.ctx.writeAll(import.suffix);
- writer.written += import.suffix.len;
try writer.ctx.writeAll("\n");
-
- writer.written += 1;
}
},
.t_verbatim => {
- defer writer.written += @intCast(usize, chunk.range.len);
if (comptime std.meta.trait.hasFn("copyFileRange")(WriterType)) {
try writer.ctx.copyFileRange(
@intCast(usize, chunk.range.loc.start),
@@ -1162,6 +1147,7 @@ pub fn NewBundler(
linker: Linker,
origin: URL,
) !CodeCount {
+ const start_count = writer.written;
if (!has_set_global_queue) {
global_queued = QueuedList.init(default_allocator);
global_import_queud = ImportQueueFifo.init(default_allocator);
@@ -1247,7 +1233,7 @@ pub fn NewBundler(
try this.writer.done();
return CodeCount{
- .written = css.written,
+ .written = @intCast(usize, @maximum(this.writer.written - start_count, 0)),
.approximate_newline_count = lines_of_code,
};
}
diff --git a/src/runtime/hmr.ts b/src/runtime/hmr.ts
index afffc4847..4e62afa0f 100644
--- a/src/runtime/hmr.ts
+++ b/src/runtime/hmr.ts
@@ -7,6 +7,7 @@ if (typeof window !== "undefined") {
// We add a scope here to minimize chances of namespace collisions
var runOnce = false;
var clientStartTime = 0;
+ var empty: Uint8Array;
function formatDuration(duration: number) {
return Math.round(duration * 1000) / 1000;
@@ -355,21 +356,15 @@ if (typeof window !== "undefined") {
}
handleBuildSuccess(
- buffer: ByteBuffer,
+ bytes: Uint8Array,
build: API.WebsocketMessageBuildSuccess,
timestamp: number
) {
- debugger;
const start = performance.now();
var update = this.findCSSLinkTag(build.id);
// The last 4 bytes of the build message are the hash of the module
// Currently, this hash is only used for ensuring we reload the source-map
- let bytes = new Uint8Array(buffer.data.buffer, buffer.index);
- if (bytes.length > 4) {
- bytes = bytes.subarray(0, bytes.length - 4);
- }
-
if (update === null) {
__hmrlog.debug("Skipping unused CSS.");
return;
@@ -446,7 +441,6 @@ if (typeof window !== "undefined") {
}
}
- buffer = null;
bytes = null;
}
@@ -834,6 +828,15 @@ if (typeof window !== "undefined") {
}
return;
}
+ var bytes =
+ buffer.data.byteOffset + buffer.index + build.blob_length <=
+ buffer.data.buffer.byteLength
+ ? new Uint8Array(
+ buffer.data.buffer,
+ buffer.data.byteOffset + buffer.index,
+ build.blob_length
+ )
+ : (empty ||= new Uint8Array(0));
if (build.loader === API.Loader.css) {
BunError.clear();
@@ -841,7 +844,7 @@ if (typeof window !== "undefined") {
console.clear();
this.needsConsoleClear = false;
}
- return this.loaders.css.handleBuildSuccess(buffer, build, timestamp);
+ return this.loaders.css.handleBuildSuccess(bytes, build, timestamp);
}
const id = build.id;
@@ -879,20 +882,16 @@ if (typeof window !== "undefined") {
}
// These are the bytes!!
- const fileBytes =
- buffer.data.length > buffer.index
- ? buffer.data.subarray(buffer.index, end)
- : new Uint8Array(0);
var reload = new HotReload(
build.id,
index,
build,
- fileBytes,
+ bytes,
ReloadBehavior.hotReload,
hash || 0
);
-
+ bytes = null;
reload.timings.notify = timestamp - build.from_timestamp;
BunError.clear();