aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2021-06-12 19:10:08 -0700
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2021-06-12 19:10:08 -0700
commit43380a4d68d57f3d78f5b1e00962a59461140967 (patch)
tree1b038a16e0324191f0627dd2b9c3881b37d0d6c2
parentf93472101aa7338b3cdfc9db5c936d010f4cda82 (diff)
downloadbun-43380a4d68d57f3d78f5b1e00962a59461140967.tar.gz
bun-43380a4d68d57f3d78f5b1e00962a59461140967.tar.zst
bun-43380a4d68d57f3d78f5b1e00962a59461140967.zip
I think thats the JS part of HMR
-rw-r--r--src/api/schema.d.ts77
-rw-r--r--src/api/schema.js280
-rw-r--r--src/api/schema.peechy65
-rw-r--r--src/api/schema.zig1833
-rw-r--r--src/bundler.zig1
-rw-r--r--src/js_parser/imports.zig5
-rw-r--r--src/js_parser/js_parser.zig41
-rw-r--r--src/linker.zig12
-rw-r--r--src/options.zig3
-rw-r--r--src/runtime.zig7
-rw-r--r--src/runtime/hmr.ts391
-rw-r--r--src/runtime/index.ts2
12 files changed, 1853 insertions, 864 deletions
diff --git a/src/api/schema.d.ts b/src/api/schema.d.ts
index b3eefd8dd..43c8bc47f 100644
--- a/src/api/schema.d.ts
+++ b/src/api/schema.d.ts
@@ -119,6 +119,29 @@ type uint32 = number;
4: "debug",
debug: "debug"
}
+ export enum WebsocketMessageKind {
+ welcome = 1,
+ file_change_notification = 2,
+ build_success = 3,
+ build_fail = 4
+ }
+ export const WebsocketMessageKindKeys = {
+ 1: "welcome",
+ welcome: "welcome",
+ 2: "file_change_notification",
+ file_change_notification: "file_change_notification",
+ 3: "build_success",
+ build_success: "build_success",
+ 4: "build_fail",
+ build_fail: "build_fail"
+ }
+ export enum WebsocketCommandKind {
+ build = 1
+ }
+ export const WebsocketCommandKindKeys = {
+ 1: "build",
+ build: "build"
+ }
export interface JSX {
factory: string;
runtime: JSXRuntime;
@@ -262,6 +285,46 @@ type uint32 = number;
msgs: Message[];
}
+ export interface WebsocketMessage {
+ timestamp: uint32;
+ kind: WebsocketMessageKind;
+ }
+
+ export interface WebsocketMessageWelcome {
+ epoch: uint32;
+ }
+
+ export interface WebsocketMessageFileChangeNotification {
+ id: uint32;
+ loader: Loader;
+ }
+
+ export interface WebsocketCommand {
+ kind: WebsocketCommandKind;
+ timestamp: uint32;
+ }
+
+ export interface WebsocketCommandBuild {
+ id: uint32;
+ }
+
+ export interface WebsocketMessageBuildSuccess {
+ id: uint32;
+ from_timestamp: uint32;
+ loader: Loader;
+ module_path: alphanumeric;
+ log: Log;
+ bytes: Uint8Array;
+ }
+
+ export interface WebsocketMessageBuildFailure {
+ id: uint32;
+ from_timestamp: uint32;
+ loader: Loader;
+ module_path: alphanumeric;
+ log: Log;
+ }
+
export declare function encodeJSX(message: JSX, bb: ByteBuffer): void;
export declare function decodeJSX(buffer: ByteBuffer): JSX;
export declare function encodeStringPointer(message: StringPointer, bb: ByteBuffer): void;
@@ -300,3 +363,17 @@ type uint32 = number;
export declare function decodeMessage(buffer: ByteBuffer): Message;
export declare function encodeLog(message: Log, bb: ByteBuffer): void;
export declare function decodeLog(buffer: ByteBuffer): Log;
+ export declare function encodeWebsocketMessage(message: WebsocketMessage, bb: ByteBuffer): void;
+ export declare function decodeWebsocketMessage(buffer: ByteBuffer): WebsocketMessage;
+ export declare function encodeWebsocketMessageWelcome(message: WebsocketMessageWelcome, bb: ByteBuffer): void;
+ export declare function decodeWebsocketMessageWelcome(buffer: ByteBuffer): WebsocketMessageWelcome;
+ export declare function encodeWebsocketMessageFileChangeNotification(message: WebsocketMessageFileChangeNotification, bb: ByteBuffer): void;
+ export declare function decodeWebsocketMessageFileChangeNotification(buffer: ByteBuffer): WebsocketMessageFileChangeNotification;
+ export declare function encodeWebsocketCommand(message: WebsocketCommand, bb: ByteBuffer): void;
+ export declare function decodeWebsocketCommand(buffer: ByteBuffer): WebsocketCommand;
+ export declare function encodeWebsocketCommandBuild(message: WebsocketCommandBuild, bb: ByteBuffer): void;
+ export declare function decodeWebsocketCommandBuild(buffer: ByteBuffer): WebsocketCommandBuild;
+ export declare function encodeWebsocketMessageBuildSuccess(message: WebsocketMessageBuildSuccess, bb: ByteBuffer): void;
+ export declare function decodeWebsocketMessageBuildSuccess(buffer: ByteBuffer): WebsocketMessageBuildSuccess;
+ export declare function encodeWebsocketMessageBuildFailure(message: WebsocketMessageBuildFailure, bb: ByteBuffer): void;
+ export declare function decodeWebsocketMessageBuildFailure(buffer: ByteBuffer): WebsocketMessageBuildFailure;
diff --git a/src/api/schema.js b/src/api/schema.js
index e72112e32..71fde7436 100644
--- a/src/api/schema.js
+++ b/src/api/schema.js
@@ -1236,6 +1236,266 @@ function encodeLog(message, bb) {
}
}
+const WebsocketMessageKind = {
+ "1": 1,
+ "2": 2,
+ "3": 3,
+ "4": 4,
+ "welcome": 1,
+ "file_change_notification": 2,
+ "build_success": 3,
+ "build_fail": 4
+};
+const WebsocketMessageKindKeys = {
+ "1": "welcome",
+ "2": "file_change_notification",
+ "3": "build_success",
+ "4": "build_fail",
+ "welcome": "welcome",
+ "file_change_notification": "file_change_notification",
+ "build_success": "build_success",
+ "build_fail": "build_fail"
+};
+const WebsocketCommandKind = {
+ "1": 1,
+ "build": 1
+};
+const WebsocketCommandKindKeys = {
+ "1": "build",
+ "build": "build"
+};
+
+function decodeWebsocketMessage(bb) {
+ var result = {};
+
+ result["timestamp"] = bb.readUint32();
+ result["kind"] = WebsocketMessageKind[bb.readByte()];
+ return result;
+}
+
+function encodeWebsocketMessage(message, bb) {
+
+ var value = message["timestamp"];
+ if (value != null) {
+ bb.writeUint32(value);
+ } else {
+ throw new Error("Missing required field \"timestamp\"");
+ }
+
+ var value = message["kind"];
+ if (value != null) {
+ var encoded = WebsocketMessageKind[value];
+if (encoded === void 0) throw new Error("Invalid value " + JSON.stringify(value) + " for enum \"WebsocketMessageKind\"");
+bb.writeByte(encoded);
+ } else {
+ throw new Error("Missing required field \"kind\"");
+ }
+
+}
+
+function decodeWebsocketMessageWelcome(bb) {
+ var result = {};
+
+ result["epoch"] = bb.readUint32();
+ return result;
+}
+
+function encodeWebsocketMessageWelcome(message, bb) {
+
+ var value = message["epoch"];
+ if (value != null) {
+ bb.writeUint32(value);
+ } else {
+ throw new Error("Missing required field \"epoch\"");
+ }
+
+}
+
+function decodeWebsocketMessageFileChangeNotification(bb) {
+ var result = {};
+
+ result["id"] = bb.readUint32();
+ result["loader"] = Loader[bb.readByte()];
+ return result;
+}
+
+function encodeWebsocketMessageFileChangeNotification(message, bb) {
+
+ var value = message["id"];
+ if (value != null) {
+ bb.writeUint32(value);
+ } else {
+ throw new Error("Missing required field \"id\"");
+ }
+
+ var value = message["loader"];
+ if (value != null) {
+ var encoded = Loader[value];
+if (encoded === void 0) throw new Error("Invalid value " + JSON.stringify(value) + " for enum \"Loader\"");
+bb.writeByte(encoded);
+ } else {
+ throw new Error("Missing required field \"loader\"");
+ }
+
+}
+
+function decodeWebsocketCommand(bb) {
+ var result = {};
+
+ result["kind"] = WebsocketCommandKind[bb.readByte()];
+ result["timestamp"] = bb.readUint32();
+ return result;
+}
+
+function encodeWebsocketCommand(message, bb) {
+
+ var value = message["kind"];
+ if (value != null) {
+ var encoded = WebsocketCommandKind[value];
+if (encoded === void 0) throw new Error("Invalid value " + JSON.stringify(value) + " for enum \"WebsocketCommandKind\"");
+bb.writeByte(encoded);
+ } else {
+ throw new Error("Missing required field \"kind\"");
+ }
+
+ var value = message["timestamp"];
+ if (value != null) {
+ bb.writeUint32(value);
+ } else {
+ throw new Error("Missing required field \"timestamp\"");
+ }
+
+}
+
+function decodeWebsocketCommandBuild(bb) {
+ var result = {};
+
+ result["id"] = bb.readUint32();
+ return result;
+}
+
+function encodeWebsocketCommandBuild(message, bb) {
+
+ var value = message["id"];
+ if (value != null) {
+ bb.writeUint32(value);
+ } else {
+ throw new Error("Missing required field \"id\"");
+ }
+
+}
+
+function decodeWebsocketMessageBuildSuccess(bb) {
+ var result = {};
+
+ result["id"] = bb.readUint32();
+ result["from_timestamp"] = bb.readUint32();
+ result["loader"] = Loader[bb.readByte()];
+ result["module_path"] = bb.readAlphanumeric();
+ result["log"] = decodeLog(bb);
+ result["bytes"] = bb.readByteArray();
+ return result;
+}
+
+function encodeWebsocketMessageBuildSuccess(message, bb) {
+
+ var value = message["id"];
+ if (value != null) {
+ bb.writeUint32(value);
+ } else {
+ throw new Error("Missing required field \"id\"");
+ }
+
+ var value = message["from_timestamp"];
+ if (value != null) {
+ bb.writeUint32(value);
+ } else {
+ throw new Error("Missing required field \"from_timestamp\"");
+ }
+
+ var value = message["loader"];
+ if (value != null) {
+ var encoded = Loader[value];
+if (encoded === void 0) throw new Error("Invalid value " + JSON.stringify(value) + " for enum \"Loader\"");
+bb.writeByte(encoded);
+ } else {
+ throw new Error("Missing required field \"loader\"");
+ }
+
+ var value = message["module_path"];
+ if (value != null) {
+ bb.writeAlphanumeric(value);
+ } else {
+ throw new Error("Missing required field \"module_path\"");
+ }
+
+ var value = message["log"];
+ if (value != null) {
+ encodeLog(value, bb);
+ } else {
+ throw new Error("Missing required field \"log\"");
+ }
+
+ var value = message["bytes"];
+ if (value != null) {
+ bb.writeByteArray(value);
+ } else {
+ throw new Error("Missing required field \"bytes\"");
+ }
+
+}
+
+function decodeWebsocketMessageBuildFailure(bb) {
+ var result = {};
+
+ result["id"] = bb.readUint32();
+ result["from_timestamp"] = bb.readUint32();
+ result["loader"] = Loader[bb.readByte()];
+ result["module_path"] = bb.readAlphanumeric();
+ result["log"] = decodeLog(bb);
+ return result;
+}
+
+function encodeWebsocketMessageBuildFailure(message, bb) {
+
+ var value = message["id"];
+ if (value != null) {
+ bb.writeUint32(value);
+ } else {
+ throw new Error("Missing required field \"id\"");
+ }
+
+ var value = message["from_timestamp"];
+ if (value != null) {
+ bb.writeUint32(value);
+ } else {
+ throw new Error("Missing required field \"from_timestamp\"");
+ }
+
+ var value = message["loader"];
+ if (value != null) {
+ var encoded = Loader[value];
+if (encoded === void 0) throw new Error("Invalid value " + JSON.stringify(value) + " for enum \"Loader\"");
+bb.writeByte(encoded);
+ } else {
+ throw new Error("Missing required field \"loader\"");
+ }
+
+ var value = message["module_path"];
+ if (value != null) {
+ bb.writeAlphanumeric(value);
+ } else {
+ throw new Error("Missing required field \"module_path\"");
+ }
+
+ var value = message["log"];
+ if (value != null) {
+ encodeLog(value, bb);
+ } else {
+ throw new Error("Missing required field \"log\"");
+ }
+
+}
export { Loader }
export { LoaderKeys }
@@ -1290,4 +1550,22 @@ export { encodeMessageData }
export { decodeMessage }
export { encodeMessage }
export { decodeLog }
-export { encodeLog } \ No newline at end of file
+export { encodeLog }
+export { WebsocketMessageKind }
+export { WebsocketMessageKindKeys }
+export { WebsocketCommandKind }
+export { WebsocketCommandKindKeys }
+export { decodeWebsocketMessage }
+export { encodeWebsocketMessage }
+export { decodeWebsocketMessageWelcome }
+export { encodeWebsocketMessageWelcome }
+export { decodeWebsocketMessageFileChangeNotification }
+export { encodeWebsocketMessageFileChangeNotification }
+export { decodeWebsocketCommand }
+export { encodeWebsocketCommand }
+export { decodeWebsocketCommandBuild }
+export { encodeWebsocketCommandBuild }
+export { decodeWebsocketMessageBuildSuccess }
+export { encodeWebsocketMessageBuildSuccess }
+export { decodeWebsocketMessageBuildFailure }
+export { encodeWebsocketMessageBuildFailure } \ No newline at end of file
diff --git a/src/api/schema.peechy b/src/api/schema.peechy
index 257fafd0a..6fa6912ef 100644
--- a/src/api/schema.peechy
+++ b/src/api/schema.peechy
@@ -243,12 +243,65 @@ struct Log {
// From a server perspective, this means the filesystem watching thread can send the same WebSocket message
// to every client, which is good for performance. It means if you have 5 tabs open it won't really be different than one tab
// The clients can just ignore files they don't care about
-smol WebsocketMessageType {
- file_change = 1,
- build_success = 2,
- build_fail = 3,
+smol WebsocketMessageKind {
+ welcome = 1;
+ file_change_notification = 2;
+ build_success = 3;
+ build_fail = 4;
}
-struct WeboscketMessage {
+smol WebsocketCommandKind {
+ build = 1;
+}
+
+// Each websocket message has two messages in it!
+// This is the first.
+struct WebsocketMessage {
+ uint32 timestamp;
+ WebsocketMessageKind kind;
+}
+
+// This is the first.
+struct WebsocketMessageWelcome {
+ uint32 epoch;
+}
+
+struct WebsocketMessageFileChangeNotification {
+ uint32 id;
+ Loader loader;
+}
+
+struct WebsocketCommand {
+ WebsocketCommandKind kind;
+ uint32 timestamp;
+}
+
+// The timestamp is used for client-side deduping
+struct WebsocketCommandBuild {
+ uint32 id;
+}
+
+// We copy the module_path here incase they don't already have it
+struct WebsocketMessageBuildSuccess {
+ uint32 id;
+ uint32 from_timestamp;
+
+ Loader loader;
+ alphanumeric module_path;
+
+ Log log;
+ byte[] bytes;
+}
+
+struct WebsocketMessageBuildFailure {
+ uint32 id;
+ uint32 from_timestamp;
+ Loader loader;
+
+ alphanumeric module_path;
+ Log log;
+}
+
+
+
-} \ No newline at end of file
diff --git a/src/api/schema.zig b/src/api/schema.zig
index 319bc9b6f..106815345 100644
--- a/src/api/schema.zig
+++ b/src/api/schema.zig
@@ -1,4 +1,3 @@
-
const std = @import("std");
pub const Reader = struct {
@@ -280,1057 +279,1201 @@ pub fn Writer(comptime WritableStream: type) type {
pub const ByteWriter = Writer(std.io.FixedBufferStream([]u8));
pub const FileWriter = Writer(std.fs.File);
+pub const Api = struct {
+ pub const Loader = enum(u8) {
+ _none,
+ /// jsx
+ jsx,
+ /// js
+ js,
+ /// ts
+ ts,
-pub const Api = struct {
+ /// tsx
+ tsx,
-pub const Loader = enum(u8) {
+ /// css
+ css,
-_none,
- /// jsx
- jsx,
+ /// file
+ file,
- /// js
- js,
+ /// json
+ json,
- /// ts
- ts,
+ _,
- /// tsx
- tsx,
+ pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
+ return try std.json.stringify(@tagName(self), opts, o);
+ }
+ };
- /// css
- css,
+ pub const ResolveMode = enum(u8) {
+ _none,
+ /// disable
+ disable,
- /// file
- file,
+ /// lazy
+ lazy,
- /// json
- json,
+ /// dev
+ dev,
-_,
+ /// bundle
+ bundle,
- pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
- return try std.json.stringify(@tagName(self), opts, o);
- }
+ _,
-
-};
+ pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
+ return try std.json.stringify(@tagName(self), opts, o);
+ }
+ };
-pub const ResolveMode = enum(u8) {
+ pub const Platform = enum(u8) {
+ _none,
+ /// browser
+ browser,
-_none,
- /// disable
- disable,
+ /// node
+ node,
- /// lazy
- lazy,
+ _,
- /// dev
- dev,
+ pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
+ return try std.json.stringify(@tagName(self), opts, o);
+ }
+ };
- /// bundle
- bundle,
+ pub const JsxRuntime = enum(u8) {
+ _none,
+ /// automatic
+ automatic,
-_,
+ /// classic
+ classic,
- pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
- return try std.json.stringify(@tagName(self), opts, o);
- }
+ _,
-
-};
+ pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
+ return try std.json.stringify(@tagName(self), opts, o);
+ }
+ };
-pub const Platform = enum(u8) {
+ pub const Jsx = struct {
+ /// factory
+ factory: []const u8,
-_none,
- /// browser
- browser,
+ /// runtime
+ runtime: JsxRuntime,
- /// node
- node,
+ /// fragment
+ fragment: []const u8,
-_,
+ /// development
+ development: bool = false,
- pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
- return try std.json.stringify(@tagName(self), opts, o);
- }
+ /// import_source
+ import_source: []const u8,
-
-};
+ /// react_fast_refresh
+ react_fast_refresh: bool = false,
-pub const JsxRuntime = enum(u8) {
+ pub fn decode(reader: anytype) anyerror!Jsx {
+ var this = std.mem.zeroes(Jsx);
-_none,
- /// automatic
- automatic,
+ this.factory = try reader.readValue([]const u8);
+ this.runtime = try reader.readValue(JsxRuntime);
+ this.fragment = try reader.readValue([]const u8);
+ this.development = try reader.readValue(bool);
+ this.import_source = try reader.readValue([]const u8);
+ this.react_fast_refresh = try reader.readValue(bool);
+ return this;
+ }
- /// classic
- classic,
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeValue(this.factory);
+ try writer.writeEnum(this.runtime);
+ try writer.writeValue(this.fragment);
+ try writer.writeInt(@intCast(u8, @boolToInt(this.development)));
+ try writer.writeValue(this.import_source);
+ try writer.writeInt(@intCast(u8, @boolToInt(this.react_fast_refresh)));
+ }
+ };
-_,
+ pub const StringPointer = packed struct {
+ /// offset
+ offset: u32 = 0,
- pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
- return try std.json.stringify(@tagName(self), opts, o);
- }
+ /// length
+ length: u32 = 0,
-
-};
+ pub fn decode(reader: anytype) anyerror!StringPointer {
+ var this = std.mem.zeroes(StringPointer);
-pub const Jsx = struct {
-/// factory
-factory: []const u8,
+ this.offset = try reader.readValue(u32);
+ this.length = try reader.readValue(u32);
+ return this;
+ }
-/// runtime
-runtime: JsxRuntime,
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeInt(this.offset);
+ try writer.writeInt(this.length);
+ }
+ };
-/// fragment
-fragment: []const u8,
+ pub const JavascriptBundledModule = struct {
+ /// path
+ path: StringPointer,
-/// development
-development: bool = false,
+ /// code
+ code: StringPointer,
-/// import_source
-import_source: []const u8,
+ /// package_id
+ package_id: u32 = 0,
-/// react_fast_refresh
-react_fast_refresh: bool = false,
+ /// id
+ id: u32 = 0,
+ /// path_extname_length
+ path_extname_length: u8 = 0,
-pub fn decode(reader: anytype) anyerror!Jsx {
- var this = std.mem.zeroes(Jsx);
+ pub fn decode(reader: anytype) anyerror!JavascriptBundledModule {
+ var this = std.mem.zeroes(JavascriptBundledModule);
- this.factory = try reader.readValue([]const u8);
- this.runtime = try reader.readValue(JsxRuntime);
- this.fragment = try reader.readValue([]const u8);
- this.development = try reader.readValue(bool);
- this.import_source = try reader.readValue([]const u8);
- this.react_fast_refresh = try reader.readValue(bool);
- return this;
-}
+ this.path = try reader.readValue(StringPointer);
+ this.code = try reader.readValue(StringPointer);
+ this.package_id = try reader.readValue(u32);
+ this.id = try reader.readValue(u32);
+ this.path_extname_length = try reader.readValue(u8);
+ return this;
+ }
-pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeValue(this.factory);
- try writer.writeEnum(this.runtime);
- try writer.writeValue(this.fragment);
- try writer.writeInt(@intCast(u8, @boolToInt(this.development)));
- try writer.writeValue(this.import_source);
- try writer.writeInt(@intCast(u8, @boolToInt(this.react_fast_refresh)));
-}
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeValue(this.path);
+ try writer.writeValue(this.code);
+ try writer.writeInt(this.package_id);
+ try writer.writeInt(this.id);
+ try writer.writeInt(this.path_extname_length);
+ }
+ };
-};
+ pub const JavascriptBundledPackage = struct {
+ /// name
+ name: StringPointer,
-pub const StringPointer = packed struct {
-/// offset
-offset: u32 = 0,
+ /// version
+ version: StringPointer,
-/// length
-length: u32 = 0,
+ /// hash
+ hash: u32 = 0,
+ /// modules_offset
+ modules_offset: u32 = 0,
-pub fn decode(reader: anytype) anyerror!StringPointer {
- var this = std.mem.zeroes(StringPointer);
+ /// modules_length
+ modules_length: u32 = 0,
- this.offset = try reader.readValue(u32);
- this.length = try reader.readValue(u32);
- return this;
-}
+ pub fn decode(reader: anytype) anyerror!JavascriptBundledPackage {
+ var this = std.mem.zeroes(JavascriptBundledPackage);
-pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeInt(this.offset);
- try writer.writeInt(this.length);
-}
+ this.name = try reader.readValue(StringPointer);
+ this.version = try reader.readValue(StringPointer);
+ this.hash = try reader.readValue(u32);
+ this.modules_offset = try reader.readValue(u32);
+ this.modules_length = try reader.readValue(u32);
+ return this;
+ }
-};
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeValue(this.name);
+ try writer.writeValue(this.version);
+ try writer.writeInt(this.hash);
+ try writer.writeInt(this.modules_offset);
+ try writer.writeInt(this.modules_length);
+ }
+ };
-pub const JavascriptBundledModule = struct {
-/// path
-path: StringPointer,
+ pub const JavascriptBundle = struct {
+ /// modules
+ modules: []const JavascriptBundledModule,
-/// code
-code: StringPointer,
+ /// packages
+ packages: []const JavascriptBundledPackage,
-/// package_id
-package_id: u32 = 0,
+ /// etag
+ etag: []const u8,
-/// id
-id: u32 = 0,
+ /// generated_at
+ generated_at: u32 = 0,
-/// path_extname_length
-path_extname_length: u8 = 0,
+ /// app_package_json_dependencies_hash
+ app_package_json_dependencies_hash: []const u8,
+ /// import_from_name
+ import_from_name: []const u8,
-pub fn decode(reader: anytype) anyerror!JavascriptBundledModule {
- var this = std.mem.zeroes(JavascriptBundledModule);
+ /// manifest_string
+ manifest_string: []const u8,
- this.path = try reader.readValue(StringPointer);
- this.code = try reader.readValue(StringPointer);
- this.package_id = try reader.readValue(u32);
- this.id = try reader.readValue(u32);
- this.path_extname_length = try reader.readValue(u8);
- return this;
-}
+ pub fn decode(reader: anytype) anyerror!JavascriptBundle {
+ var this = std.mem.zeroes(JavascriptBundle);
-pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeValue(this.path);
- try writer.writeValue(this.code);
- try writer.writeInt(this.package_id);
- try writer.writeInt(this.id);
- try writer.writeInt(this.path_extname_length);
-}
+ this.modules = try reader.readArray(JavascriptBundledModule);
+ this.packages = try reader.readArray(JavascriptBundledPackage);
+ this.etag = try reader.readArray(u8);
+ this.generated_at = try reader.readValue(u32);
+ this.app_package_json_dependencies_hash = try reader.readArray(u8);
+ this.import_from_name = try reader.readArray(u8);
+ this.manifest_string = try reader.readArray(u8);
+ return this;
+ }
-};
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeArray(JavascriptBundledModule, this.modules);
+ try writer.writeArray(JavascriptBundledPackage, this.packages);
+ try writer.writeArray(u8, this.etag);
+ try writer.writeInt(this.generated_at);
+ try writer.writeArray(u8, this.app_package_json_dependencies_hash);
+ try writer.writeArray(u8, this.import_from_name);
+ try writer.writeArray(u8, this.manifest_string);
+ }
+ };
-pub const JavascriptBundledPackage = struct {
-/// name
-name: StringPointer,
+ pub const JavascriptBundleContainer = struct {
+ /// bundle_format_version
+ bundle_format_version: ?u32 = null,
-/// version
-version: StringPointer,
+ /// bundle
+ bundle: ?JavascriptBundle = null,
-/// hash
-hash: u32 = 0,
+ /// code_length
+ code_length: ?u32 = null,
-/// modules_offset
-modules_offset: u32 = 0,
+ pub fn decode(reader: anytype) anyerror!JavascriptBundleContainer {
+ var this = std.mem.zeroes(JavascriptBundleContainer);
-/// modules_length
-modules_length: u32 = 0,
+ while (true) {
+ switch (try reader.readByte()) {
+ 0 => {
+ return this;
+ },
+ 1 => {
+ this.bundle_format_version = try reader.readValue(u32);
+ },
+ 2 => {
+ this.bundle = try reader.readValue(JavascriptBundle);
+ },
+ 3 => {
+ this.code_length = try reader.readValue(u32);
+ },
+ else => {
+ return error.InvalidMessage;
+ },
+ }
+ }
+ unreachable;
+ }
-pub fn decode(reader: anytype) anyerror!JavascriptBundledPackage {
- var this = std.mem.zeroes(JavascriptBundledPackage);
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ if (this.bundle_format_version) |bundle_format_version| {
+ try writer.writeFieldID(1);
+ try writer.writeInt(bundle_format_version);
+ }
+ if (this.bundle) |bundle| {
+ try writer.writeFieldID(2);
+ try writer.writeValue(bundle);
+ }
+ if (this.code_length) |code_length| {
+ try writer.writeFieldID(3);
+ try writer.writeInt(code_length);
+ }
+ try writer.endMessage();
+ }
+ };
- this.name = try reader.readValue(StringPointer);
- this.version = try reader.readValue(StringPointer);
- this.hash = try reader.readValue(u32);
- this.modules_offset = try reader.readValue(u32);
- this.modules_length = try reader.readValue(u32);
- return this;
-}
+ pub const ScanDependencyMode = enum(u8) {
+ _none,
+ /// app
+ app,
-pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeValue(this.name);
- try writer.writeValue(this.version);
- try writer.writeInt(this.hash);
- try writer.writeInt(this.modules_offset);
- try writer.writeInt(this.modules_length);
-}
+ /// all
+ all,
-};
+ _,
-pub const JavascriptBundle = struct {
-/// modules
-modules: []const JavascriptBundledModule,
+ pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
+ return try std.json.stringify(@tagName(self), opts, o);
+ }
+ };
-/// packages
-packages: []const JavascriptBundledPackage,
+ pub const ModuleImportType = enum(u8) {
+ _none,
+ /// import
+ import,
-/// etag
-etag: []const u8,
+ /// require
+ require,
-/// generated_at
-generated_at: u32 = 0,
+ _,
-/// app_package_json_dependencies_hash
-app_package_json_dependencies_hash: []const u8,
+ pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
+ return try std.json.stringify(@tagName(self), opts, o);
+ }
+ };
-/// import_from_name
-import_from_name: []const u8,
+ pub const ModuleImportRecord = struct {
+ /// kind
+ kind: ModuleImportType,
-/// manifest_string
-manifest_string: []const u8,
+ /// path
+ path: []const u8,
+ /// dynamic
+ dynamic: bool = false,
-pub fn decode(reader: anytype) anyerror!JavascriptBundle {
- var this = std.mem.zeroes(JavascriptBundle);
+ pub fn decode(reader: anytype) anyerror!ModuleImportRecord {
+ var this = std.mem.zeroes(ModuleImportRecord);
- this.modules = try reader.readArray(JavascriptBundledModule);
- this.packages = try reader.readArray(JavascriptBundledPackage);
- this.etag = try reader.readArray(u8);
- this.generated_at = try reader.readValue(u32);
- this.app_package_json_dependencies_hash = try reader.readArray(u8);
- this.import_from_name = try reader.readArray(u8);
- this.manifest_string = try reader.readArray(u8);
- return this;
-}
+ this.kind = try reader.readValue(ModuleImportType);
+ this.path = try reader.readValue([]const u8);
+ this.dynamic = try reader.readValue(bool);
+ return this;
+ }
-pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeArray(JavascriptBundledModule, this.modules);
- try writer.writeArray(JavascriptBundledPackage, this.packages);
- try writer.writeArray(u8, this.etag);
- try writer.writeInt(this.generated_at);
- try writer.writeArray(u8, this.app_package_json_dependencies_hash);
- try writer.writeArray(u8, this.import_from_name);
- try writer.writeArray(u8, this.manifest_string);
-}
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeEnum(this.kind);
+ try writer.writeValue(this.path);
+ try writer.writeInt(@intCast(u8, @boolToInt(this.dynamic)));
+ }
+ };
-};
+ pub const Module = struct {
+ /// path
+ path: []const u8,
-pub const JavascriptBundleContainer = struct {
-/// bundle_format_version
-bundle_format_version: ?u32 = null,
-
-/// bundle
-bundle: ?JavascriptBundle = null,
-
-/// code_length
-code_length: ?u32 = null,
-
-
-pub fn decode(reader: anytype) anyerror!JavascriptBundleContainer {
- var this = std.mem.zeroes(JavascriptBundleContainer);
-
- while(true) {
- switch (try reader.readByte()) {
- 0 => { return this; },
-
- 1 => {
- this.bundle_format_version = try reader.readValue(u32);
-},
- 2 => {
- this.bundle = try reader.readValue(JavascriptBundle);
-},
- 3 => {
- this.code_length = try reader.readValue(u32);
-},
- else => {
- return error.InvalidMessage;
- },
- }
- }
-unreachable;
-}
+ /// imports
+ imports: []const ModuleImportRecord,
-pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
-if (this.bundle_format_version) |bundle_format_version| {
- try writer.writeFieldID(1);
- try writer.writeInt(bundle_format_version);
-}
-if (this.bundle) |bundle| {
- try writer.writeFieldID(2);
- try writer.writeValue(bundle);
-}
-if (this.code_length) |code_length| {
- try writer.writeFieldID(3);
- try writer.writeInt(code_length);
-}
-try writer.endMessage();
-}
+ pub fn decode(reader: anytype) anyerror!Module {
+ var this = std.mem.zeroes(Module);
-};
+ this.path = try reader.readValue([]const u8);
+ this.imports = try reader.readArray(ModuleImportRecord);
+ return this;
+ }
-pub const ScanDependencyMode = enum(u8) {
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeValue(this.path);
+ try writer.writeArray(ModuleImportRecord, this.imports);
+ }
+ };
-_none,
- /// app
- app,
+ pub const StringMap = struct {
+ /// keys
+ keys: []const []const u8,
- /// all
- all,
+ /// values
+ values: []const []const u8,
-_,
+ pub fn decode(reader: anytype) anyerror!StringMap {
+ var this = std.mem.zeroes(StringMap);
- pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
- return try std.json.stringify(@tagName(self), opts, o);
- }
+ this.keys = try reader.readArray([]const u8);
+ this.values = try reader.readArray([]const u8);
+ return this;
+ }
-
-};
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeArray([]const u8, this.keys);
+ try writer.writeArray([]const u8, this.values);
+ }
+ };
+
+ pub const LoaderMap = struct {
+ /// extensions
+ extensions: []const []const u8,
+
+ /// loaders
+ loaders: []const Loader,
+
+ pub fn decode(reader: anytype) anyerror!LoaderMap {
+ var this = std.mem.zeroes(LoaderMap);
+
+ this.extensions = try reader.readArray([]const u8);
+ this.loaders = try reader.readArray(Loader);
+ return this;
+ }
+
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeArray([]const u8, this.extensions);
+ try writer.writeArray(Loader, this.loaders);
+ }
+ };
+
+ pub const TransformOptions = struct {
+ /// jsx
+ jsx: ?Jsx = null,
+
+ /// tsconfig_override
+ tsconfig_override: ?[]const u8 = null,
+
+ /// resolve
+ resolve: ?ResolveMode = null,
+
+ /// public_url
+ public_url: ?[]const u8 = null,
+
+ /// absolute_working_dir
+ absolute_working_dir: ?[]const u8 = null,
+
+ /// define
+ define: ?StringMap = null,
+
+ /// preserve_symlinks
+ preserve_symlinks: ?bool = null,
+
+ /// entry_points
+ entry_points: []const []const u8,
+
+ /// write
+ write: ?bool = null,
-pub const ModuleImportType = enum(u8) {
+ /// inject
+ inject: []const []const u8,
-_none,
- /// import
- import,
+ /// output_dir
+ output_dir: ?[]const u8 = null,
- /// require
- require,
+ /// external
+ external: []const []const u8,
-_,
+ /// loaders
+ loaders: ?LoaderMap = null,
- pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
- return try std.json.stringify(@tagName(self), opts, o);
+ /// main_fields
+ main_fields: []const []const u8,
+
+ /// platform
+ platform: ?Platform = null,
+
+ /// serve
+ serve: ?bool = null,
+
+ /// extension_order
+ extension_order: []const []const u8,
+
+ /// public_dir
+ public_dir: ?[]const u8 = null,
+
+ /// only_scan_dependencies
+ only_scan_dependencies: ?ScanDependencyMode = null,
+
+ /// generate_node_module_bundle
+ generate_node_module_bundle: ?bool = null,
+
+ /// node_modules_bundle_path
+ node_modules_bundle_path: ?[]const u8 = null,
+
+ pub fn decode(reader: anytype) anyerror!TransformOptions {
+ var this = std.mem.zeroes(TransformOptions);
+
+ while (true) {
+ switch (try reader.readByte()) {
+ 0 => {
+ return this;
+ },
+
+ 1 => {
+ this.jsx = try reader.readValue(Jsx);
+ },
+ 2 => {
+ this.tsconfig_override = try reader.readValue([]const u8);
+ },
+ 3 => {
+ this.resolve = try reader.readValue(ResolveMode);
+ },
+ 4 => {
+ this.public_url = try reader.readValue([]const u8);
+ },
+ 5 => {
+ this.absolute_working_dir = try reader.readValue([]const u8);
+ },
+ 6 => {
+ this.define = try reader.readValue(StringMap);
+ },
+ 7 => {
+ this.preserve_symlinks = try reader.readValue(bool);
+ },
+ 8 => {
+ this.entry_points = try reader.readArray([]const u8);
+ },
+ 9 => {
+ this.write = try reader.readValue(bool);
+ },
+ 10 => {
+ this.inject = try reader.readArray([]const u8);
+ },
+ 11 => {
+ this.output_dir = try reader.readValue([]const u8);
+ },
+ 12 => {
+ this.external = try reader.readArray([]const u8);
+ },
+ 13 => {
+ this.loaders = try reader.readValue(LoaderMap);
+ },
+ 14 => {
+ this.main_fields = try reader.readArray([]const u8);
+ },
+ 15 => {
+ this.platform = try reader.readValue(Platform);
+ },
+ 16 => {
+ this.serve = try reader.readValue(bool);
+ },
+ 17 => {
+ this.extension_order = try reader.readArray([]const u8);
+ },
+ 18 => {
+ this.public_dir = try reader.readValue([]const u8);
+ },
+ 19 => {
+ this.only_scan_dependencies = try reader.readValue(ScanDependencyMode);
+ },
+ 20 => {
+ this.generate_node_module_bundle = try reader.readValue(bool);
+ },
+ 21 => {
+ this.node_modules_bundle_path = try reader.readValue([]const u8);
+ },
+ else => {
+ return error.InvalidMessage;
+ },
}
+ }
+ unreachable;
+ }
-
-};
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ if (this.jsx) |jsx| {
+ try writer.writeFieldID(1);
+ try writer.writeValue(jsx);
+ }
+ if (this.tsconfig_override) |tsconfig_override| {
+ try writer.writeFieldID(2);
+ try writer.writeValue(tsconfig_override);
+ }
+ if (this.resolve) |resolve| {
+ try writer.writeFieldID(3);
+ try writer.writeEnum(resolve);
+ }
+ if (this.public_url) |public_url| {
+ try writer.writeFieldID(4);
+ try writer.writeValue(public_url);
+ }
+ if (this.absolute_working_dir) |absolute_working_dir| {
+ try writer.writeFieldID(5);
+ try writer.writeValue(absolute_working_dir);
+ }
+ if (this.define) |define| {
+ try writer.writeFieldID(6);
+ try writer.writeValue(define);
+ }
+ if (this.preserve_symlinks) |preserve_symlinks| {
+ try writer.writeFieldID(7);
+ try writer.writeInt(@intCast(u8, @boolToInt(preserve_symlinks)));
+ }
+ if (this.entry_points) |entry_points| {
+ try writer.writeFieldID(8);
+ try writer.writeArray([]const u8, entry_points);
+ }
+ if (this.write) |write| {
+ try writer.writeFieldID(9);
+ try writer.writeInt(@intCast(u8, @boolToInt(write)));
+ }
+ if (this.inject) |inject| {
+ try writer.writeFieldID(10);
+ try writer.writeArray([]const u8, inject);
+ }
+ if (this.output_dir) |output_dir| {
+ try writer.writeFieldID(11);
+ try writer.writeValue(output_dir);
+ }
+ if (this.external) |external| {
+ try writer.writeFieldID(12);
+ try writer.writeArray([]const u8, external);
+ }
+ if (this.loaders) |loaders| {
+ try writer.writeFieldID(13);
+ try writer.writeValue(loaders);
+ }
+ if (this.main_fields) |main_fields| {
+ try writer.writeFieldID(14);
+ try writer.writeArray([]const u8, main_fields);
+ }
+ if (this.platform) |platform| {
+ try writer.writeFieldID(15);
+ try writer.writeEnum(platform);
+ }
+ if (this.serve) |serve| {
+ try writer.writeFieldID(16);
+ try writer.writeInt(@intCast(u8, @boolToInt(serve)));
+ }
+ if (this.extension_order) |extension_order| {
+ try writer.writeFieldID(17);
+ try writer.writeArray([]const u8, extension_order);
+ }
+ if (this.public_dir) |public_dir| {
+ try writer.writeFieldID(18);
+ try writer.writeValue(public_dir);
+ }
+ if (this.only_scan_dependencies) |only_scan_dependencies| {
+ try writer.writeFieldID(19);
+ try writer.writeEnum(only_scan_dependencies);
+ }
+ if (this.generate_node_module_bundle) |generate_node_module_bundle| {
+ try writer.writeFieldID(20);
+ try writer.writeInt(@intCast(u8, @boolToInt(generate_node_module_bundle)));
+ }
+ if (this.node_modules_bundle_path) |node_modules_bundle_path| {
+ try writer.writeFieldID(21);
+ try writer.writeValue(node_modules_bundle_path);
+ }
+ try writer.endMessage();
+ }
+ };
-pub const ModuleImportRecord = struct {
-/// kind
-kind: ModuleImportType,
+ pub const FileHandle = struct {
+ /// path
+ path: []const u8,
-/// path
-path: []const u8,
+ /// size
+ size: u32 = 0,
-/// dynamic
-dynamic: bool = false,
+ /// fd
+ fd: u32 = 0,
+ pub fn decode(reader: anytype) anyerror!FileHandle {
+ var this = std.mem.zeroes(FileHandle);
-pub fn decode(reader: anytype) anyerror!ModuleImportRecord {
- var this = std.mem.zeroes(ModuleImportRecord);
+ this.path = try reader.readValue([]const u8);
+ this.size = try reader.readValue(u32);
+ this.fd = try reader.readValue(u32);
+ return this;
+ }
- this.kind = try reader.readValue(ModuleImportType);
- this.path = try reader.readValue([]const u8);
- this.dynamic = try reader.readValue(bool);
- return this;
-}
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeValue(this.path);
+ try writer.writeInt(this.size);
+ try writer.writeInt(this.fd);
+ }
+ };
-pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeEnum(this.kind);
- try writer.writeValue(this.path);
- try writer.writeInt(@intCast(u8, @boolToInt(this.dynamic)));
-}
+ pub const Transform = struct {
+ /// handle
+ handle: ?FileHandle = null,
-};
+ /// path
+ path: ?[]const u8 = null,
-pub const Module = struct {
-/// path
-path: []const u8,
+ /// contents
+ contents: []const u8,
-/// imports
-imports: []const ModuleImportRecord,
+ /// loader
+ loader: ?Loader = null,
+ /// options
+ options: ?TransformOptions = null,
-pub fn decode(reader: anytype) anyerror!Module {
- var this = std.mem.zeroes(Module);
+ pub fn decode(reader: anytype) anyerror!Transform {
+ var this = std.mem.zeroes(Transform);
- this.path = try reader.readValue([]const u8);
- this.imports = try reader.readArray(ModuleImportRecord);
- return this;
-}
+ while (true) {
+ switch (try reader.readByte()) {
+ 0 => {
+ return this;
+ },
-pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeValue(this.path);
- try writer.writeArray(ModuleImportRecord, this.imports);
-}
+ 1 => {
+ this.handle = try reader.readValue(FileHandle);
+ },
+ 2 => {
+ this.path = try reader.readValue([]const u8);
+ },
+ 3 => {
+ this.contents = try reader.readArray(u8);
+ },
+ 4 => {
+ this.loader = try reader.readValue(Loader);
+ },
+ 5 => {
+ this.options = try reader.readValue(TransformOptions);
+ },
+ else => {
+ return error.InvalidMessage;
+ },
+ }
+ }
+ unreachable;
+ }
-};
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ if (this.handle) |handle| {
+ try writer.writeFieldID(1);
+ try writer.writeValue(handle);
+ }
+ if (this.path) |path| {
+ try writer.writeFieldID(2);
+ try writer.writeValue(path);
+ }
+ if (this.contents) |contents| {
+ try writer.writeFieldID(3);
+ try writer.writeArray(u8, contents);
+ }
+ if (this.loader) |loader| {
+ try writer.writeFieldID(4);
+ try writer.writeEnum(loader);
+ }
+ if (this.options) |options| {
+ try writer.writeFieldID(5);
+ try writer.writeValue(options);
+ }
+ try writer.endMessage();
+ }
+ };
-pub const StringMap = struct {
-/// keys
-keys: []const []const u8,
+ pub const TransformResponseStatus = enum(u32) {
+ _none,
+ /// success
+ success,
-/// values
-values: []const []const u8,
+ /// fail
+ fail,
+ _,
-pub fn decode(reader: anytype) anyerror!StringMap {
- var this = std.mem.zeroes(StringMap);
+ pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
+ return try std.json.stringify(@tagName(self), opts, o);
+ }
+ };
- this.keys = try reader.readArray([]const u8);
- this.values = try reader.readArray([]const u8);
- return this;
-}
+ pub const OutputFile = struct {
+ /// data
+ data: []const u8,
-pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeArray([]const u8, this.keys);
- try writer.writeArray([]const u8, this.values);
-}
+ /// path
+ path: []const u8,
-};
+ pub fn decode(reader: anytype) anyerror!OutputFile {
+ var this = std.mem.zeroes(OutputFile);
-pub const LoaderMap = struct {
-/// extensions
-extensions: []const []const u8,
+ this.data = try reader.readArray(u8);
+ this.path = try reader.readValue([]const u8);
+ return this;
+ }
-/// loaders
-loaders: []const Loader,
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeArray(u8, this.data);
+ try writer.writeValue(this.path);
+ }
+ };
+ pub const TransformResponse = struct {
+ /// status
+ status: TransformResponseStatus,
-pub fn decode(reader: anytype) anyerror!LoaderMap {
- var this = std.mem.zeroes(LoaderMap);
+ /// files
+ files: []const OutputFile,
- this.extensions = try reader.readArray([]const u8);
- this.loaders = try reader.readArray(Loader);
- return this;
-}
+ /// errors
+ errors: []const Message,
-pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeArray([]const u8, this.extensions);
- try writer.writeArray(Loader, this.loaders);
-}
+ pub fn decode(reader: anytype) anyerror!TransformResponse {
+ var this = std.mem.zeroes(TransformResponse);
-};
+ this.status = try reader.readValue(TransformResponseStatus);
+ this.files = try reader.readArray(OutputFile);
+ this.errors = try reader.readArray(Message);
+ return this;
+ }
-pub const TransformOptions = struct {
-/// jsx
-jsx: ?Jsx = null,
-
-/// tsconfig_override
-tsconfig_override: ?[]const u8 = null,
-
-/// resolve
-resolve: ?ResolveMode = null,
-
-/// public_url
-public_url: ?[]const u8 = null,
-
-/// absolute_working_dir
-absolute_working_dir: ?[]const u8 = null,
-
-/// define
-define: ?StringMap = null,
-
-/// preserve_symlinks
-preserve_symlinks: ?bool = null,
-
-/// entry_points
-entry_points: []const []const u8,
-
-/// write
-write: ?bool = null,
-
-/// inject
-inject: []const []const u8,
-
-/// output_dir
-output_dir: ?[]const u8 = null,
-
-/// external
-external: []const []const u8,
-
-/// loaders
-loaders: ?LoaderMap = null,
-
-/// main_fields
-main_fields: []const []const u8,
-
-/// platform
-platform: ?Platform = null,
-
-/// serve
-serve: ?bool = null,
-
-/// extension_order
-extension_order: []const []const u8,
-
-/// public_dir
-public_dir: ?[]const u8 = null,
-
-/// only_scan_dependencies
-only_scan_dependencies: ?ScanDependencyMode = null,
-
-/// generate_node_module_bundle
-generate_node_module_bundle: ?bool = null,
-
-/// node_modules_bundle_path
-node_modules_bundle_path: ?[]const u8 = null,
-
-
-pub fn decode(reader: anytype) anyerror!TransformOptions {
- var this = std.mem.zeroes(TransformOptions);
-
- while(true) {
- switch (try reader.readByte()) {
- 0 => { return this; },
-
- 1 => {
- this.jsx = try reader.readValue(Jsx);
-},
- 2 => {
- this.tsconfig_override = try reader.readValue([]const u8);
-},
- 3 => {
- this.resolve = try reader.readValue(ResolveMode);
-},
- 4 => {
- this.public_url = try reader.readValue([]const u8);
-},
- 5 => {
- this.absolute_working_dir = try reader.readValue([]const u8);
-},
- 6 => {
- this.define = try reader.readValue(StringMap);
-},
- 7 => {
- this.preserve_symlinks = try reader.readValue(bool);
-},
- 8 => {
- this.entry_points = try reader.readArray([]const u8);
-},
- 9 => {
- this.write = try reader.readValue(bool);
-},
- 10 => {
- this.inject = try reader.readArray([]const u8);
-},
- 11 => {
- this.output_dir = try reader.readValue([]const u8);
-},
- 12 => {
- this.external = try reader.readArray([]const u8);
-},
- 13 => {
- this.loaders = try reader.readValue(LoaderMap);
-},
- 14 => {
- this.main_fields = try reader.readArray([]const u8);
-},
- 15 => {
- this.platform = try reader.readValue(Platform);
-},
- 16 => {
- this.serve = try reader.readValue(bool);
-},
- 17 => {
- this.extension_order = try reader.readArray([]const u8);
-},
- 18 => {
- this.public_dir = try reader.readValue([]const u8);
-},
- 19 => {
- this.only_scan_dependencies = try reader.readValue(ScanDependencyMode);
-},
- 20 => {
- this.generate_node_module_bundle = try reader.readValue(bool);
-},
- 21 => {
- this.node_modules_bundle_path = try reader.readValue([]const u8);
-},
- else => {
- return error.InvalidMessage;
- },
- }
- }
-unreachable;
-}
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeEnum(this.status);
+ try writer.writeArray(OutputFile, this.files);
+ try writer.writeArray(Message, this.errors);
+ }
+ };
-pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
-if (this.jsx) |jsx| {
- try writer.writeFieldID(1);
- try writer.writeValue(jsx);
-}
-if (this.tsconfig_override) |tsconfig_override| {
- try writer.writeFieldID(2);
- try writer.writeValue(tsconfig_override);
-}
-if (this.resolve) |resolve| {
- try writer.writeFieldID(3);
- try writer.writeEnum(resolve);
-}
-if (this.public_url) |public_url| {
- try writer.writeFieldID(4);
- try writer.writeValue(public_url);
-}
-if (this.absolute_working_dir) |absolute_working_dir| {
- try writer.writeFieldID(5);
- try writer.writeValue(absolute_working_dir);
-}
-if (this.define) |define| {
- try writer.writeFieldID(6);
- try writer.writeValue(define);
-}
-if (this.preserve_symlinks) |preserve_symlinks| {
- try writer.writeFieldID(7);
- try writer.writeInt(@intCast(u8, @boolToInt(preserve_symlinks)));
-}
-if (this.entry_points) |entry_points| {
- try writer.writeFieldID(8);
- try writer.writeArray([]const u8, entry_points);
-}
-if (this.write) |write| {
- try writer.writeFieldID(9);
- try writer.writeInt(@intCast(u8, @boolToInt(write)));
-}
-if (this.inject) |inject| {
- try writer.writeFieldID(10);
- try writer.writeArray([]const u8, inject);
-}
-if (this.output_dir) |output_dir| {
- try writer.writeFieldID(11);
- try writer.writeValue(output_dir);
-}
-if (this.external) |external| {
- try writer.writeFieldID(12);
- try writer.writeArray([]const u8, external);
-}
-if (this.loaders) |loaders| {
- try writer.writeFieldID(13);
- try writer.writeValue(loaders);
-}
-if (this.main_fields) |main_fields| {
- try writer.writeFieldID(14);
- try writer.writeArray([]const u8, main_fields);
-}
-if (this.platform) |platform| {
- try writer.writeFieldID(15);
- try writer.writeEnum(platform);
-}
-if (this.serve) |serve| {
- try writer.writeFieldID(16);
- try writer.writeInt(@intCast(u8, @boolToInt(serve)));
-}
-if (this.extension_order) |extension_order| {
- try writer.writeFieldID(17);
- try writer.writeArray([]const u8, extension_order);
-}
-if (this.public_dir) |public_dir| {
- try writer.writeFieldID(18);
- try writer.writeValue(public_dir);
-}
-if (this.only_scan_dependencies) |only_scan_dependencies| {
- try writer.writeFieldID(19);
- try writer.writeEnum(only_scan_dependencies);
-}
-if (this.generate_node_module_bundle) |generate_node_module_bundle| {
- try writer.writeFieldID(20);
- try writer.writeInt(@intCast(u8, @boolToInt(generate_node_module_bundle)));
-}
-if (this.node_modules_bundle_path) |node_modules_bundle_path| {
- try writer.writeFieldID(21);
- try writer.writeValue(node_modules_bundle_path);
-}
-try writer.endMessage();
-}
+ pub const MessageKind = enum(u32) {
+ _none,
+ /// err
+ err,
-};
+ /// warn
+ warn,
-pub const FileHandle = struct {
-/// path
-path: []const u8,
+ /// note
+ note,
-/// size
-size: u32 = 0,
+ /// debug
+ debug,
-/// fd
-fd: u32 = 0,
+ _,
+ pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
+ return try std.json.stringify(@tagName(self), opts, o);
+ }
+ };
-pub fn decode(reader: anytype) anyerror!FileHandle {
- var this = std.mem.zeroes(FileHandle);
+ pub const Location = struct {
+ /// file
+ file: []const u8,
- this.path = try reader.readValue([]const u8);
- this.size = try reader.readValue(u32);
- this.fd = try reader.readValue(u32);
- return this;
-}
+ /// namespace
+ namespace: []const u8,
-pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeValue(this.path);
- try writer.writeInt(this.size);
- try writer.writeInt(this.fd);
-}
+ /// line
+ line: i32 = 0,
-};
+ /// column
+ column: i32 = 0,
-pub const Transform = struct {
-/// handle
-handle: ?FileHandle = null,
-
-/// path
-path: ?[]const u8 = null,
-
-/// contents
-contents: []const u8,
-
-/// loader
-loader: ?Loader = null,
-
-/// options
-options: ?TransformOptions = null,
-
-
-pub fn decode(reader: anytype) anyerror!Transform {
- var this = std.mem.zeroes(Transform);
-
- while(true) {
- switch (try reader.readByte()) {
- 0 => { return this; },
-
- 1 => {
- this.handle = try reader.readValue(FileHandle);
-},
- 2 => {
- this.path = try reader.readValue([]const u8);
-},
- 3 => {
- this.contents = try reader.readArray(u8);
-},
- 4 => {
- this.loader = try reader.readValue(Loader);
-},
- 5 => {
- this.options = try reader.readValue(TransformOptions);
-},
- else => {
- return error.InvalidMessage;
- },
- }
- }
-unreachable;
-}
+ /// line_text
+ line_text: []const u8,
-pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
-if (this.handle) |handle| {
- try writer.writeFieldID(1);
- try writer.writeValue(handle);
-}
-if (this.path) |path| {
- try writer.writeFieldID(2);
- try writer.writeValue(path);
-}
-if (this.contents) |contents| {
- try writer.writeFieldID(3);
- try writer.writeArray(u8, contents);
-}
-if (this.loader) |loader| {
- try writer.writeFieldID(4);
- try writer.writeEnum(loader);
-}
-if (this.options) |options| {
- try writer.writeFieldID(5);
- try writer.writeValue(options);
-}
-try writer.endMessage();
-}
+ /// suggestion
+ suggestion: []const u8,
-};
+ /// offset
+ offset: u32 = 0,
+
+ pub fn decode(reader: anytype) anyerror!Location {
+ var this = std.mem.zeroes(Location);
+
+ this.file = try reader.readValue([]const u8);
+ this.namespace = try reader.readValue([]const u8);
+ this.line = try reader.readValue(i32);
+ this.column = try reader.readValue(i32);
+ this.line_text = try reader.readValue([]const u8);
+ this.suggestion = try reader.readValue([]const u8);
+ this.offset = try reader.readValue(u32);
+ return this;
+ }
+
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeValue(this.file);
+ try writer.writeValue(this.namespace);
+ try writer.writeInt(this.line);
+ try writer.writeInt(this.column);
+ try writer.writeValue(this.line_text);
+ try writer.writeValue(this.suggestion);
+ try writer.writeInt(this.offset);
+ }
+ };
-pub const TransformResponseStatus = enum(u32) {
+ pub const MessageData = struct {
+ /// text
+ text: ?[]const u8 = null,
-_none,
- /// success
- success,
+ /// location
+ location: ?Location = null,
- /// fail
- fail,
+ pub fn decode(reader: anytype) anyerror!MessageData {
+ var this = std.mem.zeroes(MessageData);
-_,
+ while (true) {
+ switch (try reader.readByte()) {
+ 0 => {
+ return this;
+ },
- pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
- return try std.json.stringify(@tagName(self), opts, o);
+ 1 => {
+ this.text = try reader.readValue([]const u8);
+ },
+ 2 => {
+ this.location = try reader.readValue(Location);
+ },
+ else => {
+ return error.InvalidMessage;
+ },
}
+ }
+ unreachable;
+ }
-
-};
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ if (this.text) |text| {
+ try writer.writeFieldID(1);
+ try writer.writeValue(text);
+ }
+ if (this.location) |location| {
+ try writer.writeFieldID(2);
+ try writer.writeValue(location);
+ }
+ try writer.endMessage();
+ }
+ };
-pub const OutputFile = struct {
-/// data
-data: []const u8,
+ pub const Message = struct {
+ /// kind
+ kind: MessageKind,
-/// path
-path: []const u8,
+ /// data
+ data: MessageData,
+ /// notes
+ notes: []const MessageData,
-pub fn decode(reader: anytype) anyerror!OutputFile {
- var this = std.mem.zeroes(OutputFile);
+ pub fn decode(reader: anytype) anyerror!Message {
+ var this = std.mem.zeroes(Message);
- this.data = try reader.readArray(u8);
- this.path = try reader.readValue([]const u8);
- return this;
-}
+ this.kind = try reader.readValue(MessageKind);
+ this.data = try reader.readValue(MessageData);
+ this.notes = try reader.readArray(MessageData);
+ return this;
+ }
-pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeArray(u8, this.data);
- try writer.writeValue(this.path);
-}
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeEnum(this.kind);
+ try writer.writeValue(this.data);
+ try writer.writeArray(MessageData, this.notes);
+ }
+ };
-};
+ pub const Log = struct {
+ /// warnings
+ warnings: u32 = 0,
-pub const TransformResponse = struct {
-/// status
-status: TransformResponseStatus,
+ /// errors
+ errors: u32 = 0,
-/// files
-files: []const OutputFile,
+ /// msgs
+ msgs: []const Message,
-/// errors
-errors: []const Message,
+ pub fn decode(reader: anytype) anyerror!Log {
+ var this = std.mem.zeroes(Log);
+ this.warnings = try reader.readValue(u32);
+ this.errors = try reader.readValue(u32);
+ this.msgs = try reader.readArray(Message);
+ return this;
+ }
-pub fn decode(reader: anytype) anyerror!TransformResponse {
- var this = std.mem.zeroes(TransformResponse);
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeInt(this.warnings);
+ try writer.writeInt(this.errors);
+ try writer.writeArray(Message, this.msgs);
+ }
+ };
- this.status = try reader.readValue(TransformResponseStatus);
- this.files = try reader.readArray(OutputFile);
- this.errors = try reader.readArray(Message);
- return this;
-}
+ pub const WebsocketMessageKind = enum(u8) {
+ _none,
+ /// welcome
+ welcome,
-pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeEnum(this.status);
- try writer.writeArray(OutputFile, this.files);
- try writer.writeArray(Message, this.errors);
-}
+ /// file_change_notification
+ file_change_notification,
-};
+ /// build_success
+ build_success,
-pub const MessageKind = enum(u32) {
+ /// build_fail
+ build_fail,
-_none,
- /// err
- err,
+ _,
- /// warn
- warn,
+ pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
+ return try std.json.stringify(@tagName(self), opts, o);
+ }
+ };
- /// note
- note,
+ pub const WebsocketCommandKind = enum(u8) {
+ _none,
+ /// build
+ build,
- /// debug
- debug,
+ _,
-_,
+ pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
+ return try std.json.stringify(@tagName(self), opts, o);
+ }
+ };
- pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
- return try std.json.stringify(@tagName(self), opts, o);
- }
+ pub const WebsocketMessage = struct {
+ /// timestamp
+ timestamp: u32 = 0,
-
-};
+ /// kind
+ kind: WebsocketMessageKind,
-pub const Location = struct {
-/// file
-file: []const u8,
+ pub fn decode(reader: anytype) anyerror!WebsocketMessage {
+ var this = std.mem.zeroes(WebsocketMessage);
-/// namespace
-namespace: []const u8,
+ this.timestamp = try reader.readValue(u32);
+ this.kind = try reader.readValue(WebsocketMessageKind);
+ return this;
+ }
-/// line
-line: i32 = 0,
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeInt(this.timestamp);
+ try writer.writeEnum(this.kind);
+ }
+ };
-/// column
-column: i32 = 0,
+ pub const WebsocketMessageWelcome = packed struct {
+ /// epoch
+ epoch: u32 = 0,
-/// line_text
-line_text: []const u8,
+ pub fn decode(reader: anytype) anyerror!WebsocketMessageWelcome {
+ var this = std.mem.zeroes(WebsocketMessageWelcome);
-/// suggestion
-suggestion: []const u8,
+ this.epoch = try reader.readValue(u32);
+ return this;
+ }
-/// offset
-offset: u32 = 0,
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeInt(this.epoch);
+ }
+ };
+ pub const WebsocketMessageFileChangeNotification = struct {
+ /// id
+ id: u32 = 0,
-pub fn decode(reader: anytype) anyerror!Location {
- var this = std.mem.zeroes(Location);
+ /// loader
+ loader: Loader,
- this.file = try reader.readValue([]const u8);
- this.namespace = try reader.readValue([]const u8);
- this.line = try reader.readValue(i32);
- this.column = try reader.readValue(i32);
- this.line_text = try reader.readValue([]const u8);
- this.suggestion = try reader.readValue([]const u8);
- this.offset = try reader.readValue(u32);
- return this;
-}
+ pub fn decode(reader: anytype) anyerror!WebsocketMessageFileChangeNotification {
+ var this = std.mem.zeroes(WebsocketMessageFileChangeNotification);
-pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeValue(this.file);
- try writer.writeValue(this.namespace);
- try writer.writeInt(this.line);
- try writer.writeInt(this.column);
- try writer.writeValue(this.line_text);
- try writer.writeValue(this.suggestion);
- try writer.writeInt(this.offset);
-}
+ this.id = try reader.readValue(u32);
+ this.loader = try reader.readValue(Loader);
+ return this;
+ }
-};
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeInt(this.id);
+ try writer.writeEnum(this.loader);
+ }
+ };
-pub const MessageData = struct {
-/// text
-text: ?[]const u8 = null,
-
-/// location
-location: ?Location = null,
-
-
-pub fn decode(reader: anytype) anyerror!MessageData {
- var this = std.mem.zeroes(MessageData);
-
- while(true) {
- switch (try reader.readByte()) {
- 0 => { return this; },
-
- 1 => {
- this.text = try reader.readValue([]const u8);
-},
- 2 => {
- this.location = try reader.readValue(Location);
-},
- else => {
- return error.InvalidMessage;
- },
- }
- }
-unreachable;
-}
+ pub const WebsocketCommand = struct {
+ /// kind
+ kind: WebsocketCommandKind,
-pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
-if (this.text) |text| {
- try writer.writeFieldID(1);
- try writer.writeValue(text);
-}
-if (this.location) |location| {
- try writer.writeFieldID(2);
- try writer.writeValue(location);
-}
-try writer.endMessage();
-}
+ /// timestamp
+ timestamp: u32 = 0,
-};
+ pub fn decode(reader: anytype) anyerror!WebsocketCommand {
+ var this = std.mem.zeroes(WebsocketCommand);
-pub const Message = struct {
-/// kind
-kind: MessageKind,
+ this.kind = try reader.readValue(WebsocketCommandKind);
+ this.timestamp = try reader.readValue(u32);
+ return this;
+ }
-/// data
-data: MessageData,
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeEnum(this.kind);
+ try writer.writeInt(this.timestamp);
+ }
+ };
-/// notes
-notes: []const MessageData,
+ pub const WebsocketCommandBuild = packed struct {
+ /// id
+ id: u32 = 0,
+ pub fn decode(reader: anytype) anyerror!WebsocketCommandBuild {
+ var this = std.mem.zeroes(WebsocketCommandBuild);
-pub fn decode(reader: anytype) anyerror!Message {
- var this = std.mem.zeroes(Message);
+ this.id = try reader.readValue(u32);
+ return this;
+ }
- this.kind = try reader.readValue(MessageKind);
- this.data = try reader.readValue(MessageData);
- this.notes = try reader.readArray(MessageData);
- return this;
-}
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeInt(this.id);
+ }
+ };
-pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeEnum(this.kind);
- try writer.writeValue(this.data);
- try writer.writeArray(MessageData, this.notes);
-}
+ pub const WebsocketMessageBuildSuccess = struct {
+ /// id
+ id: u32 = 0,
-};
+ /// from_timestamp
+ from_timestamp: u32 = 0,
-pub const Log = struct {
-/// warnings
-warnings: u32 = 0,
+ /// loader
+ loader: Loader,
-/// errors
-errors: u32 = 0,
+ /// module_path
+ module_path: []const u8,
-/// msgs
-msgs: []const Message,
+ /// log
+ log: Log,
+ /// bytes
+ bytes: []const u8,
-pub fn decode(reader: anytype) anyerror!Log {
- var this = std.mem.zeroes(Log);
+ pub fn decode(reader: anytype) anyerror!WebsocketMessageBuildSuccess {
+ var this = std.mem.zeroes(WebsocketMessageBuildSuccess);
- this.warnings = try reader.readValue(u32);
- this.errors = try reader.readValue(u32);
- this.msgs = try reader.readArray(Message);
- return this;
-}
+ this.id = try reader.readValue(u32);
+ this.from_timestamp = try reader.readValue(u32);
+ this.loader = try reader.readValue(Loader);
+ this.module_path = try reader.readValue([]const u8);
+ this.log = try reader.readValue(Log);
+ this.bytes = try reader.readArray(u8);
+ return this;
+ }
-pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeInt(this.warnings);
- try writer.writeInt(this.errors);
- try writer.writeArray(Message, this.msgs);
-}
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeInt(this.id);
+ try writer.writeInt(this.from_timestamp);
+ try writer.writeEnum(this.loader);
+ try writer.writeValue(this.module_path);
+ try writer.writeValue(this.log);
+ try writer.writeArray(u8, this.bytes);
+ }
+ };
-};
+ pub const WebsocketMessageBuildFailure = struct {
+ /// id
+ id: u32 = 0,
+ /// from_timestamp
+ from_timestamp: u32 = 0,
-};
+ /// loader
+ loader: Loader,
+
+ /// module_path
+ module_path: []const u8,
+
+ /// log
+ log: Log,
+ pub fn decode(reader: anytype) anyerror!WebsocketMessageBuildFailure {
+ var this = std.mem.zeroes(WebsocketMessageBuildFailure);
+
+ this.id = try reader.readValue(u32);
+ this.from_timestamp = try reader.readValue(u32);
+ this.loader = try reader.readValue(Loader);
+ this.module_path = try reader.readValue([]const u8);
+ this.log = try reader.readValue(Log);
+ return this;
+ }
+
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeInt(this.id);
+ try writer.writeInt(this.from_timestamp);
+ try writer.writeEnum(this.loader);
+ try writer.writeValue(this.module_path);
+ try writer.writeValue(this.log);
+ }
+ };
+};
const ExamplePackedStruct = packed struct {
len: u32 = 0,
diff --git a/src/bundler.zig b/src/bundler.zig
index 3c1f5155e..cbdb5586a 100644
--- a/src/bundler.zig
+++ b/src/bundler.zig
@@ -1091,6 +1091,7 @@ pub fn NewBundler(cache_files: bool) type {
opts.enable_bundling = bundler.options.node_modules_bundle != null;
opts.transform_require_to_import = true;
opts.can_import_from_bundle = bundler.options.node_modules_bundle != null;
+ opts.features.hot_module_reloading = bundler.options.hot_module_reloading;
const value = (bundler.resolver.caches.js.parse(allocator, opts, bundler.options.define, bundler.log, &source) catch null) orelse return null;
return ParseResult{
.ast = value,
diff --git a/src/js_parser/imports.zig b/src/js_parser/imports.zig
index 9ab6a9cb2..e276d6260 100644
--- a/src/js_parser/imports.zig
+++ b/src/js_parser/imports.zig
@@ -7,7 +7,9 @@ pub const options = @import("../options.zig");
pub const alloc = @import("../alloc.zig");
pub const js_printer = @import("../js_printer.zig");
pub const renamer = @import("../renamer.zig");
-pub const RuntimeImports = @import("../runtime.zig").Runtime.Imports;
+const _runtime = @import("../runtime.zig");
+pub const RuntimeImports = _runtime.Runtime.Imports;
+pub const RuntimeFeatures = _runtime.Runtime.Features;
pub const fs = @import("../fs.zig");
const _hash_map = @import("../hash_map.zig");
pub usingnamespace @import("../global.zig");
@@ -23,6 +25,7 @@ pub const ExprNodeIndex = js_ast.ExprNodeIndex;
pub const ExprNodeList = js_ast.ExprNodeList;
pub const StmtNodeList = js_ast.StmtNodeList;
pub const BindingNodeList = js_ast.BindingNodeList;
+
pub const assert = std.debug.assert;
pub const LocRef = js_ast.LocRef;
diff --git a/src/js_parser/js_parser.zig b/src/js_parser/js_parser.zig
index 23e9cfad0..4033cdd8d 100644
--- a/src/js_parser/js_parser.zig
+++ b/src/js_parser/js_parser.zig
@@ -1552,6 +1552,8 @@ pub const Parser = struct {
use_define_for_class_fields: bool = false,
suppress_warnings_about_weird_code: bool = true,
+ features: RuntimeFeatures = RuntimeFeatures{},
+
// Used when bundling node_modules
enable_bundling: bool = false,
transform_require_to_import: bool = true,
@@ -1889,7 +1891,7 @@ pub const Parser = struct {
jsx_part_stmts[stmt_i] = p.s(S.Local{ .kind = .k_var, .decls = decls }, loc);
- after.append(js_ast.Part{
+ before.append(js_ast.Part{
.stmts = jsx_part_stmts,
.declared_symbols = declared_symbols,
.import_record_indices = import_records,
@@ -1947,7 +1949,7 @@ pub const Parser = struct {
};
}
- after.append(js_ast.Part{
+ before.append(js_ast.Part{
.stmts = p.cjs_import_stmts.items,
.declared_symbols = declared_symbols,
.import_record_indices = import_records,
@@ -4419,6 +4421,41 @@ pub fn NewParser(
}, loc);
}
+ // For HMR, we must convert syntax like this:
+ // export function leftPad() {
+ // export const guy = GUY_FIERI_ASCII_ART;
+ // export class Bacon {}
+ // export default GuyFieriAsciiArt;
+ // export {Bacon};
+ // export {Bacon as default};
+ // to:
+ // var __hmr__module = new __hmr_HMRModule(file_id, import.meta);
+ // (__hmr__module._load = function() {
+ // __hmr__module.exports.leftPad = function () {};
+ // __hmr__module.exports.npmProgressBar33 = true;
+ // __hmr__module.exports.Bacon = class {};
+ // })();
+ // export { __hmr__module.exports.leftPad as leftPad, __hmr__module.exports.npmProgressBar33 as npmProgressBar33, __hmr__module }
+ //
+ //
+ //
+ // At bottom of the file:
+ // -
+ // var __hmr__exports = new HMRModule({
+ // leftPad: () => leftPad,
+ // npmProgressBar33 () => npmProgressBar33,
+ // default: () => GuyFieriAsciiArt,
+ // [__hmr_ModuleIDSymbol]:
+ //});
+ // export { __hmr__exports.leftPad as leftPad, __hmr__ }
+ // -
+ // Then:
+ // if () {
+ //
+ // }
+
+ // pub fn maybeRewriteExportSymbol(p: *P, )
+
pub fn parseStmt(p: *P, opts: *ParseStatementOptions) anyerror!Stmt {
var loc = p.lexer.loc();
diff --git a/src/linker.zig b/src/linker.zig
index 15b2e82e6..71f954774 100644
--- a/src/linker.zig
+++ b/src/linker.zig
@@ -301,12 +301,12 @@ pub fn NewLinker(comptime BundlerType: type) type {
// Change the import order so that any bundled imports appear last
// This is to make it so the bundle (which should be quite large) is least likely to block rendering
- if (needs_bundle) {
- const sorter = ImportStatementSorter{ .import_records = result.ast.import_records };
- for (result.ast.parts) |*part, i| {
- std.sort.sort(js_ast.Stmt, part.stmts, sorter, ImportStatementSorter.lessThan);
- }
- }
+ // if (needs_bundle) {
+ // const sorter = ImportStatementSorter{ .import_records = result.ast.import_records };
+ // for (result.ast.parts) |*part, i| {
+ // std.sort.sort(js_ast.Stmt, part.stmts, sorter, ImportStatementSorter.lessThan);
+ // }
+ // }
}
const ImportPathsList = allocators.BSSStringList(512, 128);
diff --git a/src/options.zig b/src/options.zig
index 56c72ff1a..4b45acdf2 100644
--- a/src/options.zig
+++ b/src/options.zig
@@ -540,7 +540,9 @@ pub const BundleOptions = struct {
loaders: std.StringHashMap(Loader),
resolve_dir: string = "/",
jsx: JSX.Pragma = JSX.Pragma{},
+
react_fast_refresh: bool = false,
+ hot_module_reloading: bool = false,
inject: ?[]string = null,
public_url: string = "",
public_dir: string = "public",
@@ -685,6 +687,7 @@ pub const BundleOptions = struct {
if (isWindows and opts.public_dir_handle != null) {
opts.public_dir_handle.?.close();
}
+ opts.hot_module_reloading = true;
}
if (opts.write and opts.output_dir.len > 0) {
diff --git a/src/runtime.zig b/src/runtime.zig
index f74ed8067..f6a15da98 100644
--- a/src/runtime.zig
+++ b/src/runtime.zig
@@ -2,12 +2,12 @@ const options = @import("./options.zig");
usingnamespace @import("ast/base.zig");
usingnamespace @import("global.zig");
const std = @import("std");
-pub const ProdSourceContent = @embedFile("./runtime.js");
+pub const ProdSourceContent = @embedFile("./runtime.out.js");
pub const Runtime = struct {
pub fn sourceContent() string {
if (isDebug) {
- var runtime_path = std.fs.path.join(std.heap.c_allocator, &[_]string{ std.fs.path.dirname(@src().file).?, "runtime.js" }) catch unreachable;
+ var runtime_path = std.fs.path.join(std.heap.c_allocator, &[_]string{ std.fs.path.dirname(@src().file).?, "runtime.out.js" }) catch unreachable;
const file = std.fs.openFileAbsolute(runtime_path, .{}) catch unreachable;
defer file.close();
return file.readToEndAlloc(std.heap.c_allocator, (file.stat() catch unreachable).size) catch unreachable;
@@ -19,7 +19,8 @@ pub const Runtime = struct {
pub fn version() string {
return version_hash;
}
- pub const Features = packed struct {
+
+ pub const Features = struct {
react_fast_refresh: bool = false,
hot_module_reloading: bool = false,
keep_names_for_arrow_functions: bool = true,
diff --git a/src/runtime/hmr.ts b/src/runtime/hmr.ts
new file mode 100644
index 000000000..f6d540b5a
--- /dev/null
+++ b/src/runtime/hmr.ts
@@ -0,0 +1,391 @@
+import { ByteBuffer } from "peechy/bb";
+import * as Schema from "../api/schema";
+
+var runOnce = false;
+var clientStartTime = 0;
+
+function formatDuration(duration: number) {
+ return Math.round(duration * 100000) / 100;
+}
+
+export class Client {
+ socket: WebSocket;
+ hasWelcomed: boolean = false;
+ reconnect: number = 0;
+ // Server timestamps are relative to the time the server's HTTP server launched
+ // This so we can send timestamps as uint32 instead of 128-bit integers
+ epoch: number = 0;
+
+ start() {
+ if (runOnce) {
+ console.warn(
+ "[speedy] Attempted to start HMR client multiple times. This may be a bug."
+ );
+ return;
+ }
+
+ runOnce = true;
+ this.connect();
+ }
+
+ connect() {
+ clientStartTime = performance.now();
+
+ this.socket = new WebSocket("/_api", ["speedy-hmr"]);
+ this.socket.binaryType = "arraybuffer";
+ this.socket.onclose = this.handleClose;
+ this.socket.onopen = this.handleOpen;
+ this.socket.onmessage = this.handleMessage;
+ }
+
+ // key: module id
+ // value: server-timestamp
+ builds = new Map<number, number>();
+
+ indexOfModuleId(id: number): number {
+ return Module.dependencies.graph.indexOf(id);
+ }
+
+ handleBuildFailure(buffer: ByteBuffer, timestamp: number) {
+ // 0: ID
+ // 1: Timestamp
+ const header_data = new Uint32Array(
+ buffer._data.buffer,
+ buffer._data.byteOffset,
+ buffer._data.byteOffset + 8
+ );
+ const index = this.indexOfModuleId(header_data[0]);
+ // Ignore build failures of modules that are not loaded
+ if (index === -1) {
+ return;
+ }
+
+ // Build failed for a module we didn't request?
+ const minTimestamp = this.builds.get(index);
+ if (!minTimestamp) {
+ return;
+ }
+ const fail = Schema.decodeWebsocketMessageBuildFailure(buffer);
+ // TODO: finish this.
+ console.error("[speedy] Build failed", fail.module_path);
+ }
+
+ verbose = process.env.SPEEDY_HMR_VERBOSE;
+
+ handleBuildSuccess(buffer: ByteBuffer, timestamp: number) {
+ // 0: ID
+ // 1: Timestamp
+ const header_data = new Uint32Array(
+ buffer._data.buffer,
+ buffer._data.byteOffset,
+ buffer._data.byteOffset + 8
+ );
+ const index = this.indexOfModuleId(header_data[0]);
+ // Ignore builds of modules that are not loaded
+ if (index === -1) {
+ if (this.verbose) {
+ console.debug(
+ `[speedy] Skipping reload for unknown module id:`,
+ header_data[0]
+ );
+ }
+
+ return;
+ }
+
+ // Ignore builds of modules we expect a later version of
+ const currentVersion = this.builds.get(header_data[0]) || -Infinity;
+ if (currentVersion > header_data[1]) {
+ if (this.verbose) {
+ console.debug(
+ `[speedy] Ignoring module update for "${Module.dependencies.modules[index].url.pathname}" due to timestamp mismatch.\n Expected: >=`,
+ currentVersion,
+ `\n Received:`,
+ header_data[1]
+ );
+ }
+ return;
+ }
+
+ if (this.verbose) {
+ console.debug(
+ "[speedy] Preparing to reload",
+ Module.dependencies.modules[index].url.pathname
+ );
+ }
+
+ const build = Schema.decodeWebsocketMessageBuildSuccess(buffer);
+ var reload = new HotReload(header_data[0], index, build);
+ reload.timings.notify = timestamp - build.from_timestamp;
+ reload.run().then(
+ ([module, timings]) => {
+ console.log(
+ `[speedy] Reloaded in ${formatDuration(timings.total)}ms :`,
+ module.url.pathname
+ );
+ },
+ (err) => {
+ console.error("[speedy] Hot Module Reload failed!", err);
+ debugger;
+ }
+ );
+ }
+
+ handleFileChangeNotification(buffer: ByteBuffer, timestamp: number) {
+ const notification =
+ Schema.decodeWebsocketMessageFileChangeNotification(buffer);
+ const index = Module.dependencies.graph.indexOf(notification.id);
+
+ if (index === -1) {
+ if (this.verbose) {
+ console.debug("[speedy] Unknown module changed, skipping");
+ }
+ return;
+ }
+
+ if ((this.builds.get(notification.id) || -Infinity) > timestamp) {
+ console.debug(
+ `[speedy] Received update for ${Module.dependencies.modules[index].url.pathname}`
+ );
+ return;
+ }
+
+ if (this.verbose) {
+ console.debug(
+ `[speedy] Requesting update for ${Module.dependencies.modules[index].url.pathname}`
+ );
+ }
+
+ this.builds.set(notification.id, timestamp);
+ this.buildCommandBuf[0] = Schema.WebsocketCommandKind.build;
+ this.buildCommandUArray[0] = timestamp;
+ this.buildCommandBuf.set(new Uint8Array(this.buildCommandUArray), 1);
+ this.buildCommandUArray[0] = notification.id;
+ this.buildCommandBuf.set(new Uint8Array(this.buildCommandUArray), 5);
+ this.socket.send(this.buildCommandBuf);
+ }
+ buildCommandBuf = new Uint8Array(9);
+ buildCommandUArray = new Uint32Array(1);
+
+ handleOpen = (event: Event) => {
+ globalThis.clearInterval(this.reconnect);
+ this.reconnect = 0;
+ };
+
+ handleMessage = (event: MessageEvent) => {
+ const data = new Uint8Array(event.data);
+ const message_header_byte_buffer = new ByteBuffer(data);
+ const header = Schema.decodeWebsocketMessage(message_header_byte_buffer);
+ const buffer = new ByteBuffer(
+ data.subarray(message_header_byte_buffer._index)
+ );
+
+ switch (header.kind) {
+ case Schema.WebsocketMessageKind.build_fail: {
+ this.handleBuildFailure(buffer, header.timestamp);
+ break;
+ }
+ case Schema.WebsocketMessageKind.build_success: {
+ this.handleBuildSuccess(buffer, header.timestamp);
+ break;
+ }
+ case Schema.WebsocketMessageKind.file_change_notification: {
+ this.handleFileChangeNotification(buffer, header.timestamp);
+ break;
+ }
+ case Schema.WebsocketMessageKind.welcome: {
+ const now = performance.now();
+ console.log(
+ "[speedy] HMR connected in",
+ formatDuration(now - clientStartTime),
+ "ms"
+ );
+ clientStartTime = now;
+ this.hasWelcomed = true;
+ const welcome = Schema.decodeWebsocketMessageWelcome(buffer);
+ this.epoch = welcome.epoch;
+ if (!this.epoch) {
+ console.warn("[speedy] Internal HMR error");
+ }
+ break;
+ }
+ }
+ };
+
+ handleClose = (event: CloseEvent) => {
+ if (this.reconnect !== 0) {
+ return;
+ }
+
+ this.reconnect = setInterval(this.connect, 500) as any as number;
+ console.warn("[speedy] HMR disconnected. Attempting to reconnect.");
+ };
+}
+
+class HotReload {
+ module_id: number = 0;
+ module_index: number = 0;
+ build: Schema.WebsocketMessageBuildSuccess;
+ timings = {
+ notify: 0,
+ decode: 0,
+ import: 0,
+ callbacks: 0,
+ total: 0,
+ start: 0,
+ };
+
+ constructor(
+ module_id: HotReload["module_id"],
+ module_index: HotReload["module_index"],
+ build: HotReload["build"]
+ ) {
+ this.module_id = module_id;
+ this.module_index = module_index;
+ this.build = build;
+ }
+
+ async run(): Promise<[Module, HotReload["timings"]]> {
+ const importStart = performance.now();
+ let orig_deps = Module.dependencies;
+ Module.dependencies = orig_deps.fork(this.module_index);
+ var blobURL = null;
+ try {
+ const blob = new Blob([this.build.bytes], { type: "text/javascript" });
+ blobURL = URL.createObjectURL(blob);
+ await import(blobURL);
+ this.timings.import = performance.now() - importStart;
+ } catch (exception) {
+ Module.dependencies = orig_deps;
+ URL.revokeObjectURL(blobURL);
+ throw exception;
+ }
+
+ URL.revokeObjectURL(blobURL);
+
+ if (process.env.SPEEDY_HMR_VERBOSE) {
+ console.debug(
+ "[speedy] Re-imported",
+ Module.dependencies.modules[this.module_index].url.pathname,
+ "in",
+ formatDuration(this.timings.import),
+ ". Running callbacks"
+ );
+ }
+
+ const callbacksStart = performance.now();
+ try {
+ // ES Modules delay execution until all imports are parsed
+ // They execute depth-first
+ // If you load N modules and append each module ID to the array, 0 is the *last* module imported.
+ // modules.length - 1 is the first.
+ // Therefore, to reload all the modules in the correct order, we traverse the graph backwards
+ // This only works when the graph is up to date.
+ // If the import order changes, we need to regenerate the entire graph
+ // Which sounds expensive, until you realize that we are mostly talking about an array that will be typically less than 1024 elements
+ // Computers can do that in < 1ms easy!
+ for (let i = Module.dependencies.graph_used; i > this.module_index; i--) {
+ let handled = !Module.dependencies.modules[i].exports.__hmrDisable;
+ if (typeof Module.dependencies.modules[i].dispose === "function") {
+ Module.dependencies.modules[i].dispose();
+ handled = true;
+ }
+ if (typeof Module.dependencies.modules[i].accept === "function") {
+ Module.dependencies.modules[i].accept();
+ handled = true;
+ }
+ if (!handled) {
+ Module.dependencies.modules[i]._load();
+ }
+ }
+ } catch (exception) {
+ Module.dependencies = orig_deps;
+ throw exception;
+ }
+ this.timings.callbacks = performance.now() - callbacksStart;
+
+ if (process.env.SPEEDY_HMR_VERBOSE) {
+ console.debug(
+ "[speedy] Ran callbacks",
+ Module.dependencies.modules[this.module_index].url.pathname,
+ "in",
+ formatDuration(this.timings.callbacks),
+ "ms"
+ );
+ }
+
+ orig_deps = null;
+ this.timings.total =
+ this.timings.import + this.timings.callbacks + this.build.from_timestamp;
+ return Promise.resolve([
+ Module.dependencies.modules[this.module_index],
+ this.timings,
+ ]);
+ }
+}
+var client: Client;
+if ("SPEEDY_HMR_CLIENT" in globalThis) {
+ console.warn(
+ "[speedy] Attempted to load multiple copies of HMR. This may be a bug."
+ );
+} else if (process.env.SPEEDY_HMR_ENABLED) {
+ client = new Client();
+ client.start();
+ globalThis.SPEEDY_HMR_CLIENT = client;
+}
+
+export class Module {
+ constructor(id: number, url: URL) {
+ // Ensure V8 knows this is a U32
+ this.id = id | 0;
+ this.url = url;
+
+ if (!Module._dependencies) {
+ Module.dependencies = Module._dependencies;
+ }
+
+ this.graph_index = Module.dependencies.graph_used++;
+
+ // Grow the dependencies graph
+ if (Module.dependencies.graph.length <= this.graph_index) {
+ const new_graph = new Uint32Array(Module.dependencies.graph.length * 4);
+ new_graph.set(Module.dependencies.graph);
+ Module.dependencies.graph = new_graph;
+
+ // In-place grow. This creates a holey array, which is bad, but less bad than pushing potentially 1000 times
+ Module.dependencies.modules.length = new_graph.length;
+ }
+
+ Module.dependencies.modules[this.graph_index] = this;
+ Module.dependencies.graph[this.graph_index] = this.id | 0;
+ }
+ additional_files = [];
+
+ // When a module updates, we need to re-initialize each dependent, recursively
+ // To do so:
+ // 1. Track which modules are imported by which *at runtime*
+ // 2. When A updates, loop through each dependent of A in insertion order
+ // 3. For each old dependent, call .dispose() if exists
+ // 3. For each new dependent, call .accept() if exists
+ // 4.
+ static _dependencies = {
+ modules: new Array<Module>(32),
+ graph: new Uint32Array(32),
+ graph_used: 0,
+
+ fork(offset: number) {
+ return {
+ modules: Module._dependencies.modules.slice(),
+ graph: Module._dependencies.graph.slice(),
+ graph_used: offset - 1,
+ };
+ },
+ };
+ static dependencies: Module["_dependencies"];
+ url: URL;
+ _load = function () {};
+ id = 0;
+ graph_index = 0;
+ _exports = {};
+ exports = {};
+}
diff --git a/src/runtime/index.ts b/src/runtime/index.ts
new file mode 100644
index 000000000..873666412
--- /dev/null
+++ b/src/runtime/index.ts
@@ -0,0 +1,2 @@
+export * from "./hmr";
+export * from "../runtime.js";