aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/api/schema.d.ts9
-rw-r--r--src/api/schema.js82
-rw-r--r--src/api/schema.peechy13
-rw-r--r--src/api/schema.zig2725
-rw-r--r--src/env_loader.zig330
-rw-r--r--src/feature_flags.zig1
-rw-r--r--src/http.zig104
-rw-r--r--src/http/url_path.zig8
-rw-r--r--src/javascript/jsc/api/router.zig40
-rw-r--r--src/javascript/jsc/javascript.zig103
-rw-r--r--src/js_ast.zig40
-rw-r--r--src/js_lexer.zig1
-rw-r--r--src/js_lexer_tables.zig20
-rw-r--r--src/js_parser/js_parser.zig26
-rw-r--r--src/js_printer.zig20
-rw-r--r--src/linker.zig37
-rw-r--r--src/logger.zig2
-rw-r--r--src/options.zig83
-rw-r--r--src/query_string_map.zig417
-rw-r--r--src/resolver/package_json.zig60
-rw-r--r--src/router.zig23
-rw-r--r--src/string_immutable.zig17
22 files changed, 2719 insertions, 1442 deletions
diff --git a/src/api/schema.d.ts b/src/api/schema.d.ts
index 58207e2f9..1077a34f2 100644
--- a/src/api/schema.d.ts
+++ b/src/api/schema.d.ts
@@ -241,6 +241,10 @@ type uint32 = number;
client?: string;
server?: string;
development?: boolean;
+ client_defines?: StringMap;
+ server_defines?: StringMap;
+ client_defines_prefix?: string;
+ server_defines_prefix?: string;
}
export interface LoadedFramework {
@@ -248,18 +252,23 @@ type uint32 = number;
package: string;
development: boolean;
client: boolean;
+ define_defaults: StringMap;
+ define_prefix: string;
+ has_define_prefix: boolean;
}
export interface LoadedRouteConfig {
dir: string;
extensions: string[];
static_dir: string;
+ asset_prefix: string;
}
export interface RouteConfig {
dir?: string;
extensions?: string[];
static_dir?: string;
+ asset_prefix?: string;
}
export interface TransformOptions {
diff --git a/src/api/schema.js b/src/api/schema.js
index 40a6f132e..178d95662 100644
--- a/src/api/schema.js
+++ b/src/api/schema.js
@@ -613,6 +613,22 @@ function decodeFrameworkConfig(bb) {
result["development"] = !!bb.readByte();
break;
+ case 5:
+ result["client_defines"] = decodeStringMap(bb);
+ break;
+
+ case 6:
+ result["server_defines"] = decodeStringMap(bb);
+ break;
+
+ case 7:
+ result["client_defines_prefix"] = bb.readString();
+ break;
+
+ case 8:
+ result["server_defines_prefix"] = bb.readString();
+ break;
+
default:
throw new Error("Attempted to parse invalid message");
}
@@ -644,6 +660,30 @@ function encodeFrameworkConfig(message, bb) {
bb.writeByte(4);
bb.writeByte(value);
}
+
+ var value = message["client_defines"];
+ if (value != null) {
+ bb.writeByte(5);
+ encodeStringMap(value, bb);
+ }
+
+ var value = message["server_defines"];
+ if (value != null) {
+ bb.writeByte(6);
+ encodeStringMap(value, bb);
+ }
+
+ var value = message["client_defines_prefix"];
+ if (value != null) {
+ bb.writeByte(7);
+ bb.writeString(value);
+ }
+
+ var value = message["server_defines_prefix"];
+ if (value != null) {
+ bb.writeByte(8);
+ bb.writeString(value);
+ }
bb.writeByte(0);
}
@@ -655,6 +695,9 @@ function decodeLoadedFramework(bb) {
result["package"] = bb.readString();
result["development"] = !!bb.readByte();
result["client"] = !!bb.readByte();
+ result["define_defaults"] = decodeStringMap(bb);
+ result["define_prefix"] = bb.readString();
+ result["has_define_prefix"] = !!bb.readByte();
return result;
}
@@ -688,6 +731,27 @@ function encodeLoadedFramework(message, bb) {
throw new Error("Missing required field \"client\"");
}
+ var value = message["define_defaults"];
+ if (value != null) {
+ encodeStringMap(value, bb);
+ } else {
+ throw new Error("Missing required field \"define_defaults\"");
+ }
+
+ var value = message["define_prefix"];
+ if (value != null) {
+ bb.writeString(value);
+ } else {
+ throw new Error("Missing required field \"define_prefix\"");
+ }
+
+ var value = message["has_define_prefix"];
+ if (value != null) {
+ bb.writeByte(value);
+ } else {
+ throw new Error("Missing required field \"has_define_prefix\"");
+ }
+
}
function decodeLoadedRouteConfig(bb) {
@@ -698,6 +762,7 @@ function decodeLoadedRouteConfig(bb) {
var values = result["extensions"] = Array(length);
for (var i = 0; i < length; i++) values[i] = bb.readString();
result["static_dir"] = bb.readString();
+ result["asset_prefix"] = bb.readString();
return result;
}
@@ -729,6 +794,13 @@ function encodeLoadedRouteConfig(message, bb) {
throw new Error("Missing required field \"static_dir\"");
}
+ var value = message["asset_prefix"];
+ if (value != null) {
+ bb.writeString(value);
+ } else {
+ throw new Error("Missing required field \"asset_prefix\"");
+ }
+
}
function decodeRouteConfig(bb) {
@@ -753,6 +825,10 @@ function decodeRouteConfig(bb) {
result["static_dir"] = bb.readString();
break;
+ case 4:
+ result["asset_prefix"] = bb.readString();
+ break;
+
default:
throw new Error("Attempted to parse invalid message");
}
@@ -783,6 +859,12 @@ function encodeRouteConfig(message, bb) {
bb.writeByte(3);
bb.writeString(value);
}
+
+ var value = message["asset_prefix"];
+ if (value != null) {
+ bb.writeByte(4);
+ bb.writeString(value);
+ }
bb.writeByte(0);
}
diff --git a/src/api/schema.peechy b/src/api/schema.peechy
index 52d661619..864c6b114 100644
--- a/src/api/schema.peechy
+++ b/src/api/schema.peechy
@@ -140,6 +140,10 @@ message FrameworkConfig {
string client = 2;
string server = 3;
bool development = 4;
+ StringMap client_defines = 5;
+ StringMap server_defines = 6;
+ string client_defines_prefix = 7;
+ string server_defines_prefix = 8;
}
struct LoadedFramework {
@@ -147,18 +151,23 @@ struct LoadedFramework {
string package;
bool development;
bool client;
+ StringMap define_defaults;
+ string define_prefix;
+ bool has_define_prefix;
}
struct LoadedRouteConfig {
string dir;
string[] extensions;
string static_dir;
+ string asset_prefix;
}
message RouteConfig {
string dir = 1;
string[] extensions = 2;
string static_dir = 3;
+ string asset_prefix = 4;
}
message TransformOptions {
@@ -384,4 +393,6 @@ struct WebsocketMessageManifestFailure {
uint32 from_timestamp;
Loader loader;
Log log;
-} \ No newline at end of file
+}
+
+
diff --git a/src/api/schema.zig b/src/api/schema.zig
index 33bc54bcb..344a60a28 100644
--- a/src/api/schema.zig
+++ b/src/api/schema.zig
@@ -1,3 +1,4 @@
+
const std = @import("std");
pub const Reader = struct {
@@ -281,1602 +282,1774 @@ 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,
- /// tsx
- tsx,
+pub const Api = struct {
- /// css
- css,
+pub const Loader = enum(u8) {
- /// file
- file,
+_none,
+ /// jsx
+ jsx,
- /// json
- json,
+ /// js
+ js,
- _,
+ /// ts
+ ts,
- pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
- return try std.json.stringify(@tagName(self), opts, o);
- }
- };
+ /// tsx
+ tsx,
- pub const ResolveMode = enum(u8) {
- _none,
- /// disable
- disable,
+ /// css
+ css,
- /// lazy
- lazy,
+ /// file
+ file,
- /// dev
- dev,
+ /// json
+ json,
- /// 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 Platform = enum(u8) {
- _none,
- /// browser
- browser,
+pub const ResolveMode = enum(u8) {
- /// node
- node,
+_none,
+ /// disable
+ disable,
- /// speedy
- speedy,
+ /// 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,
+ /// speedy
+ speedy,
- /// development
- development: bool = false,
+_,
- /// import_source
- import_source: []const u8,
+ pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
+ return try std.json.stringify(@tagName(self), opts, o);
+ }
- /// react_fast_refresh
- react_fast_refresh: bool = false,
+
+};
- pub fn decode(reader: anytype) anyerror!Jsx {
- var this = std.mem.zeroes(Jsx);
+pub const JsxRuntime = enum(u8) {
- 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;
- }
+_none,
+ /// automatic
+ automatic,
- 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)));
- }
- };
+ /// classic
+ classic,
- pub const StringPointer = packed struct {
- /// offset
- offset: u32 = 0,
+_,
- /// length
- length: 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!StringPointer {
- var this = std.mem.zeroes(StringPointer);
+
+};
- this.offset = try reader.readValue(u32);
- this.length = try reader.readValue(u32);
- return this;
- }
+pub const Jsx = struct {
+/// factory
+factory: []const u8,
- pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeInt(this.offset);
- try writer.writeInt(this.length);
- }
- };
+/// runtime
+runtime: JsxRuntime,
- pub const JavascriptBundledModule = struct {
- /// path
- path: StringPointer,
+/// fragment
+fragment: []const u8,
- /// code
- code: StringPointer,
+/// development
+development: bool = false,
- /// package_id
- package_id: u32 = 0,
+/// import_source
+import_source: []const u8,
- /// id
- id: u32 = 0,
+/// react_fast_refresh
+react_fast_refresh: bool = false,
- /// path_extname_length
- path_extname_length: u8 = 0,
- pub fn decode(reader: anytype) anyerror!JavascriptBundledModule {
- var this = std.mem.zeroes(JavascriptBundledModule);
+pub fn decode(reader: anytype) anyerror!Jsx {
+ var this = std.mem.zeroes(Jsx);
- 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;
- }
+ 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;
+}
- 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 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 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,
- /// framework
- framework: ?LoadedFramework = null,
+/// modules_offset
+modules_offset: u32 = 0,
- /// routes
- routes: ?LoadedRouteConfig = null,
+/// modules_length
+modules_length: u32 = 0,
- /// code_length
- code_length: ?u32 = null,
- pub fn decode(reader: anytype) anyerror!JavascriptBundleContainer {
- var this = std.mem.zeroes(JavascriptBundleContainer);
+pub fn decode(reader: anytype) anyerror!JavascriptBundledPackage {
+ var this = std.mem.zeroes(JavascriptBundledPackage);
- while (true) {
- switch (try reader.readByte()) {
- 0 => {
- return this;
- },
+ 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;
+}
- 1 => {
- this.bundle_format_version = try reader.readValue(u32);
- },
- 2 => {
- this.bundle = try reader.readValue(JavascriptBundle);
- },
- 3 => {
- this.framework = try reader.readValue(LoadedFramework);
- },
- 4 => {
- this.routes = try reader.readValue(LoadedRouteConfig);
- },
- 5 => {
- this.code_length = try reader.readValue(u32);
- },
- else => {
- return error.InvalidMessage;
- },
+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 JavascriptBundle = struct {
+/// modules
+modules: []const JavascriptBundledModule,
+
+/// packages
+packages: []const JavascriptBundledPackage,
+
+/// etag
+etag: []const u8,
+
+/// generated_at
+generated_at: u32 = 0,
+
+/// app_package_json_dependencies_hash
+app_package_json_dependencies_hash: []const u8,
+
+/// import_from_name
+import_from_name: []const u8,
+
+/// manifest_string
+manifest_string: []const u8,
+
+
+pub fn decode(reader: anytype) anyerror!JavascriptBundle {
+ var this = std.mem.zeroes(JavascriptBundle);
+
+ 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 JavascriptBundleContainer = struct {
+/// bundle_format_version
+bundle_format_version: ?u32 = null,
+
+/// bundle
+bundle: ?JavascriptBundle = null,
+
+/// framework
+framework: ?LoadedFramework = null,
+
+/// routes
+routes: ?LoadedRouteConfig = 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.framework = try reader.readValue(LoadedFramework);
+},
+ 4 => {
+ this.routes = try reader.readValue(LoadedRouteConfig);
+},
+ 5 => {
+ this.code_length = try reader.readValue(u32);
+},
+ else => {
+ return error.InvalidMessage;
+ },
+ }
+ }
+unreachable;
+}
+
+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.framework) |framework| {
+ try writer.writeFieldID(3);
+ try writer.writeValue(framework);
+}
+if (this.routes) |routes| {
+ try writer.writeFieldID(4);
+ try writer.writeValue(routes);
+}
+if (this.code_length) |code_length| {
+ try writer.writeFieldID(5);
+ try writer.writeInt(code_length);
+}
+try writer.endMessage();
+}
+
+};
+
+pub const ScanDependencyMode = enum(u8) {
+
+_none,
+ /// app
+ app,
+
+ /// all
+ all,
+
+_,
+
+ pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
+ return try std.json.stringify(@tagName(self), opts, o);
}
- }
- unreachable;
- }
- 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.framework) |framework| {
- try writer.writeFieldID(3);
- try writer.writeValue(framework);
- }
- if (this.routes) |routes| {
- try writer.writeFieldID(4);
- try writer.writeValue(routes);
- }
- if (this.code_length) |code_length| {
- try writer.writeFieldID(5);
- try writer.writeInt(code_length);
- }
- try writer.endMessage();
- }
- };
+
+};
- pub const ScanDependencyMode = enum(u8) {
- _none,
- /// app
- app,
+pub const ModuleImportType = enum(u8) {
- /// all
- all,
+_none,
+ /// import
+ import,
- _,
+ /// require
+ require,
- pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
- return try std.json.stringify(@tagName(self), opts, o);
- }
- };
+_,
- pub const ModuleImportType = enum(u8) {
- _none,
- /// import
- import,
+ pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
+ return try std.json.stringify(@tagName(self), opts, o);
+ }
- /// require
- require,
+
+};
- _,
+pub const ModuleImportRecord = struct {
+/// kind
+kind: ModuleImportType,
- pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
- return try std.json.stringify(@tagName(self), opts, o);
- }
- };
+/// path
+path: []const u8,
- pub const ModuleImportRecord = struct {
- /// kind
- kind: ModuleImportType,
+/// dynamic
+dynamic: bool = false,
- /// path
- path: []const u8,
- /// dynamic
- dynamic: bool = false,
+pub fn decode(reader: anytype) anyerror!ModuleImportRecord {
+ var this = std.mem.zeroes(ModuleImportRecord);
- pub fn decode(reader: anytype) anyerror!ModuleImportRecord {
- var this = std.mem.zeroes(ModuleImportRecord);
+ this.kind = try reader.readValue(ModuleImportType);
+ this.path = try reader.readValue([]const u8);
+ this.dynamic = try reader.readValue(bool);
+ 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.writeEnum(this.kind);
+ try writer.writeValue(this.path);
+ try writer.writeInt(@intCast(u8, @boolToInt(this.dynamic)));
+}
- 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 Module = struct {
+/// path
+path: []const u8,
- /// imports
- imports: []const ModuleImportRecord,
+/// imports
+imports: []const ModuleImportRecord,
- 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 fn decode(reader: anytype) anyerror!Module {
+ var this = std.mem.zeroes(Module);
- pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeValue(this.path);
- try writer.writeArray(ModuleImportRecord, this.imports);
- }
- };
+ this.path = try reader.readValue([]const u8);
+ this.imports = try reader.readArray(ModuleImportRecord);
+ return this;
+}
- pub const StringMap = struct {
- /// keys
- keys: []const []const u8,
+pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeValue(this.path);
+ try writer.writeArray(ModuleImportRecord, this.imports);
+}
- /// values
- values: []const []const u8,
+};
- pub fn decode(reader: anytype) anyerror!StringMap {
- var this = std.mem.zeroes(StringMap);
+pub const StringMap = struct {
+/// keys
+keys: []const []const u8,
- this.keys = try reader.readArray([]const u8);
- this.values = try reader.readArray([]const u8);
- return this;
- }
+/// values
+values: []const []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);
- }
- };
- pub const LoaderMap = struct {
- /// extensions
- extensions: []const []const u8,
+pub fn decode(reader: anytype) anyerror!StringMap {
+ var this = std.mem.zeroes(StringMap);
- /// loaders
- loaders: []const Loader,
+ this.keys = try reader.readArray([]const u8);
+ this.values = try reader.readArray([]const u8);
+ return this;
+}
- pub fn decode(reader: anytype) anyerror!LoaderMap {
- var this = std.mem.zeroes(LoaderMap);
+pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeArray([]const u8, this.keys);
+ try writer.writeArray([]const u8, this.values);
+}
- 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 LoaderMap = struct {
+/// extensions
+extensions: []const []const u8,
- pub const FrameworkConfig = struct {
- /// package
- package: ?[]const u8 = null,
+/// loaders
+loaders: []const Loader,
- /// client
- client: ?[]const u8 = null,
- /// server
- server: ?[]const u8 = null,
+pub fn decode(reader: anytype) anyerror!LoaderMap {
+ var this = std.mem.zeroes(LoaderMap);
- /// development
- development: ?bool = null,
+ this.extensions = try reader.readArray([]const u8);
+ this.loaders = try reader.readArray(Loader);
+ return this;
+}
- pub fn decode(reader: anytype) anyerror!FrameworkConfig {
- var this = std.mem.zeroes(FrameworkConfig);
+pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeArray([]const u8, this.extensions);
+ try writer.writeArray(Loader, this.loaders);
+}
- while (true) {
- switch (try reader.readByte()) {
- 0 => {
- return this;
- },
+};
- 1 => {
- this.package = try reader.readValue([]const u8);
- },
- 2 => {
- this.client = try reader.readValue([]const u8);
- },
- 3 => {
- this.server = try reader.readValue([]const u8);
- },
- 4 => {
- this.development = try reader.readValue(bool);
- },
- else => {
- return error.InvalidMessage;
- },
- }
- }
- unreachable;
- }
+pub const FrameworkConfig = struct {
+/// package
+package: ?[]const u8 = null,
+
+/// client
+client: ?[]const u8 = null,
+
+/// server
+server: ?[]const u8 = null,
+
+/// development
+development: ?bool = null,
+
+/// client_defines
+client_defines: ?StringMap = null,
+
+/// server_defines
+server_defines: ?StringMap = null,
+
+/// client_defines_prefix
+client_defines_prefix: ?[]const u8 = null,
+
+/// server_defines_prefix
+server_defines_prefix: ?[]const u8 = null,
+
+
+pub fn decode(reader: anytype) anyerror!FrameworkConfig {
+ var this = std.mem.zeroes(FrameworkConfig);
+
+ while(true) {
+ switch (try reader.readByte()) {
+ 0 => { return this; },
+
+ 1 => {
+ this.package = try reader.readValue([]const u8);
+},
+ 2 => {
+ this.client = try reader.readValue([]const u8);
+},
+ 3 => {
+ this.server = try reader.readValue([]const u8);
+},
+ 4 => {
+ this.development = try reader.readValue(bool);
+},
+ 5 => {
+ this.client_defines = try reader.readValue(StringMap);
+},
+ 6 => {
+ this.server_defines = try reader.readValue(StringMap);
+},
+ 7 => {
+ this.client_defines_prefix = try reader.readValue([]const u8);
+},
+ 8 => {
+ this.server_defines_prefix = try reader.readValue([]const u8);
+},
+ else => {
+ return error.InvalidMessage;
+ },
+ }
+ }
+unreachable;
+}
- pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- if (this.package) |package| {
- try writer.writeFieldID(1);
- try writer.writeValue(package);
- }
- if (this.client) |client| {
- try writer.writeFieldID(2);
- try writer.writeValue(client);
- }
- if (this.server) |server| {
- try writer.writeFieldID(3);
- try writer.writeValue(server);
- }
- if (this.development) |development| {
- try writer.writeFieldID(4);
- try writer.writeInt(@intCast(u8, @boolToInt(development)));
- }
- try writer.endMessage();
- }
- };
+pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+if (this.package) |package| {
+ try writer.writeFieldID(1);
+ try writer.writeValue(package);
+}
+if (this.client) |client| {
+ try writer.writeFieldID(2);
+ try writer.writeValue(client);
+}
+if (this.server) |server| {
+ try writer.writeFieldID(3);
+ try writer.writeValue(server);
+}
+if (this.development) |development| {
+ try writer.writeFieldID(4);
+ try writer.writeInt(@intCast(u8, @boolToInt(development)));
+}
+if (this.client_defines) |client_defines| {
+ try writer.writeFieldID(5);
+ try writer.writeValue(client_defines);
+}
+if (this.server_defines) |server_defines| {
+ try writer.writeFieldID(6);
+ try writer.writeValue(server_defines);
+}
+if (this.client_defines_prefix) |client_defines_prefix| {
+ try writer.writeFieldID(7);
+ try writer.writeValue(client_defines_prefix);
+}
+if (this.server_defines_prefix) |server_defines_prefix| {
+ try writer.writeFieldID(8);
+ try writer.writeValue(server_defines_prefix);
+}
+try writer.endMessage();
+}
- pub const LoadedFramework = struct {
- /// entry_point
- entry_point: []const u8,
+};
- /// package
- package: []const u8,
+pub const LoadedFramework = struct {
+/// entry_point
+entry_point: []const u8,
- /// development
- development: bool = false,
+/// package
+package: []const u8,
- /// client
- client: bool = false,
+/// development
+development: bool = false,
- pub fn decode(reader: anytype) anyerror!LoadedFramework {
- var this = std.mem.zeroes(LoadedFramework);
+/// client
+client: bool = false,
- this.entry_point = try reader.readValue([]const u8);
- this.package = try reader.readValue([]const u8);
- this.development = try reader.readValue(bool);
- this.client = try reader.readValue(bool);
- return this;
- }
+/// define_defaults
+define_defaults: StringMap,
- pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeValue(this.entry_point);
- try writer.writeValue(this.package);
- try writer.writeInt(@intCast(u8, @boolToInt(this.development)));
- try writer.writeInt(@intCast(u8, @boolToInt(this.client)));
- }
- };
+/// define_prefix
+define_prefix: []const u8,
- pub const LoadedRouteConfig = struct {
- /// dir
- dir: []const u8,
+/// has_define_prefix
+has_define_prefix: bool = false,
- /// extensions
- extensions: []const []const u8,
- /// static_dir
- static_dir: []const u8,
+pub fn decode(reader: anytype) anyerror!LoadedFramework {
+ var this = std.mem.zeroes(LoadedFramework);
- pub fn decode(reader: anytype) anyerror!LoadedRouteConfig {
- var this = std.mem.zeroes(LoadedRouteConfig);
+ this.entry_point = try reader.readValue([]const u8);
+ this.package = try reader.readValue([]const u8);
+ this.development = try reader.readValue(bool);
+ this.client = try reader.readValue(bool);
+ this.define_defaults = try reader.readValue(StringMap);
+ this.define_prefix = try reader.readValue([]const u8);
+ this.has_define_prefix = try reader.readValue(bool);
+ return this;
+}
- this.dir = try reader.readValue([]const u8);
- this.extensions = try reader.readArray([]const u8);
- this.static_dir = try reader.readValue([]const u8);
- return this;
- }
+pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeValue(this.entry_point);
+ try writer.writeValue(this.package);
+ try writer.writeInt(@intCast(u8, @boolToInt(this.development)));
+ try writer.writeInt(@intCast(u8, @boolToInt(this.client)));
+ try writer.writeValue(this.define_defaults);
+ try writer.writeValue(this.define_prefix);
+ try writer.writeInt(@intCast(u8, @boolToInt(this.has_define_prefix)));
+}
- pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeValue(this.dir);
- try writer.writeArray([]const u8, this.extensions);
- try writer.writeValue(this.static_dir);
- }
- };
+};
- pub const RouteConfig = struct {
- /// dir
- dir: ?[]const u8 = null,
+pub const LoadedRouteConfig = struct {
+/// dir
+dir: []const u8,
- /// extensions
- extensions: []const []const u8,
+/// extensions
+extensions: []const []const u8,
- /// static_dir
- static_dir: ?[]const u8 = null,
+/// static_dir
+static_dir: []const u8,
- pub fn decode(reader: anytype) anyerror!RouteConfig {
- var this = std.mem.zeroes(RouteConfig);
+/// asset_prefix
+asset_prefix: []const u8,
- while (true) {
- switch (try reader.readByte()) {
- 0 => {
- return this;
- },
- 1 => {
- this.dir = try reader.readValue([]const u8);
- },
- 2 => {
- this.extensions = try reader.readArray([]const u8);
- },
- 3 => {
- this.static_dir = try reader.readValue([]const u8);
- },
- else => {
- return error.InvalidMessage;
- },
- }
- }
- unreachable;
- }
+pub fn decode(reader: anytype) anyerror!LoadedRouteConfig {
+ var this = std.mem.zeroes(LoadedRouteConfig);
- pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- if (this.dir) |dir| {
- try writer.writeFieldID(1);
- try writer.writeValue(dir);
- }
- if (this.extensions) |extensions| {
- try writer.writeFieldID(2);
- try writer.writeArray([]const u8, extensions);
- }
- if (this.static_dir) |static_dir| {
- try writer.writeFieldID(3);
- try writer.writeValue(static_dir);
- }
- try writer.endMessage();
- }
- };
+ this.dir = try reader.readValue([]const u8);
+ this.extensions = try reader.readArray([]const u8);
+ this.static_dir = try reader.readValue([]const u8);
+ this.asset_prefix = try reader.readValue([]const u8);
+ return this;
+}
- pub const TransformOptions = struct {
- /// jsx
- jsx: ?Jsx = null,
+pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeValue(this.dir);
+ try writer.writeArray([]const u8, this.extensions);
+ try writer.writeValue(this.static_dir);
+ try writer.writeValue(this.asset_prefix);
+}
- /// tsconfig_override
- tsconfig_override: ?[]const u8 = null,
+};
- /// resolve
- resolve: ?ResolveMode = null,
+pub const RouteConfig = struct {
+/// dir
+dir: ?[]const u8 = null,
+
+/// extensions
+extensions: []const []const u8,
+
+/// static_dir
+static_dir: ?[]const u8 = null,
+
+/// asset_prefix
+asset_prefix: ?[]const u8 = null,
+
+
+pub fn decode(reader: anytype) anyerror!RouteConfig {
+ var this = std.mem.zeroes(RouteConfig);
+
+ while(true) {
+ switch (try reader.readByte()) {
+ 0 => { return this; },
+
+ 1 => {
+ this.dir = try reader.readValue([]const u8);
+},
+ 2 => {
+ this.extensions = try reader.readArray([]const u8);
+},
+ 3 => {
+ this.static_dir = try reader.readValue([]const u8);
+},
+ 4 => {
+ this.asset_prefix = try reader.readValue([]const u8);
+},
+ else => {
+ return error.InvalidMessage;
+ },
+ }
+ }
+unreachable;
+}
- /// origin
- origin: ?[]const u8 = null,
+pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+if (this.dir) |dir| {
+ try writer.writeFieldID(1);
+ try writer.writeValue(dir);
+}
+if (this.extensions) |extensions| {
+ try writer.writeFieldID(2);
+ try writer.writeArray([]const u8, extensions);
+}
+if (this.static_dir) |static_dir| {
+ try writer.writeFieldID(3);
+ try writer.writeValue(static_dir);
+}
+if (this.asset_prefix) |asset_prefix| {
+ try writer.writeFieldID(4);
+ try writer.writeValue(asset_prefix);
+}
+try writer.endMessage();
+}
- /// absolute_working_dir
- absolute_working_dir: ?[]const u8 = null,
+};
- /// define
- define: ?StringMap = null,
+pub const TransformOptions = struct {
+/// jsx
+jsx: ?Jsx = null,
- /// preserve_symlinks
- preserve_symlinks: ?bool = null,
+/// tsconfig_override
+tsconfig_override: ?[]const u8 = null,
- /// entry_points
- entry_points: []const []const u8,
+/// resolve
+resolve: ?ResolveMode = null,
- /// write
- write: ?bool = null,
+/// origin
+origin: ?[]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,
+
+/// 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,
+
+/// node_modules_bundle_path_server
+node_modules_bundle_path_server: ?[]const u8 = null,
+
+/// framework
+framework: ?FrameworkConfig = null,
+
+/// router
+router: ?RouteConfig = 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.origin = 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.only_scan_dependencies = try reader.readValue(ScanDependencyMode);
+},
+ 19 => {
+ this.generate_node_module_bundle = try reader.readValue(bool);
+},
+ 20 => {
+ this.node_modules_bundle_path = try reader.readValue([]const u8);
+},
+ 21 => {
+ this.node_modules_bundle_path_server = try reader.readValue([]const u8);
+},
+ 22 => {
+ this.framework = try reader.readValue(FrameworkConfig);
+},
+ 23 => {
+ this.router = try reader.readValue(RouteConfig);
+},
+ else => {
+ return error.InvalidMessage;
+ },
+ }
+ }
+unreachable;
+}
- /// inject
- inject: []const []const u8,
+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.origin) |origin| {
+ try writer.writeFieldID(4);
+ try writer.writeValue(origin);
+}
+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.only_scan_dependencies) |only_scan_dependencies| {
+ try writer.writeFieldID(18);
+ try writer.writeEnum(only_scan_dependencies);
+}
+if (this.generate_node_module_bundle) |generate_node_module_bundle| {
+ try writer.writeFieldID(19);
+ try writer.writeInt(@intCast(u8, @boolToInt(generate_node_module_bundle)));
+}
+if (this.node_modules_bundle_path) |node_modules_bundle_path| {
+ try writer.writeFieldID(20);
+ try writer.writeValue(node_modules_bundle_path);
+}
+if (this.node_modules_bundle_path_server) |node_modules_bundle_path_server| {
+ try writer.writeFieldID(21);
+ try writer.writeValue(node_modules_bundle_path_server);
+}
+if (this.framework) |framework| {
+ try writer.writeFieldID(22);
+ try writer.writeValue(framework);
+}
+if (this.router) |router| {
+ try writer.writeFieldID(23);
+ try writer.writeValue(router);
+}
+try writer.endMessage();
+}
- /// output_dir
- output_dir: ?[]const u8 = null,
+};
- /// external
- external: []const []const u8,
+pub const FileHandle = struct {
+/// path
+path: []const u8,
- /// loaders
- loaders: ?LoaderMap = null,
+/// size
+size: u32 = 0,
- /// main_fields
- main_fields: []const []const u8,
+/// fd
+fd: u32 = 0,
- /// platform
- platform: ?Platform = null,
- /// serve
- serve: ?bool = null,
+pub fn decode(reader: anytype) anyerror!FileHandle {
+ var this = std.mem.zeroes(FileHandle);
- /// extension_order
- extension_order: []const []const u8,
+ this.path = try reader.readValue([]const u8);
+ this.size = try reader.readValue(u32);
+ this.fd = try reader.readValue(u32);
+ return this;
+}
- /// only_scan_dependencies
- only_scan_dependencies: ?ScanDependencyMode = null,
+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);
+}
- /// generate_node_module_bundle
- generate_node_module_bundle: ?bool = null,
+};
- /// node_modules_bundle_path
- node_modules_bundle_path: ?[]const u8 = null,
+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;
+}
- /// node_modules_bundle_path_server
- node_modules_bundle_path_server: ?[]const u8 = null,
+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();
+}
- /// framework
- framework: ?FrameworkConfig = null,
+};
- /// router
- router: ?RouteConfig = null,
+pub const TransformResponseStatus = enum(u32) {
- pub fn decode(reader: anytype) anyerror!TransformOptions {
- var this = std.mem.zeroes(TransformOptions);
+_none,
+ /// success
+ success,
- while (true) {
- switch (try reader.readByte()) {
- 0 => {
- return this;
- },
+ /// fail
+ fail,
- 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.origin = 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.only_scan_dependencies = try reader.readValue(ScanDependencyMode);
- },
- 19 => {
- this.generate_node_module_bundle = try reader.readValue(bool);
- },
- 20 => {
- this.node_modules_bundle_path = try reader.readValue([]const u8);
- },
- 21 => {
- this.node_modules_bundle_path_server = try reader.readValue([]const u8);
- },
- 22 => {
- this.framework = try reader.readValue(FrameworkConfig);
- },
- 23 => {
- this.router = try reader.readValue(RouteConfig);
- },
- else => {
- return error.InvalidMessage;
- },
+_,
+
+ pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
+ return try std.json.stringify(@tagName(self), opts, o);
}
- }
- 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.origin) |origin| {
- try writer.writeFieldID(4);
- try writer.writeValue(origin);
- }
- 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.only_scan_dependencies) |only_scan_dependencies| {
- try writer.writeFieldID(18);
- try writer.writeEnum(only_scan_dependencies);
- }
- if (this.generate_node_module_bundle) |generate_node_module_bundle| {
- try writer.writeFieldID(19);
- try writer.writeInt(@intCast(u8, @boolToInt(generate_node_module_bundle)));
- }
- if (this.node_modules_bundle_path) |node_modules_bundle_path| {
- try writer.writeFieldID(20);
- try writer.writeValue(node_modules_bundle_path);
- }
- if (this.node_modules_bundle_path_server) |node_modules_bundle_path_server| {
- try writer.writeFieldID(21);
- try writer.writeValue(node_modules_bundle_path_server);
- }
- if (this.framework) |framework| {
- try writer.writeFieldID(22);
- try writer.writeValue(framework);
- }
- if (this.router) |router| {
- try writer.writeFieldID(23);
- try writer.writeValue(router);
- }
- try writer.endMessage();
- }
- };
+
+};
- pub const FileHandle = struct {
- /// path
- path: []const u8,
+pub const OutputFile = struct {
+/// data
+data: []const u8,
- /// size
- size: u32 = 0,
+/// path
+path: []const u8,
- /// fd
- fd: u32 = 0,
- pub fn decode(reader: anytype) anyerror!FileHandle {
- var this = std.mem.zeroes(FileHandle);
+pub fn decode(reader: anytype) anyerror!OutputFile {
+ var this = std.mem.zeroes(OutputFile);
- this.path = try reader.readValue([]const u8);
- this.size = try reader.readValue(u32);
- this.fd = try reader.readValue(u32);
- return this;
- }
+ this.data = try reader.readArray(u8);
+ this.path = try reader.readValue([]const u8);
+ 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.writeArray(u8, this.data);
+ try writer.writeValue(this.path);
+}
- pub const Transform = struct {
- /// handle
- handle: ?FileHandle = null,
+};
- /// path
- path: ?[]const u8 = null,
+pub const TransformResponse = struct {
+/// status
+status: TransformResponseStatus,
- /// contents
- contents: []const u8,
+/// files
+files: []const OutputFile,
- /// loader
- loader: ?Loader = null,
+/// errors
+errors: []const Message,
- /// options
- options: ?TransformOptions = null,
- pub fn decode(reader: anytype) anyerror!Transform {
- var this = std.mem.zeroes(Transform);
+pub fn decode(reader: anytype) anyerror!TransformResponse {
+ var this = std.mem.zeroes(TransformResponse);
- while (true) {
- switch (try reader.readByte()) {
- 0 => {
- return this;
- },
+ this.status = try reader.readValue(TransformResponseStatus);
+ this.files = try reader.readArray(OutputFile);
+ this.errors = try reader.readArray(Message);
+ 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;
- },
+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 const MessageKind = enum(u32) {
+
+_none,
+ /// err
+ err,
+
+ /// warn
+ warn,
+
+ /// note
+ note,
+
+ /// debug
+ debug,
+
+_,
+
+ pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
+ return try std.json.stringify(@tagName(self), opts, o);
}
- }
- 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 TransformResponseStatus = enum(u32) {
- _none,
- /// success
- success,
+pub const Location = struct {
+/// file
+file: []const u8,
- /// fail
- fail,
+/// namespace
+namespace: []const u8,
- _,
+/// line
+line: i32 = 0,
- pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
- return try std.json.stringify(@tagName(self), opts, o);
- }
- };
+/// column
+column: i32 = 0,
- pub const OutputFile = struct {
- /// data
- data: []const u8,
+/// line_text
+line_text: []const u8,
- /// path
- path: []const u8,
+/// suggestion
+suggestion: []const u8,
- pub fn decode(reader: anytype) anyerror!OutputFile {
- var this = std.mem.zeroes(OutputFile);
+/// offset
+offset: u32 = 0,
- this.data = try reader.readArray(u8);
- this.path = try reader.readValue([]const u8);
- 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 decode(reader: anytype) anyerror!Location {
+ var this = std.mem.zeroes(Location);
- pub const TransformResponse = struct {
- /// status
- status: TransformResponseStatus,
+ 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;
+}
- /// files
- files: []const OutputFile,
+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);
+}
- /// errors
- errors: []const Message,
+};
- pub fn decode(reader: anytype) anyerror!TransformResponse {
- var this = std.mem.zeroes(TransformResponse);
+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;
+}
- this.status = try reader.readValue(TransformResponseStatus);
- this.files = try reader.readArray(OutputFile);
- this.errors = try reader.readArray(Message);
- return this;
- }
+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 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 const MessageKind = enum(u32) {
- _none,
- /// err
- err,
+pub const Message = struct {
+/// kind
+kind: MessageKind,
- /// warn
- warn,
+/// data
+data: MessageData,
- /// note
- note,
+/// notes
+notes: []const MessageData,
- /// debug
- debug,
- _,
+pub fn decode(reader: anytype) anyerror!Message {
+ var this = std.mem.zeroes(Message);
- pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
- return try std.json.stringify(@tagName(self), opts, o);
- }
- };
+ this.kind = try reader.readValue(MessageKind);
+ this.data = try reader.readValue(MessageData);
+ this.notes = try reader.readArray(MessageData);
+ return this;
+}
- pub const Location = struct {
- /// file
- file: []const u8,
+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);
+}
- /// namespace
- namespace: []const u8,
+};
- /// line
- line: i32 = 0,
+pub const Log = struct {
+/// warnings
+warnings: u32 = 0,
- /// column
- column: i32 = 0,
+/// errors
+errors: u32 = 0,
- /// line_text
- line_text: []const u8,
+/// msgs
+msgs: []const Message,
- /// suggestion
- suggestion: []const u8,
- /// offset
- offset: u32 = 0,
+pub fn decode(reader: anytype) anyerror!Log {
+ var this = std.mem.zeroes(Log);
- pub fn decode(reader: anytype) anyerror!Location {
- var this = std.mem.zeroes(Location);
+ this.warnings = try reader.readValue(u32);
+ this.errors = try reader.readValue(u32);
+ this.msgs = try reader.readArray(Message);
+ return this;
+}
- 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.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.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 MessageData = struct {
- /// text
- text: ?[]const u8 = null,
+pub const Reloader = enum(u8) {
- /// location
- location: ?Location = null,
+_none,
+ /// disable
+ disable,
- pub fn decode(reader: anytype) anyerror!MessageData {
- var this = std.mem.zeroes(MessageData);
+ /// live
+ live,
- while (true) {
- switch (try reader.readByte()) {
- 0 => {
- return this;
- },
+ /// fast_refresh
+ fast_refresh,
- 1 => {
- this.text = try reader.readValue([]const u8);
- },
- 2 => {
- this.location = try reader.readValue(Location);
- },
- else => {
- return error.InvalidMessage;
- },
+_,
+
+ pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
+ return try std.json.stringify(@tagName(self), opts, o);
}
- }
- 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 Message = struct {
- /// kind
- kind: MessageKind,
+pub const WebsocketMessageKind = enum(u8) {
- /// data
- data: MessageData,
+_none,
+ /// welcome
+ welcome,
- /// notes
- notes: []const MessageData,
+ /// file_change_notification
+ file_change_notification,
- pub fn decode(reader: anytype) anyerror!Message {
- var this = std.mem.zeroes(Message);
+ /// build_success
+ build_success,
- this.kind = try reader.readValue(MessageKind);
- this.data = try reader.readValue(MessageData);
- this.notes = try reader.readArray(MessageData);
- return this;
- }
+ /// build_fail
+ build_fail,
- 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);
- }
- };
+ /// manifest_success
+ manifest_success,
- pub const Log = struct {
- /// warnings
- warnings: u32 = 0,
+ /// manifest_fail
+ manifest_fail,
- /// errors
- errors: u32 = 0,
+_,
- /// msgs
- msgs: []const Message,
+ 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!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 const WebsocketCommandKind = enum(u8) {
- 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);
- }
- };
+_none,
+ /// build
+ build,
- pub const Reloader = enum(u8) {
- _none,
- /// disable
- disable,
+ /// manifest
+ manifest,
- /// live
- live,
+_,
- /// fast_refresh
- fast_refresh,
+ 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,
- pub const WebsocketMessageKind = enum(u8) {
- _none,
- /// welcome
- welcome,
+/// kind
+kind: WebsocketMessageKind,
- /// file_change_notification
- file_change_notification,
- /// build_success
- build_success,
+pub fn decode(reader: anytype) anyerror!WebsocketMessage {
+ var this = std.mem.zeroes(WebsocketMessage);
- /// build_fail
- build_fail,
+ this.timestamp = try reader.readValue(u32);
+ this.kind = try reader.readValue(WebsocketMessageKind);
+ return this;
+}
- /// manifest_success
- manifest_success,
+pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeInt(this.timestamp);
+ try writer.writeEnum(this.kind);
+}
- /// manifest_fail
- manifest_fail,
+};
- _,
+pub const WebsocketMessageWelcome = struct {
+/// epoch
+epoch: u32 = 0,
- pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
- return try std.json.stringify(@tagName(self), opts, o);
- }
- };
+/// javascriptReloader
+javascript_reloader: Reloader,
- pub const WebsocketCommandKind = enum(u8) {
- _none,
- /// build
- build,
- /// manifest
- manifest,
+pub fn decode(reader: anytype) anyerror!WebsocketMessageWelcome {
+ var this = std.mem.zeroes(WebsocketMessageWelcome);
- _,
+ this.epoch = try reader.readValue(u32);
+ this.javascript_reloader = try reader.readValue(Reloader);
+ return this;
+}
- pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
- return try std.json.stringify(@tagName(self), opts, o);
- }
- };
+pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeInt(this.epoch);
+ try writer.writeEnum(this.javascript_reloader);
+}
- pub const WebsocketMessage = struct {
- /// timestamp
- timestamp: u32 = 0,
+};
- /// kind
- kind: WebsocketMessageKind,
+pub const WebsocketMessageFileChangeNotification = struct {
+/// id
+id: u32 = 0,
- pub fn decode(reader: anytype) anyerror!WebsocketMessage {
- var this = std.mem.zeroes(WebsocketMessage);
+/// loader
+loader: Loader,
- this.timestamp = try reader.readValue(u32);
- this.kind = try reader.readValue(WebsocketMessageKind);
- return this;
- }
- pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeInt(this.timestamp);
- try writer.writeEnum(this.kind);
- }
- };
+pub fn decode(reader: anytype) anyerror!WebsocketMessageFileChangeNotification {
+ var this = std.mem.zeroes(WebsocketMessageFileChangeNotification);
- pub const WebsocketMessageWelcome = struct {
- /// epoch
- epoch: u32 = 0,
+ this.id = try reader.readValue(u32);
+ this.loader = try reader.readValue(Loader);
+ return this;
+}
- /// javascriptReloader
- javascript_reloader: Reloader,
+pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeInt(this.id);
+ try writer.writeEnum(this.loader);
+}
- pub fn decode(reader: anytype) anyerror!WebsocketMessageWelcome {
- var this = std.mem.zeroes(WebsocketMessageWelcome);
+};
- this.epoch = try reader.readValue(u32);
- this.javascript_reloader = try reader.readValue(Reloader);
- return this;
- }
+pub const WebsocketCommand = struct {
+/// kind
+kind: WebsocketCommandKind,
- pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeInt(this.epoch);
- try writer.writeEnum(this.javascript_reloader);
- }
- };
+/// timestamp
+timestamp: u32 = 0,
- pub const WebsocketMessageFileChangeNotification = struct {
- /// id
- id: u32 = 0,
- /// loader
- loader: Loader,
+pub fn decode(reader: anytype) anyerror!WebsocketCommand {
+ var this = std.mem.zeroes(WebsocketCommand);
- pub fn decode(reader: anytype) anyerror!WebsocketMessageFileChangeNotification {
- var this = std.mem.zeroes(WebsocketMessageFileChangeNotification);
+ this.kind = try reader.readValue(WebsocketCommandKind);
+ this.timestamp = try reader.readValue(u32);
+ return this;
+}
- 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.writeEnum(this.kind);
+ try writer.writeInt(this.timestamp);
+}
- pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeInt(this.id);
- try writer.writeEnum(this.loader);
- }
- };
+};
- pub const WebsocketCommand = struct {
- /// kind
- kind: WebsocketCommandKind,
+pub const WebsocketCommandBuild = packed struct {
+/// id
+id: u32 = 0,
- /// timestamp
- timestamp: u32 = 0,
- pub fn decode(reader: anytype) anyerror!WebsocketCommand {
- var this = std.mem.zeroes(WebsocketCommand);
+pub fn decode(reader: anytype) anyerror!WebsocketCommandBuild {
+ var this = std.mem.zeroes(WebsocketCommandBuild);
- this.kind = try reader.readValue(WebsocketCommandKind);
- this.timestamp = try reader.readValue(u32);
- return this;
- }
+ this.id = try reader.readValue(u32);
+ return this;
+}
- pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeEnum(this.kind);
- try writer.writeInt(this.timestamp);
- }
- };
+pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeInt(this.id);
+}
- pub const WebsocketCommandBuild = packed struct {
- /// id
- id: u32 = 0,
+};
- pub fn decode(reader: anytype) anyerror!WebsocketCommandBuild {
- var this = std.mem.zeroes(WebsocketCommandBuild);
+pub const WebsocketCommandManifest = packed struct {
+/// id
+id: u32 = 0,
- this.id = try reader.readValue(u32);
- return this;
- }
- pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeInt(this.id);
- }
- };
+pub fn decode(reader: anytype) anyerror!WebsocketCommandManifest {
+ var this = std.mem.zeroes(WebsocketCommandManifest);
- pub const WebsocketCommandManifest = packed struct {
- /// id
- id: u32 = 0,
+ this.id = try reader.readValue(u32);
+ return this;
+}
- pub fn decode(reader: anytype) anyerror!WebsocketCommandManifest {
- var this = std.mem.zeroes(WebsocketCommandManifest);
+pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeInt(this.id);
+}
- this.id = try reader.readValue(u32);
- return this;
- }
+};
- pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeInt(this.id);
- }
- };
+pub const WebsocketMessageBuildSuccess = struct {
+/// id
+id: u32 = 0,
- pub const WebsocketMessageBuildSuccess = struct {
- /// id
- id: u32 = 0,
+/// from_timestamp
+from_timestamp: u32 = 0,
- /// from_timestamp
- from_timestamp: u32 = 0,
+/// loader
+loader: Loader,
- /// loader
- loader: Loader,
+/// module_path
+module_path: []const u8,
- /// module_path
- module_path: []const u8,
+/// blob_length
+blob_length: u32 = 0,
- /// blob_length
- blob_length: u32 = 0,
- pub fn decode(reader: anytype) anyerror!WebsocketMessageBuildSuccess {
- var this = std.mem.zeroes(WebsocketMessageBuildSuccess);
+pub fn decode(reader: anytype) anyerror!WebsocketMessageBuildSuccess {
+ var this = std.mem.zeroes(WebsocketMessageBuildSuccess);
- 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.blob_length = try reader.readValue(u32);
- 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.blob_length = try reader.readValue(u32);
+ 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.writeInt(this.blob_length);
- }
- };
+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.writeInt(this.blob_length);
+}
- pub const WebsocketMessageBuildFailure = struct {
- /// id
- id: u32 = 0,
+};
- /// from_timestamp
- from_timestamp: u32 = 0,
+pub const WebsocketMessageBuildFailure = struct {
+/// id
+id: u32 = 0,
- /// loader
- loader: Loader,
+/// from_timestamp
+from_timestamp: u32 = 0,
- /// module_path
- module_path: []const u8,
+/// loader
+loader: Loader,
- /// log
- log: Log,
+/// module_path
+module_path: []const u8,
- pub fn decode(reader: anytype) anyerror!WebsocketMessageBuildFailure {
- var this = std.mem.zeroes(WebsocketMessageBuildFailure);
+/// log
+log: Log,
- 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);
- }
- };
+pub fn decode(reader: anytype) anyerror!WebsocketMessageBuildFailure {
+ var this = std.mem.zeroes(WebsocketMessageBuildFailure);
- pub const DependencyManifest = struct {
- /// ids
- ids: []const u32,
+ 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 decode(reader: anytype) anyerror!DependencyManifest {
- var this = std.mem.zeroes(DependencyManifest);
+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);
+}
- this.ids = try reader.readArray(u32);
- return this;
- }
+};
- pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeArray(u32, this.ids);
- }
- };
+pub const DependencyManifest = struct {
+/// ids
+ids: []const u32,
- pub const FileList = struct {
- /// ptrs
- ptrs: []const StringPointer,
- /// files
- files: []const u8,
+pub fn decode(reader: anytype) anyerror!DependencyManifest {
+ var this = std.mem.zeroes(DependencyManifest);
- pub fn decode(reader: anytype) anyerror!FileList {
- var this = std.mem.zeroes(FileList);
+ this.ids = try reader.readArray(u32);
+ return this;
+}
- this.ptrs = try reader.readArray(StringPointer);
- this.files = try reader.readValue([]const u8);
- return this;
- }
+pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeArray(u32, this.ids);
+}
- pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeArray(StringPointer, this.ptrs);
- try writer.writeValue(this.files);
- }
- };
+};
- pub const WebsocketMessageResolveIDs = struct {
- /// id
- id: []const u32,
+pub const FileList = struct {
+/// ptrs
+ptrs: []const StringPointer,
- /// list
- list: FileList,
+/// files
+files: []const u8,
- pub fn decode(reader: anytype) anyerror!WebsocketMessageResolveIDs {
- var this = std.mem.zeroes(WebsocketMessageResolveIDs);
- this.id = try reader.readArray(u32);
- this.list = try reader.readValue(FileList);
- return this;
- }
+pub fn decode(reader: anytype) anyerror!FileList {
+ var this = std.mem.zeroes(FileList);
- pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeArray(u32, this.id);
- try writer.writeValue(this.list);
- }
- };
+ this.ptrs = try reader.readArray(StringPointer);
+ this.files = try reader.readValue([]const u8);
+ return this;
+}
- pub const WebsocketCommandResolveIDs = struct {
- /// ptrs
- ptrs: []const StringPointer,
+pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeArray(StringPointer, this.ptrs);
+ try writer.writeValue(this.files);
+}
- /// files
- files: []const u8,
+};
- pub fn decode(reader: anytype) anyerror!WebsocketCommandResolveIDs {
- var this = std.mem.zeroes(WebsocketCommandResolveIDs);
+pub const WebsocketMessageResolveIDs = struct {
+/// id
+id: []const u32,
- this.ptrs = try reader.readArray(StringPointer);
- this.files = try reader.readValue([]const u8);
- return this;
- }
+/// list
+list: FileList,
- pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeArray(StringPointer, this.ptrs);
- try writer.writeValue(this.files);
- }
- };
- pub const WebsocketMessageManifestSuccess = struct {
- /// id
- id: u32 = 0,
+pub fn decode(reader: anytype) anyerror!WebsocketMessageResolveIDs {
+ var this = std.mem.zeroes(WebsocketMessageResolveIDs);
- /// module_path
- module_path: []const u8,
+ this.id = try reader.readArray(u32);
+ this.list = try reader.readValue(FileList);
+ return this;
+}
- /// loader
- loader: Loader,
+pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeArray(u32, this.id);
+ try writer.writeValue(this.list);
+}
- /// manifest
- manifest: DependencyManifest,
+};
- pub fn decode(reader: anytype) anyerror!WebsocketMessageManifestSuccess {
- var this = std.mem.zeroes(WebsocketMessageManifestSuccess);
+pub const WebsocketCommandResolveIDs = struct {
+/// ptrs
+ptrs: []const StringPointer,
- this.id = try reader.readValue(u32);
- this.module_path = try reader.readValue([]const u8);
- this.loader = try reader.readValue(Loader);
- this.manifest = try reader.readValue(DependencyManifest);
- return this;
- }
+/// files
+files: []const u8,
- pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
- try writer.writeInt(this.id);
- try writer.writeValue(this.module_path);
- try writer.writeEnum(this.loader);
- try writer.writeValue(this.manifest);
- }
- };
- pub const WebsocketMessageManifestFailure = struct {
- /// id
- id: u32 = 0,
+pub fn decode(reader: anytype) anyerror!WebsocketCommandResolveIDs {
+ var this = std.mem.zeroes(WebsocketCommandResolveIDs);
+
+ this.ptrs = try reader.readArray(StringPointer);
+ this.files = try reader.readValue([]const u8);
+ return this;
+}
- /// from_timestamp
- from_timestamp: u32 = 0,
+pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeArray(StringPointer, this.ptrs);
+ try writer.writeValue(this.files);
+}
- /// loader
- loader: Loader,
+};
- /// log
- log: Log,
+pub const WebsocketMessageManifestSuccess = struct {
+/// id
+id: u32 = 0,
- pub fn decode(reader: anytype) anyerror!WebsocketMessageManifestFailure {
- var this = std.mem.zeroes(WebsocketMessageManifestFailure);
+/// module_path
+module_path: []const u8,
- this.id = try reader.readValue(u32);
- this.from_timestamp = try reader.readValue(u32);
- this.loader = try reader.readValue(Loader);
- this.log = try reader.readValue(Log);
- return this;
- }
+/// loader
+loader: Loader,
+
+/// manifest
+manifest: DependencyManifest,
+
+
+pub fn decode(reader: anytype) anyerror!WebsocketMessageManifestSuccess {
+ var this = std.mem.zeroes(WebsocketMessageManifestSuccess);
+
+ this.id = try reader.readValue(u32);
+ this.module_path = try reader.readValue([]const u8);
+ this.loader = try reader.readValue(Loader);
+ this.manifest = try reader.readValue(DependencyManifest);
+ return this;
+}
+
+pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeInt(this.id);
+ try writer.writeValue(this.module_path);
+ try writer.writeEnum(this.loader);
+ try writer.writeValue(this.manifest);
+}
- 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.log);
- }
- };
};
+pub const WebsocketMessageManifestFailure = struct {
+/// id
+id: u32 = 0,
+
+/// from_timestamp
+from_timestamp: u32 = 0,
+
+/// loader
+loader: Loader,
+
+/// log
+log: Log,
+
+
+pub fn decode(reader: anytype) anyerror!WebsocketMessageManifestFailure {
+ var this = std.mem.zeroes(WebsocketMessageManifestFailure);
+
+ this.id = try reader.readValue(u32);
+ this.from_timestamp = try reader.readValue(u32);
+ this.loader = try reader.readValue(Loader);
+ 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.log);
+}
+
+};
+
+
+};
+
+
const ExamplePackedStruct = packed struct {
len: u32 = 0,
offset: u32 = 0,
diff --git a/src/env_loader.zig b/src/env_loader.zig
new file mode 100644
index 000000000..9a4c6dde7
--- /dev/null
+++ b/src/env_loader.zig
@@ -0,0 +1,330 @@
+const std = @import("std");
+const logger = @import("./logger.zig");
+usingnamespace @import("./global.zig");
+const CodepointIterator = @import("./string_immutable.zig").CodepointIterator;
+
+const Variable = struct {
+ key: string,
+ value: string,
+};
+
+// i don't expect anyone to actually use the escape line feed character
+const escLineFeed = 0x0C;
+// arbitrary character that is invalid in a real text file
+const implicitQuoteCharacter = 8;
+
+pub const Lexer = struct {
+ source: *const logger.Source,
+ iter: CodepointIterator,
+ _codepoint: CodePoint = 0,
+ current: usize = 0,
+ start: usize = 0,
+ end: usize = 0,
+ has_nested_values: bool = false,
+ has_newline_before: bool = true,
+
+ pub inline fn codepoint(this: *Lexer) CodePoint {
+ return this._codepoint;
+ }
+
+ pub fn step(this: *Lexer) void {
+ @call(.{ .modifier = .always_inline }, CodepointIterator.nextCodepointNoReturn, .{&this.iter});
+ this._codepoint = this.iter.c;
+ this.current += 1;
+ }
+
+ pub fn eatValue(
+ lexer: *Lexer,
+ comptime quote: CodePoint,
+ ) string {
+ const start = lexer.current - 1;
+ lexer.step();
+
+ var last_non_space: usize = 0;
+ while (true) {
+ switch (lexer.codepoint()) {
+ '\\' => {
+ lexer.step();
+ // Handle Windows CRLF
+ last_non_space += 1;
+ if (lexer.codepoint() == '\r') {
+ lexer.step();
+ last_non_space += 1;
+ if (lexer.codepoint() == '\n') {
+ lexer.step();
+ last_non_space += 1;
+ }
+ continue;
+ }
+ },
+ -1 => {
+ lexer.end = lexer.current;
+
+ return lexer.source.contents[start..][0 .. last_non_space + 1];
+ },
+ '$' => {
+ lexer.has_nested_values = true;
+ last_non_space += 1;
+ },
+
+ '#' => {
+ lexer.step();
+ lexer.eatComment();
+
+ return lexer.source.contents[start..][0 .. last_non_space + 1];
+ },
+
+ '\n', '\r', escLineFeed => {
+ switch (comptime quote) {
+ '\'' => {
+ lexer.end = lexer.current;
+ lexer.step();
+ return lexer.source.contents[start .. lexer.end - 1];
+ },
+ implicitQuoteCharacter => {
+ lexer.end = lexer.current;
+ lexer.step();
+
+ return lexer.source.contents[start..][0 .. last_non_space + 1];
+ },
+ '"' => {
+ // We keep going
+
+ },
+ else => {},
+ }
+ },
+ quote => {
+ lexer.end = lexer.current;
+ lexer.step();
+ return lexer.source.contents[start..lexer.end];
+ },
+ ' ' => {},
+ else => {
+ last_non_space += 1;
+ },
+ }
+
+ lexer.step();
+ }
+ unreachable;
+ }
+
+ pub fn eatComment(this: *Lexer) void {
+ while (true) {
+ switch (this.codepoint()) {
+ '\r' => {
+ this.step();
+ if (this.codepoint() == '\n') {
+ return;
+ }
+ },
+ '\n' => {
+ this.step();
+ return;
+ },
+ -1 => {
+ return;
+ },
+ else => {
+ this.step();
+ },
+ }
+ }
+ }
+
+ // const NEWLINE = '\n'
+ // const RE_INI_KEY_VAL = /^\s*([\w.-]+)\s*=\s*(.*)?\s*$/
+ // const RE_NEWLINES = /\\n/g
+ // const NEWLINES_MATCH = /\r\n|\n|\r/
+ pub fn next(this: *Lexer) ?Variable {
+ if (this.end == 0) this.step();
+
+ const start = this.start;
+
+ this.has_newline_before = this.end == 0;
+
+ restart: while (true) {
+ switch (this.codepoint()) {
+ 0, -1 => {
+ return null;
+ },
+ '#' => {
+ this.step();
+
+ this.eatComment();
+ continue :restart;
+ },
+ '\r', '\n', 0x2028, 0x2029 => {
+ this.step();
+ this.has_newline_before = true;
+ continue;
+ },
+
+ // Valid keys:
+ 'a'...'z', 'A'...'Z', '0'...'9', '_', '-', '.' => {
+ this.start = this.current - 1;
+ this.step();
+ var last_non_space: usize = 0;
+ while (true) {
+ switch (this.codepoint()) {
+
+ // to match npm's "dotenv" behavior, we ignore lines that don't have an equals
+ '\r', '\n', escLineFeed => {
+ this.end = this.current;
+ this.step();
+ continue :restart;
+ },
+ 0, -1 => {
+ this.end = this.current;
+ return Variable{ .key = this.source.contents[this.start..][0 .. last_non_space + 1], .value = "" };
+ },
+ 'a'...'z', 'A'...'Z', '0'...'9', '_', '-', '.' => {
+ last_non_space += 1;
+ },
+ '=' => {
+ this.end = this.current;
+ const key = this.source.contents[this.start..][0 .. last_non_space + 1];
+ if (key.len == 0) return null;
+ this.step();
+
+ inner: while (true) {
+ switch (this.codepoint()) {
+ '"' => {
+ const value = this.eatValue('"');
+ return Variable{ .key = key, .value = value };
+ },
+ '\'' => {
+ const value = this.eatValue('\'');
+ return Variable{ .key = key, .value = value };
+ },
+ 0, -1 => {
+ return Variable{ .key = key, .value = "" };
+ },
+ '\r', '\n', escLineFeed => {
+ this.step();
+ return Variable{ .key = key, .value = "" };
+ },
+ // consume unquoted leading spaces
+ ' ' => {
+ this.step();
+ continue :inner;
+ },
+ // we treat everything else the same as if it were wrapped in single quotes
+ // except we don't terminate on that character
+ else => {
+ const value = this.eatValue(implicitQuoteCharacter);
+ return Variable{ .key = key, .value = value };
+ },
+ }
+ }
+ },
+ ' ' => {},
+ else => {
+ last_non_space += 1;
+ },
+ }
+ this.step();
+ }
+ },
+ else => {},
+ }
+
+ this.step();
+ }
+ }
+
+ pub fn init(source: *const logger.Source) Lexer {
+ return Lexer{
+ .source = source,
+ .iter = CodepointIterator{ .bytes = source.contents, .i = 0 },
+ };
+ }
+};
+
+pub const Parser = struct {
+ pub fn parse(source: *const logger.Source, allocator: *std.mem.Allocator) Map {
+ var map = Map.init(allocator);
+
+ var lexer = Lexer.init(source);
+ while (lexer.next()) |variable| {
+ map.put(variable.key, variable.value) catch {};
+ }
+
+ return map;
+ }
+};
+
+pub const Map = struct {
+ const HashTable = std.StringArrayHashMap(string);
+
+ map: HashTable,
+
+ pub inline fn init(allocator: *std.mem.Allocator) Map {
+ return Map{ .map = HashTable.init(allocator) };
+ }
+
+ pub inline fn iter(this: *Map) !HashTable.Iterator {
+ return this.map.iterator();
+ }
+
+ pub inline fn put(this: *Map, key: string, value: string) !void {
+ try this.map.put(key, value);
+ }
+
+ pub inline fn get(
+ this: *const Map,
+ key: string,
+ ) ?string {
+ return this.map.get(key);
+ }
+
+ pub inline fn putDefault(this: *Map, key: string, value: string) !void {
+ _ = try this.map.getOrPutValue(key, value);
+ }
+};
+
+const expectString = std.testing.expectEqualStrings;
+const expect = std.testing.expect;
+test "DotEnv Loader" {
+ const VALID_ENV =
+ \\API_KEY=verysecure
+ \\process.env.WAT=ABCDEFGHIJKLMNOPQRSTUVWXYZZ10239457123
+ \\DOUBLE-QUOTED_SHOULD_PRESERVE_NEWLINES="
+ \\ya
+ \\"
+ \\DOUBLE_QUOTES_ESCAPABLE="\"yoooo\""
+ \\SINGLE_QUOTED_SHOULDNT_PRESERVE_NEWLINES='yo
+ \\'
+ \\
+ \\SINGLE_QUOTED_PRESERVES_QUOTES='yo'
+ \\
+ \\# Line Comment
+ \\UNQUOTED_SHOULDNT_PRESERVE_NEWLINES_AND_TRIMS_TRAILING_SPACE=yo # Inline Comment
+ \\
+ \\ LEADING_SPACE_IS_TRIMMED=yes
+ \\
+ \\LEADING_SPACE_IN_UNQUOTED_VALUE_IS_TRIMMED= yes
+ \\
+ \\LINES_WITHOUT_EQUAL_ARE_IGNORED
+ \\
+ \\NO_VALUE_IS_EMPTY_STRING=
+ \\LINES_WITHOUT_EQUAL_ARE_IGNORED
+ \\
+ \\IGNORING_DOESNT_BREAK_OTHER_LINES='yes'
+ \\
+ ;
+ const source = logger.Source.initPathString(".env", VALID_ENV);
+ const map = Parser.parse(&source, std.heap.c_allocator);
+ try expectString(map.get("API_KEY").?, "verysecure");
+ try expectString(map.get("process.env.WAT").?, "ABCDEFGHIJKLMNOPQRSTUVWXYZZ10239457123");
+ try expectString(map.get("DOUBLE-QUOTED_SHOULD_PRESERVE_NEWLINES").?, "\"\nya\n\"");
+ try expectString(map.get("SINGLE_QUOTED_SHOULDNT_PRESERVE_NEWLINES").?, "'yo");
+ try expectString(map.get("SINGLE_QUOTED_PRESERVES_QUOTES").?, "'yo'");
+ try expectString(map.get("UNQUOTED_SHOULDNT_PRESERVE_NEWLINES_AND_TRIMS_TRAILING_SPACE").?, "yo");
+ try expect(map.get("LINES_WITHOUT_EQUAL_ARE_IGNORED") == null);
+ try expectString(map.get("LEADING_SPACE_IS_TRIMMED").?, "yes");
+ try expect(map.get("NO_VALUE_IS_EMPTY_STRING").?.len == 0);
+ try expectString(map.get("IGNORING_DOESNT_BREAK_OTHER_LINES").?, "'yes'");
+ try expectString(map.get("LEADING_SPACE_IN_UNQUOTED_VALUE_IS_TRIMMED").?, "yes");
+}
diff --git a/src/feature_flags.zig b/src/feature_flags.zig
index f2fa69884..3cbd5787a 100644
--- a/src/feature_flags.zig
+++ b/src/feature_flags.zig
@@ -34,6 +34,7 @@ pub const css_supports_fence = true;
pub const disable_entry_cache = false;
pub const enable_bytecode_caching = false;
+pub const react_specific_warnings = true;
// Disabled due to concurrency bug I don't have time to fix right now.
// I suspect it's like 3 undefined memory issues.
// This was the command I ran to reproduce it:
diff --git a/src/http.zig b/src/http.zig
index ffb7a3d72..b60487fbc 100644
--- a/src/http.zig
+++ b/src/http.zig
@@ -134,8 +134,8 @@ pub const RequestContext = struct {
pub fn getFullURL(this: *RequestContext) [:0]const u8 {
if (this.full_url.len == 0) {
- if (this.bundler.options.origin.len > 0) {
- this.full_url = std.fmt.allocPrintZ(this.allocator, "{s}{s}", .{ this.bundler.options.origin, this.request.path }) catch unreachable;
+ if (this.bundler.options.origin.isAbsolute()) {
+ this.full_url = std.fmt.allocPrintZ(this.allocator, "{s}{s}", .{ this.bundler.options.origin.origin, this.request.path }) catch unreachable;
} else {
this.full_url = this.allocator.dupeZ(u8, this.request.path) catch unreachable;
}
@@ -733,6 +733,7 @@ pub const RequestContext = struct {
Output.flush();
return;
};
+ vm.bundler.configureRouter() catch {};
std.debug.assert(JavaScript.VirtualMachine.vm_loaded);
javascript_vm = vm;
@@ -740,62 +741,67 @@ pub const RequestContext = struct {
std.debug.assert(boot.len > 0);
defer vm.deinit();
vm.watcher = handler.watcher;
- var entry_point = boot;
- if (!std.fs.path.isAbsolute(entry_point)) {
- const resolved_entry_point = try vm.bundler.resolver.resolve(
- std.fs.path.dirname(boot) orelse vm.bundler.fs.top_level_dir,
- vm.bundler.normalizeEntryPointPath(boot),
- .entry_point,
- );
- entry_point = resolved_entry_point.path_pair.primary.text;
- }
-
- var load_result = vm.loadEntryPoint(
- entry_point,
- ) catch |err| {
- Output.prettyErrorln(
- "<r>JavaScript VM failed to start.\n<red>{s}:<r> while loading <r><b>\"\"",
- .{ @errorName(err), entry_point },
- );
-
- if (channel.tryReadItem() catch null) |item| {
- item.ctx.sendInternalError(error.JSFailedToStart) catch {};
- item.ctx.arena.deinit();
+ {
+ defer vm.flush();
+
+ var entry_point = boot;
+ if (!std.fs.path.isAbsolute(entry_point)) {
+ const resolved_entry_point = try vm.bundler.resolver.resolve(
+ std.fs.path.dirname(boot) orelse vm.bundler.fs.top_level_dir,
+ vm.bundler.normalizeEntryPointPath(boot),
+ .entry_point,
+ );
+ entry_point = resolved_entry_point.path_pair.primary.text;
}
- return;
- };
- switch (load_result.status(vm.global.vm())) {
- JSPromise.Status.Fulfilled => {},
- else => {
+ var load_result = vm.loadEntryPoint(
+ entry_point,
+ ) catch |err| {
Output.prettyErrorln(
- "JavaScript VM failed to start",
- .{},
+ "<r>JavaScript VM failed to start.\n<red>{s}:<r> while loading <r><b>\"\"",
+ .{ @errorName(err), entry_point },
);
- var result = load_result.result(vm.global.vm());
-
- vm.defaultErrorHandler(result);
if (channel.tryReadItem() catch null) |item| {
item.ctx.sendInternalError(error.JSFailedToStart) catch {};
item.ctx.arena.deinit();
}
return;
- },
- }
+ };
+
+ switch (load_result.status(vm.global.vm())) {
+ JSPromise.Status.Fulfilled => {},
+ else => {
+ Output.prettyErrorln(
+ "JavaScript VM failed to start",
+ .{},
+ );
+ var result = load_result.result(vm.global.vm());
+
+ vm.defaultErrorHandler(result);
- if (vm.event_listeners.count() == 0) {
- Output.prettyErrorln("<r><red>error<r>: Framework didn't run <b><cyan>addEventListener(\"fetch\", callback)<r>, which means it can't accept HTTP requests.\nShutting down JS.", .{});
- if (channel.tryReadItem() catch null) |item| {
- item.ctx.sendInternalError(error.JSFailedToStart) catch {};
- item.ctx.arena.deinit();
+ if (channel.tryReadItem() catch null) |item| {
+ item.ctx.sendInternalError(error.JSFailedToStart) catch {};
+ item.ctx.arena.deinit();
+ }
+ return;
+ },
+ }
+
+ if (vm.event_listeners.count() == 0) {
+ Output.prettyErrorln("<r><red>error<r>: Framework didn't run <b><cyan>addEventListener(\"fetch\", callback)<r>, which means it can't accept HTTP requests.\nShutting down JS.", .{});
+ if (channel.tryReadItem() catch null) |item| {
+ item.ctx.sendInternalError(error.JSFailedToStart) catch {};
+ item.ctx.arena.deinit();
+ }
+ return;
}
- return;
}
js_ast.Stmt.Data.Store.reset();
js_ast.Expr.Data.Store.reset();
JavaScript.Wundle.flushCSSImports();
+ vm.flush();
try runLoop(vm);
}
@@ -805,6 +811,7 @@ pub const RequestContext = struct {
while (true) {
defer {
+ JavaScript.VirtualMachine.vm.flush();
std.debug.assert(ZigGlobalObject.resetModuleRegistryMap(vm.global, module_map));
js_ast.Stmt.Data.Store.reset();
js_ast.Expr.Data.Store.reset();
@@ -1573,7 +1580,7 @@ pub const RequestContext = struct {
break :brk try ctx.bundler.buildFile(
&ctx.log,
ctx.allocator,
- ctx.url.pathWithoutOrigin(ctx.bundler.options.origin),
+ ctx.url.pathWithoutAssetPrefix(ctx.bundler.options.routes.asset_prefix_path),
ctx.url.extname,
true,
);
@@ -1581,7 +1588,7 @@ pub const RequestContext = struct {
break :brk try ctx.bundler.buildFile(
&ctx.log,
ctx.allocator,
- ctx.url.pathWithoutOrigin(ctx.bundler.options.origin),
+ ctx.url.pathWithoutAssetPrefix(ctx.bundler.options.routes.asset_prefix_path),
ctx.url.extname,
false,
);
@@ -1743,7 +1750,16 @@ pub const Server = struct {
// try listener.ack(true);
- try listener.bind(ip.Address.initIPv4(IPv4.unspecified, 9000));
+ var port: u16 = 3000;
+
+ if (server.bundler.options.origin.getPort()) |_port| {
+ port = _port;
+ }
+
+ try listener.bind(ip.Address.initIPv4(
+ IPv4.unspecified,
+ port,
+ ));
try listener.listen(1280);
const addr = try listener.getLocalAddress();
diff --git a/src/http/url_path.zig b/src/http/url_path.zig
index e82d5601a..0a4d35069 100644
--- a/src/http/url_path.zig
+++ b/src/http/url_path.zig
@@ -14,11 +14,11 @@ const toMutable = allocators.constStrToU8;
// TODO: use a real URL parser
// this treats a URL like /_next/ identically to /
-pub fn pathWithoutOrigin(this: *const URLPath, _origin: string) string {
- if (_origin.len == 0) return this.path;
- const leading_slash_offset: usize = if (_origin[0] == '/') 1 else 0;
+pub fn pathWithoutAssetPrefix(this: *const URLPath, asset_prefix: string) string {
+ if (asset_prefix.len == 0) return this.path;
+ const leading_slash_offset: usize = if (asset_prefix[0] == '/') 1 else 0;
const base = this.path;
- const origin = _origin[leading_slash_offset..];
+ const origin = asset_prefix[leading_slash_offset..];
return if (base.len >= origin.len and strings.eql(base[0..origin.len], origin)) base[origin.len..] else base;
}
diff --git a/src/javascript/jsc/api/router.zig b/src/javascript/jsc/api/router.zig
index 84562fee3..647dee2ea 100644
--- a/src/javascript/jsc/api/router.zig
+++ b/src/javascript/jsc/api/router.zig
@@ -358,6 +358,29 @@ pub fn createQueryObject(ctx: js.JSContextRef, map: *QueryStringMap, exception:
}
threadlocal var entry_point_tempbuf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
+pub fn getScriptSrcString(
+ comptime Writer: type,
+ writer: Writer,
+ file_path: string,
+ client_framework_enabled: bool,
+) void {
+ // We don't store the framework config including the client parts in the server
+ // instead, we just store a boolean saying whether we should generate this whenever the script is requested
+ // this is kind of bad. we should consider instead a way to inline the contents of the script.
+ if (client_framework_enabled) {
+ JavaScript.Wundle.getPublicPath(
+ Bundler.ClientEntryPoint.generateEntryPointPath(
+ &entry_point_tempbuf,
+ Fs.PathName.init(file_path),
+ ),
+ ScriptSrcStream.Writer,
+ writer,
+ );
+ } else {
+ JavaScript.Wundle.getPublicPath(file_path, ScriptSrcStream.Writer, writer);
+ }
+}
+
pub fn getScriptSrc(
this: *Router,
ctx: js.JSContextRef,
@@ -366,22 +389,7 @@ pub fn getScriptSrc(
exception: js.ExceptionRef,
) js.JSValueRef {
const src = this.script_src orelse brk: {
- // We don't store the framework config including the client parts in the server
- // instead, we just store a boolean saying whether we should generate this whenever the script is requested
- // this is kind of bad. we should consider instead a way to inline the contents of the script.
- var writer = this.script_src_buf_writer.writer();
- if (this.route.client_framework_enabled) {
- JavaScript.Wundle.getPublicPath(
- Bundler.ClientEntryPoint.generateEntryPointPath(
- &entry_point_tempbuf,
- Fs.PathName.init(this.route.file_path),
- ),
- ScriptSrcStream.Writer,
- writer,
- );
- } else {
- JavaScript.Wundle.getPublicPath(this.route.file_path, ScriptSrcStream.Writer, writer);
- }
+ getScriptSrcString(ScriptSrcStream.Writer, this.script_src_buf_writer.writer(), this.route.file_path, this.route.client_framework_enabled);
break :brk this.script_src_buf[0..this.script_src_buf_writer.pos];
};
diff --git a/src/javascript/jsc/javascript.zig b/src/javascript/jsc/javascript.zig
index 0b96ca3ed..9945b9283 100644
--- a/src/javascript/jsc/javascript.zig
+++ b/src/javascript/jsc/javascript.zig
@@ -39,6 +39,8 @@ pub const Wundle = struct {
threadlocal var css_imports_buf: std.ArrayList(u8) = undefined;
threadlocal var css_imports_buf_loaded: bool = false;
+ threadlocal var routes_list_strings: [1024]ZigString = undefined;
+
pub fn onImportCSS(
resolve_result: *const Resolver.Result,
import_record: *ImportRecord,
@@ -97,7 +99,7 @@ pub const Wundle = struct {
prop: js.JSStringRef,
exception: js.ExceptionRef,
) js.JSValueRef {
- return ZigString.init(VirtualMachine.vm.bundler.options.origin).toValue(VirtualMachine.vm.global).asRef();
+ return ZigString.init(VirtualMachine.vm.bundler.options.origin.origin).toValue(VirtualMachine.vm.global).asRef();
}
pub fn getMain(
@@ -110,28 +112,24 @@ pub const Wundle = struct {
return ZigString.init(VirtualMachine.vm.main).toValue(VirtualMachine.vm.global).asRef();
}
- pub fn getRoutesDir(
+ pub fn getAssetPrefix(
this: void,
ctx: js.JSContextRef,
thisObject: js.JSValueRef,
prop: js.JSStringRef,
exception: js.ExceptionRef,
) js.JSValueRef {
- if (!VirtualMachine.vm.bundler.options.routes.routes_enabled or VirtualMachine.vm.bundler.options.routes.dir.len == 0) {
- return js.JSValueMakeUndefined(ctx);
- }
-
- return ZigString.init(VirtualMachine.vm.bundler.options.routes.dir).toValue(VirtualMachine.vm.global).asRef();
+ return ZigString.init(VirtualMachine.vm.bundler.options.routes.asset_prefix_path).toValue(VirtualMachine.vm.global).asRef();
}
- pub fn routeByName(
+ pub fn getRoutesDir(
this: void,
ctx: js.JSContextRef,
thisObject: js.JSValueRef,
prop: js.JSStringRef,
exception: js.ExceptionRef,
) js.JSValueRef {
- if (!VirtualMachine.vm.bundler.options.routes.routes_enabled) {
+ if (!VirtualMachine.vm.bundler.options.routes.routes_enabled or VirtualMachine.vm.bundler.options.routes.dir.len == 0) {
return js.JSValueMakeUndefined(ctx);
}
@@ -155,15 +153,39 @@ pub const Wundle = struct {
return JSValue.createStringArray(VirtualMachine.vm.global, styles.ptr, styles.len).asRef();
}
+ pub fn getRouteFiles(
+ this: void,
+ ctx: js.JSContextRef,
+ function: js.JSObjectRef,
+ thisObject: js.JSObjectRef,
+ arguments: []const js.JSValueRef,
+ exception: js.ExceptionRef,
+ ) js.JSValueRef {
+ if (VirtualMachine.vm.bundler.router == null) return js.JSValueMakeNull(ctx);
+
+ const router = &(VirtualMachine.vm.bundler.router orelse unreachable);
+ const list = router.getEntryPointsWithBuffer(VirtualMachine.vm.allocator, false) catch unreachable;
+ VirtualMachine.vm.flush_list.append(list.buffer) catch {};
+ defer VirtualMachine.vm.allocator.free(list.entry_points);
+
+ for (routes_list_strings[0..std.math.min(list.entry_points.len, routes_list_strings.len)]) |_, i| {
+ routes_list_strings[i] = ZigString.init(list.entry_points[i]);
+ }
+
+ const ref = JSValue.createStringArray(VirtualMachine.vm.global, &routes_list_strings, list.entry_points.len).asRef();
+ return ref;
+ }
+
pub fn getPublicPath(to: string, comptime Writer: type, writer: Writer) void {
const relative_path = VirtualMachine.vm.bundler.fs.relativeTo(to);
- if (VirtualMachine.vm.bundler.options.origin.len > 0) {
- writer.print(
- "{s}/{s}",
- .{
- std.mem.trimRight(u8, VirtualMachine.vm.bundler.options.origin, "/"),
- std.mem.trimLeft(u8, relative_path, "/"),
- },
+ if (VirtualMachine.vm.bundler.options.origin.isAbsolute()) {
+ VirtualMachine.vm.bundler.options.origin.joinWrite(
+ Writer,
+ writer,
+ VirtualMachine.vm.bundler.options.routes.asset_prefix_path,
+ "",
+ relative_path,
+ "",
) catch unreachable;
} else {
writer.writeAll(std.mem.trimLeft(u8, relative_path, "/")) catch unreachable;
@@ -194,6 +216,13 @@ pub const Wundle = struct {
.@"return" = "string[]",
},
},
+ .getRouteFiles = .{
+ .rfn = Wundle.getRouteFiles,
+ .ts = d.ts{
+ .name = "getRouteFiles",
+ .@"return" = "string[]",
+ },
+ },
},
.{
.Route = Router.Instance.GetClass(void){},
@@ -213,6 +242,10 @@ pub const Wundle = struct {
.get = getRoutesDir,
.ts = d.ts{ .name = "routesDir", .@"return" = "string" },
},
+ .assetPrefix = .{
+ .get = getAssetPrefix,
+ .ts = d.ts{ .name = "assetPrefix", .@"return" = "string" },
+ },
},
);
};
@@ -240,6 +273,8 @@ pub const VirtualMachine = struct {
main: string = "",
process: js.JSObjectRef = null,
+ flush_list: std.ArrayList(string),
+
pub var vm_loaded = false;
pub var vm: *VirtualMachine = undefined;
@@ -274,6 +309,7 @@ pub const VirtualMachine = struct {
.console = console,
.node_modules = bundler.options.node_modules_bundle,
.log = log,
+ .flush_list = std.ArrayList(string).init(allocator),
};
VirtualMachine.vm.bundler.configureLinker();
@@ -305,6 +341,13 @@ pub const VirtualMachine = struct {
threadlocal var source_code_printer: js_printer.BufferPrinter = undefined;
threadlocal var source_code_printer_loaded: bool = false;
+ pub fn flush(this: *VirtualMachine) void {
+ for (this.flush_list.items) |item| {
+ this.allocator.free(item);
+ }
+ this.flush_list.shrinkRetainingCapacity(0);
+ }
+
inline fn _fetch(
global: *JSGlobalObject,
_specifier: string,
@@ -537,12 +580,23 @@ pub const VirtualMachine = struct {
res.* = ErrorableZigString.ok(ZigString.init(result.path));
}
- pub fn normalizeSpecifier(slice: string) string {
+ pub fn normalizeSpecifier(slice_: string) string {
+ var slice = slice_;
if (slice.len == 0) return slice;
- if (VirtualMachine.vm.bundler.options.origin.len > 0) {
- if (strings.startsWith(slice, VirtualMachine.vm.bundler.options.origin)) {
- return slice[VirtualMachine.vm.bundler.options.origin.len..];
+ if (strings.startsWith(slice, VirtualMachine.vm.bundler.options.origin.host)) {
+ slice = slice[VirtualMachine.vm.bundler.options.origin.host.len..];
+ }
+
+ if (VirtualMachine.vm.bundler.options.origin.path.len > 1) {
+ if (strings.startsWith(slice, VirtualMachine.vm.bundler.options.origin.path)) {
+ slice = slice[VirtualMachine.vm.bundler.options.origin.path.len..];
+ }
+ }
+
+ if (VirtualMachine.vm.bundler.options.routes.asset_prefix_path.len > 0) {
+ if (strings.startsWith(slice, VirtualMachine.vm.bundler.options.routes.asset_prefix_path)) {
+ slice = slice[VirtualMachine.vm.bundler.options.routes.asset_prefix_path.len..];
}
}
@@ -561,6 +615,15 @@ pub const VirtualMachine = struct {
return;
}
+ if (log.warnings > 0) {
+ var writer = Output.errorWriter();
+ for (log.msgs.items) |msg| {
+ if (msg.kind == .warn) {
+ msg.writeFormat(writer) catch {};
+ }
+ }
+ }
+
ret.result.value = result;
ret.success = true;
}
diff --git a/src/js_ast.zig b/src/js_ast.zig
index 8797e4c62..8e388a103 100644
--- a/src/js_ast.zig
+++ b/src/js_ast.zig
@@ -1042,7 +1042,7 @@ pub const E = struct {
};
pub const Object = struct {
- properties: []G.Property,
+ properties: []G.Property = &[_]G.Property{},
comma_after_spread: ?logger.Loc = null,
is_single_line: bool = false,
is_parenthesized: bool = false,
@@ -2098,6 +2098,44 @@ pub const Expr = struct {
}
}
+ pub fn joinAllWithCommaCallback(all: []Expr, comptime Context: type, ctx: Context, callback: (fn (ctx: anytype, expr: anytype) ?Expr), allocator: *std.mem.Allocator) ?Expr {
+ std.debug.assert(all.len > 0);
+ switch (all.len) {
+ 1 => {
+ return callback(ctx, all[0]);
+ },
+ 2 => {
+ return Expr.joinWithComma(
+ callback(ctx, all[0]) orelse Expr{
+ .data = .{ .e_missing = .{} },
+ .loc = all[0].loc,
+ },
+ callback(ctx, all[1]) orelse Expr{
+ .data = .{ .e_missing = .{} },
+ .loc = all[1].loc,
+ },
+ allocator,
+ );
+ },
+ else => {
+ var i: usize = 1;
+ var expr = callback(ctx, all[0]) orelse Expr{
+ .data = .{ .e_missing = .{} },
+ .loc = all[0].loc,
+ };
+
+ while (i < all.len) : (i += 1) {
+ expr = Expr.joinWithComma(expr, callback(ctx, all[i]) orelse Expr{
+ .data = .{ .e_missing = .{} },
+ .loc = all[i].loc,
+ }, allocator);
+ }
+
+ return expr;
+ },
+ }
+ }
+
pub fn jsonStringify(self: *const @This(), options: anytype, writer: anytype) !void {
return try std.json.stringify(Serializable{ .@"type" = std.meta.activeTag(self.data), .object = "expr", .value = self.data, .loc = self.loc }, options, writer);
}
diff --git a/src/js_lexer.zig b/src/js_lexer.zig
index a687739d4..ee80c6fb6 100644
--- a/src/js_lexer.zig
+++ b/src/js_lexer.zig
@@ -18,6 +18,7 @@ pub const StrictModeReservedWords = tables.StrictModeReservedWords;
pub const PropertyModifierKeyword = tables.PropertyModifierKeyword;
pub const TypescriptStmtKeyword = tables.TypescriptStmtKeyword;
pub const TypeScriptAccessibilityModifier = tables.TypeScriptAccessibilityModifier;
+pub const ChildlessJSXTags = tables.ChildlessJSXTags;
fn notimpl() noreturn {
Global.panic("not implemented yet!", .{});
diff --git a/src/js_lexer_tables.zig b/src/js_lexer_tables.zig
index 0a49a268b..41d3cf352 100644
--- a/src/js_lexer_tables.zig
+++ b/src/js_lexer_tables.zig
@@ -535,6 +535,26 @@ pub const TypescriptStmtKeyword = enum {
pub const JSXEntityMap = std.StringHashMap(CodePoint);
+// Error: meta is a void element tag and must neither have `children` nor use `dangerouslySetInnerHTML`.
+pub const ChildlessJSXTags = std.ComptimeStringMap(void, .{
+ .{ "area", void },
+ .{ "base", void },
+ .{ "br", void },
+ .{ "col", void },
+ .{ "embed", void },
+ .{ "hr", void },
+ .{ "img", void },
+ .{ "input", void },
+ .{ "keygen", void },
+ .{ "link", void },
+ .{ "meta", void },
+ .{ "param", void },
+ .{ "source", void },
+ .{ "track", void },
+ .{ "wbr", void },
+ .{ "menuitem", void },
+});
+
pub var jsxEntity: JSXEntityMap = undefined;
var has_loaded_jsx_map = false;
diff --git a/src/js_parser/js_parser.zig b/src/js_parser/js_parser.zig
index f6b59141c..4bc70eb01 100644
--- a/src/js_parser/js_parser.zig
+++ b/src/js_parser/js_parser.zig
@@ -769,7 +769,7 @@ pub const SideEffects = enum(u2) {
// A call that has been marked "__PURE__" can be removed if all arguments
// can be removed. The annotation causes us to ignore the target.
if (call.can_be_unwrapped_if_unused) {
- return Expr.joinAllWithComma(call.args, p.allocator);
+ return Expr.joinAllWithCommaCallback(call.args, @TypeOf(p), p, simpifyUnusedExpr, p.allocator);
}
},
@@ -802,7 +802,7 @@ pub const SideEffects = enum(u2) {
// the right expression can be completely removed. Otherwise, the left
// expression is important for the branch.
bin.right = simpifyUnusedExpr(p, bin.right) orelse bin.right.toEmpty();
- if (!bin.right.isEmpty()) {
+ if (bin.right.isEmpty()) {
return simpifyUnusedExpr(p, bin.left);
}
},
@@ -10374,7 +10374,7 @@ pub fn NewParser(
p.panic("Unexpected private identifier. This is an internal error - not your fault.", .{});
},
.e_jsx_element => |e_| {
- const tag = tagger: {
+ const tag: Expr = tagger: {
if (e_.tag) |_tag| {
break :tagger p.visitExpr(_tag);
} else {
@@ -10397,13 +10397,26 @@ pub fn NewParser(
}
const runtime = if (p.options.jsx.runtime == .automatic and !e_.flags.is_key_before_rest) options.JSX.Runtime.automatic else options.JSX.Runtime.classic;
+ var children_count = e_.children.len;
+
+ const is_childless_tag = FeatureFlags.react_specific_warnings and children_count > 0 and tag.data == .e_string and tag.data.e_string.isUTF8() and js_lexer.ChildlessJSXTags.has(tag.data.e_string.utf8);
+
+ if (is_childless_tag) {
+ children_count = 0;
+ }
+
+ if (children_count != e_.children.len) {
+ // Error: meta is a void element tag and must neither have `children` nor use `dangerouslySetInnerHTML`.
+ // ^ from react-dom
+ p.log.addWarningFmt(p.source, tag.loc, p.allocator, "<{s} /> is a void element and must not have \"children\"", .{tag.data.e_string.utf8}) catch {};
+ }
// TODO: maybe we should split these into two different AST Nodes
// That would reduce the amount of allocations a little
switch (runtime) {
.classic => {
// Arguments to createElement()
- const args = p.allocator.alloc(Expr, 1 + e_.children.len) catch unreachable;
+ const args = p.allocator.alloc(Expr, 1 + children_count) catch unreachable;
var i: usize = 1;
if (e_.properties.len > 0) {
if (e_.key) |key| {
@@ -10417,7 +10430,7 @@ pub fn NewParser(
args[0] = p.e(E.Null{}, expr.loc);
}
- for (e_.children) |child| {
+ for (e_.children[0..children_count]) |child| {
args[i] = p.visitExpr(child);
i += 1;
}
@@ -10444,12 +10457,11 @@ pub fn NewParser(
// ...props,
// children: []
// }
- for (e_.children) |child, i| {
+ for (e_.children[0..children_count]) |child, i| {
e_.children[i] = p.visitExpr(child);
}
const children_key = Expr{ .data = jsxChildrenKeyData, .loc = expr.loc };
- //
props.append(G.Property{
.key = children_key,
.value = p.e(E.Array{
diff --git a/src/js_printer.zig b/src/js_printer.zig
index 8a5c81c8c..fa51171d8 100644
--- a/src/js_printer.zig
+++ b/src/js_printer.zig
@@ -2838,12 +2838,6 @@ pub fn NewPrinter(
p.printLoadFromBundleWithoutCall(s.import_record_index);
- if (!record.contains_import_star) {
- p.print(" as ");
-
- p.printSymbol(s.namespace_ref);
- }
-
p.print("} from ");
p.printQuotedUTF8(record.path.text, false);
p.printSemicolonAfterStatement();
@@ -2867,11 +2861,8 @@ pub fn NewPrinter(
}
p.print("} = ");
- if (!record.contains_import_star) {
- p.printSymbol(s.namespace_ref);
- } else {
- p.printLoadFromBundleWithoutCall(s.import_record_index);
- }
+ p.printLoadFromBundleWithoutCall(s.import_record_index);
+
p.print("()");
p.printSemicolonAfterStatement();
} else if (s.default_name) |default_name| {
@@ -2883,11 +2874,7 @@ pub fn NewPrinter(
p.printSymbol(default_name.ref.?);
p.print("} = ");
- if (!record.contains_import_star) {
- p.printSymbol(s.namespace_ref);
- } else {
- p.printLoadFromBundleWithoutCall(s.import_record_index);
- }
+ p.printLoadFromBundleWithoutCall(s.import_record_index);
p.print("()");
p.printSemicolonAfterStatement();
@@ -2902,7 +2889,6 @@ pub fn NewPrinter(
return;
}
-
p.print("import");
p.printSpace();
diff --git a/src/linker.zig b/src/linker.zig
index 5073e88cf..018db3528 100644
--- a/src/linker.zig
+++ b/src/linker.zig
@@ -460,6 +460,7 @@ pub fn NewLinker(comptime BundlerType: type) type {
},
.relative => {
var relative_name = linker.fs.relative(source_dir, source_path);
+
var pretty: string = undefined;
if (use_hashed_name) {
var basepath = Fs.Path.init(source_path);
@@ -529,35 +530,13 @@ pub fn NewLinker(comptime BundlerType: type) type {
basename = try linker.getHashedFilename(basepath, null);
}
- const needs_slash = dirname.len > 0 and dirname[dirname.len - 1] != '/';
-
- if (needs_slash) {
- const absolute_url = try std.fmt.allocPrint(
- linker.allocator,
- "{s}{s}/{s}{s}",
- .{
- linker.options.origin,
- dirname,
- basename,
- absolute_pathname.ext,
- },
- );
-
- return Fs.Path.initWithPretty(absolute_url, absolute_url);
- } else {
- const absolute_url = try std.fmt.allocPrint(
- linker.allocator,
- "{s}{s}{s}{s}",
- .{
- linker.options.origin,
- dirname,
- basename,
- absolute_pathname.ext,
- },
- );
-
- return Fs.Path.initWithPretty(absolute_url, absolute_url);
- }
+ return Fs.Path.init(try linker.options.origin.joinAlloc(
+ linker.allocator,
+ linker.options.routes.asset_prefix_path,
+ dirname,
+ basename,
+ absolute_pathname.ext,
+ ));
},
else => unreachable,
diff --git a/src/logger.zig b/src/logger.zig
index 08be0d70d..9d1db56e6 100644
--- a/src/logger.zig
+++ b/src/logger.zig
@@ -447,7 +447,7 @@ pub const Log = struct {
pub fn addWarningFmt(log: *Log, source: ?*const Source, l: Loc, allocator: *std.mem.Allocator, comptime text: string, args: anytype) !void {
log.warnings += 1;
try log.addMsg(Msg{
- .kind = .err,
+ .kind = .warn,
.data = rangeData(source, Range{ .loc = l }, std.fmt.allocPrint(allocator, text, args) catch unreachable),
});
}
diff --git a/src/options.zig b/src/options.zig
index a4302a703..a9211f2a2 100644
--- a/src/options.zig
+++ b/src/options.zig
@@ -10,6 +10,7 @@ const Api = api.Api;
const defines = @import("./defines.zig");
const resolve_path = @import("./resolver/resolve_path.zig");
const NodeModuleBundle = @import("./node_module_bundle.zig").NodeModuleBundle;
+const URL = @import("./query_string_map.zig").URL;
usingnamespace @import("global.zig");
const assert = std.debug.assert;
@@ -593,6 +594,7 @@ pub fn definesFromTransformOptions(
}
var resolved_defines = try defines.DefineData.from_input(user_defines, log, allocator);
+
return try defines.Define.init(
allocator,
resolved_defines,
@@ -645,7 +647,7 @@ pub const BundleOptions = struct {
hot_module_reloading: bool = false,
inject: ?[]string = null,
- origin: string = "",
+ origin: URL = URL{},
output_dir: string = "",
output_dir_handle: ?std.fs.Dir = null,
@@ -711,8 +713,7 @@ pub const BundleOptions = struct {
};
if (transform.origin) |origin| {
- opts.import_path_format = ImportPathFormat.absolute_url;
- opts.origin = origin;
+ opts.origin = URL.parse(origin);
}
if (transform.jsx) |jsx| {
@@ -728,6 +729,29 @@ pub const BundleOptions = struct {
opts.main_fields = Platform.DefaultMainFields.get(opts.platform);
}
+ if (transform.serve orelse false) {
+ // When we're serving, we need some kind of URL.
+ if (!opts.origin.isAbsolute()) {
+ const protocol: string = if (opts.origin.hasHTTPLikeProtocol()) opts.origin.protocol else "http";
+
+ const had_valid_port = opts.origin.hasValidPort();
+ const port: string = if (had_valid_port) opts.origin.port else "3000";
+
+ opts.origin = URL.parse(
+ try std.fmt.allocPrint(
+ allocator,
+ "{s}://localhost:{s}{s}",
+ .{
+ protocol,
+ port,
+ opts.origin.path,
+ },
+ ),
+ );
+ opts.origin.port_was_automatically_set = !had_valid_port;
+ }
+ }
+
switch (opts.platform) {
.node => {
opts.import_path_format = .relative_nodejs;
@@ -766,21 +790,9 @@ pub const BundleOptions = struct {
var node_module_bundle = try allocator.create(NodeModuleBundle);
node_module_bundle.* = bundle;
opts.node_modules_bundle = node_module_bundle;
- if (opts.origin.len > 0) {
- var relative = node_module_bundle.bundle.import_from_name;
- if (relative[0] == std.fs.path.sep) {
- relative = relative[1..];
- }
-
- const buf_size = opts.origin.len + relative.len + pretty_path.len;
- var buf = try allocator.alloc(u8, buf_size);
- opts.node_modules_bundle_url = try std.fmt.bufPrint(buf, "{s}{s}", .{ opts.origin, relative });
- opts.node_modules_bundle_pretty_path = buf[opts.node_modules_bundle_url.len..];
- std.mem.copy(
- u8,
- buf[opts.node_modules_bundle_url.len..],
- pretty_path,
- );
+ if (opts.origin.isAbsolute()) {
+ opts.node_modules_bundle_url = try opts.origin.joinAlloc(allocator, "", "", node_module_bundle.bundle.import_from_name, "");
+ opts.node_modules_bundle_pretty_path = opts.node_modules_bundle_url[opts.node_modules_bundle_url.len - node_module_bundle.bundle.import_from_name.len - 1 ..];
} else {
opts.node_modules_bundle_pretty_path = try allocator.dupe(u8, pretty_path);
}
@@ -838,9 +850,6 @@ pub const BundleOptions = struct {
if (transform.serve orelse false) {
opts.preserve_extensions = true;
opts.append_package_version_in_query_string = true;
- if (opts.origin.len == 0) {
- opts.origin = "/";
- }
opts.resolve_mode = .lazy;
@@ -899,6 +908,10 @@ pub const BundleOptions = struct {
opts.hot_module_reloading = opts.platform.isWebLike();
}
+ if (opts.origin.isAbsolute()) {
+ opts.import_path_format = ImportPathFormat.absolute_url;
+ }
+
if (opts.write and opts.output_dir.len > 0) {
opts.output_dir_handle = try openOutputDir(opts.output_dir);
}
@@ -1181,6 +1194,22 @@ pub const Framework = struct {
resolved: bool = false,
from_bundle: bool = false,
+ client_env: ?Env = null,
+ server_env: ?Env = null,
+
+ pub const Env = struct {
+ pub const Map = std.StringArrayHashMap(string);
+ defaults: Map,
+ prefix: string = "",
+
+ pub fn init(allocator: *std.mem.Allocator, prefix: string) Env {
+ return Env{
+ .defaults = Map.init(allocator),
+ .prefix = prefix,
+ };
+ }
+ };
+
fn normalizedPath(allocator: *std.mem.Allocator, toplevel_path: string, path: string) !string {
std.debug.assert(std.fs.path.isAbsolute(path));
var str = path;
@@ -1257,6 +1286,11 @@ pub const Framework = struct {
pub const RouteConfig = struct {
dir: string = "",
+
+ // Frameworks like Next.js (and others) use a special prefix for bundled/transpiled assets
+ // This is combined with "origin" when printing import paths
+ asset_prefix_path: string = "",
+
// TODO: do we need a separate list for data-only extensions?
// e.g. /foo.json just to get the data for the route, without rendering the html
// I think it's fine to hardcode as .json for now, but if I personally were writing a framework
@@ -1271,6 +1305,7 @@ pub const RouteConfig = struct {
pub fn toAPI(this: *const RouteConfig) Api.LoadedRouteConfig {
return .{
+ .asset_prefix = this.asset_prefix_path,
.dir = if (this.routes_enabled) this.dir else "",
.extensions = this.extensions,
.static_dir = if (this.static_dir_enabled) this.static_dir else "",
@@ -1293,6 +1328,7 @@ pub const RouteConfig = struct {
return RouteConfig{
.extensions = loaded.extensions,
.dir = loaded.dir,
+ .asset_prefix_path = loaded.asset_prefix,
.static_dir = loaded.static_dir,
.routes_enabled = loaded.dir.len > 0,
.static_dir_enabled = loaded.static_dir.len > 0,
@@ -1304,6 +1340,7 @@ pub const RouteConfig = struct {
var router_dir: string = std.mem.trimRight(u8, router_.dir orelse "", "/\\");
var static_dir: string = std.mem.trimRight(u8, router_.static_dir orelse "", "/\\");
+ var asset_prefix: string = std.mem.trimRight(u8, router_.asset_prefix orelse "", "/\\");
if (router_dir.len != 0) {
router.dir = router_dir;
@@ -1314,6 +1351,10 @@ pub const RouteConfig = struct {
router.static_dir = static_dir;
}
+ if (asset_prefix.len > 0) {
+ router.asset_prefix_path = asset_prefix;
+ }
+
if (router_.extensions.len > 0) {
var count: usize = 0;
for (router_.extensions) |_ext| {
diff --git a/src/query_string_map.zig b/src/query_string_map.zig
index 2640e8a73..00b451e9a 100644
--- a/src/query_string_map.zig
+++ b/src/query_string_map.zig
@@ -1,7 +1,305 @@
const std = @import("std");
const Api = @import("./api/schema.zig").Api;
+const resolve_path = @import("./resolver/resolve_path.zig");
usingnamespace @import("./global.zig");
+// This is close to WHATWG URL, but we don't want the validation errors
+pub const URL = struct {
+ hash: string = "",
+ host: string = "",
+ hostname: string = "",
+ href: string = "",
+ origin: string = "",
+ password: string = "",
+ pathname: string = "/",
+ path: string = "/",
+ port: string = "",
+ protocol: string = "",
+ search: string = "",
+ searchParams: ?QueryStringMap = null,
+ username: string = "",
+
+ port_was_automatically_set: bool = false,
+
+ pub fn hasHTTPLikeProtocol(this: *const URL) bool {
+ return strings.eqlComptime(this.protocol, "http") or strings.eqlComptime(this.protocol, "https");
+ }
+
+ pub fn getPort(this: *const URL) ?u16 {
+ return std.fmt.parseInt(u16, this.port, 10) catch null;
+ }
+
+ pub fn hasValidPort(this: *const URL) bool {
+ return (this.getPort() orelse 0) > 1;
+ }
+
+ pub fn isEmpty(this: *const URL) bool {
+ return this.href.len == 0;
+ }
+
+ pub fn isAbsolute(this: *const URL) bool {
+ return this.hostname.len > 0 and this.pathname.len > 0;
+ }
+
+ pub fn joinNormalize(out: []u8, prefix: string, dirname: string, basename: string, extname: string) string {
+ var buf: [2048]u8 = undefined;
+
+ var path_parts: [10]string = undefined;
+ var path_end: usize = 0;
+
+ path_parts[0] = "/";
+ path_end += 1;
+
+ if (prefix.len > 0) {
+ path_parts[path_end] = prefix;
+ path_end += 1;
+ }
+
+ if (dirname.len > 0) {
+ path_parts[path_end] = std.mem.trim(u8, dirname, "/\\");
+ path_end += 1;
+ }
+
+ if (basename.len > 0) {
+ if (dirname.len > 0) {
+ path_parts[path_end] = "/";
+ path_end += 1;
+ }
+
+ path_parts[path_end] = std.mem.trim(u8, basename, "/\\");
+ path_end += 1;
+ }
+
+ if (extname.len > 0) {
+ path_parts[path_end] = extname;
+ path_end += 1;
+ }
+
+ var buf_i: usize = 0;
+ for (path_parts[0..path_end]) |part| {
+ std.mem.copy(u8, buf[buf_i..], part);
+ buf_i += part.len;
+ }
+ return resolve_path.normalizeStringBuf(buf[0..buf_i], out, false, .loose, false);
+ }
+
+ pub fn joinWrite(
+ this: *const URL,
+ comptime Writer: type,
+ writer: Writer,
+ prefix: string,
+ dirname: string,
+ basename: string,
+ extname: string,
+ ) !void {
+ var out: [2048]u8 = undefined;
+ const normalized_path = joinNormalize(&out, prefix, dirname, basename, extname);
+
+ try writer.print("{s}/{s}", .{ this.origin, normalized_path });
+ }
+
+ pub fn joinAlloc(this: *const URL, allocator: *std.mem.Allocator, prefix: string, dirname: string, basename: string, extname: string) !string {
+ var out: [2048]u8 = undefined;
+ const normalized_path = joinNormalize(&out, prefix, dirname, basename, extname);
+
+ return try std.fmt.allocPrint(allocator, "{s}/{s}", .{ this.origin, normalized_path });
+ }
+
+ pub fn parse(base_: string) URL {
+ const base = std.mem.trim(u8, base_, &std.ascii.spaces);
+ if (base.len == 0) return URL{};
+ var url = URL{};
+ url.href = base;
+ var offset: u31 = 0;
+ switch (base[0]) {
+ '@' => {
+ offset += url.parsePassword(base[offset..]) orelse 0;
+ offset += url.parseHost(base[offset..]) orelse 0;
+ },
+ 'a'...'z', 'A'...'Z', '0'...'9', '-', '_', ':' => {
+ offset += url.parseProtocol(base[offset..]) orelse 0;
+
+ // if there's no protocol or @, it's ambiguous whether the colon is a port or a username.
+ if (offset > 0) {
+ if ((std.mem.indexOfScalar(u8, base[offset..], '@') orelse 0) > (std.mem.indexOfScalar(u8, base[offset..], ':') orelse 0)) {
+ offset += url.parseUsername(base[offset..]) orelse 0;
+ offset += url.parsePassword(base[offset..]) orelse 0;
+ }
+ }
+
+ offset += url.parseHost(base[offset..]) orelse 0;
+ },
+ else => {},
+ }
+
+ url.origin = base[0..offset];
+
+ if (offset > base.len) {
+ return url;
+ }
+
+ const path_offset = offset;
+
+ var can_update_path = true;
+ if (base.len > offset + 1 and base[offset] == '/' and base[offset..].len > 0) {
+ url.path = base[offset..];
+ url.pathname = url.path;
+ }
+
+ if (strings.indexOfChar(base[offset..], '?')) |q| {
+ offset += @intCast(u31, q);
+ url.path = base[path_offset..][0..q];
+ can_update_path = false;
+ url.search = base[offset..];
+ }
+
+ if (strings.indexOfChar(base[offset..], '#')) |hash| {
+ offset += @intCast(u31, hash);
+ if (can_update_path) {
+ url.path = base[path_offset..][0..hash];
+ }
+ url.hash = base[offset..];
+
+ if (url.search.len > 0) {
+ url.search = url.search[0 .. url.search.len - url.hash.len];
+ }
+ }
+
+ if (base.len > path_offset and base[path_offset] == '/' and offset > 0) {
+ url.pathname = base[path_offset..std.math.min(offset, base.len)];
+ url.origin = base[0..path_offset];
+ }
+
+ if (url.path.len > 1) {
+ const trimmed = std.mem.trim(u8, url.path, "/");
+ if (trimmed.len > 1) {
+ url.path = url.path[std.math.max(@ptrToInt(trimmed.ptr) - @ptrToInt(url.path.ptr), 1) - 1 ..];
+ } else {
+ url.path = "/";
+ }
+ } else {
+ url.path = "/";
+ }
+
+ if (url.pathname.len == 0) {
+ url.pathname = "/";
+ }
+
+ url.origin = std.mem.trim(u8, url.origin, "/ ?#");
+ return url;
+ }
+
+ pub fn parseProtocol(url: *URL, str: string) ?u31 {
+ var i: u31 = 0;
+ if (str.len < "://".len) return null;
+ while (i < str.len) : (i += 1) {
+ switch (str[i]) {
+ '/', '?', '%' => {
+ return null;
+ },
+ ':' => {
+ if (i + 3 <= str.len and str[i + 1] == '/' and str[i + 2] == '/') {
+ url.protocol = str[0..i];
+ return i + 3;
+ }
+ },
+ else => {},
+ }
+ }
+
+ return null;
+ }
+
+ pub fn parseUsername(url: *URL, str: string) ?u31 {
+ var i: u31 = 0;
+
+ // reset it
+ url.username = "";
+
+ if (str.len < "@".len) return null;
+
+ while (i < str.len) : (i += 1) {
+ switch (str[i]) {
+ ':', '@' => {
+ // we found a username, everything before this point in the slice is a username
+ url.username = str[0..i];
+ return i + 1;
+ },
+ // if we reach a slash, there's no username
+ '/' => {
+ return null;
+ },
+ else => {},
+ }
+ }
+ return null;
+ }
+
+ pub fn parsePassword(url: *URL, str: string) ?u31 {
+ var i: u31 = 0;
+
+ // reset it
+ url.password = "";
+
+ if (str.len < "@".len) return null;
+
+ while (i < str.len) : (i += 1) {
+ switch (str[i]) {
+ '@' => {
+ // we found a password, everything before this point in the slice is a password
+ url.password = str[0..i];
+ std.debug.assert(str[i..].len < 2 or std.mem.readIntNative(u16, str[i..][0..2]) != std.mem.readIntNative(u16, "//"));
+ return i + 1;
+ },
+ // if we reach a slash, there's no password
+ '/' => {
+ return null;
+ },
+ else => {},
+ }
+ }
+ return null;
+ }
+
+ pub fn parseHost(url: *URL, str: string) ?u31 {
+ var i: u31 = 0;
+
+ // reset it
+ url.host = "";
+ url.hostname = "";
+ url.port = "";
+
+ // look for the first "/"
+ // if we have a slash, anything before that is the host
+ // anything before the colon is the hostname
+ // anything after the colon but before the slash is the port
+ // the origin is the scheme before the slash
+
+ var colon_i: ?u31 = null;
+ while (i < str.len) : (i += 1) {
+ colon_i = if (colon_i == null and str[i] == ':') i else colon_i;
+
+ switch (str[i]) {
+ // alright, we found the slash
+ '/' => {
+ break;
+ },
+ else => {},
+ }
+ }
+
+ url.host = str[0..i];
+ if (colon_i) |colon| {
+ url.hostname = str[0..colon];
+ url.port = str[colon + 1 .. i];
+ } else {
+ url.hostname = str[0..i];
+ }
+
+ return i;
+ }
+};
+
/// QueryString array-backed hash table that does few allocations and preserves the original order
pub const QueryStringMap = struct {
allocator: *std.mem.Allocator,
@@ -825,3 +1123,122 @@ test "QueryStringMap Iterator" {
try expect(iter.next(buf) == null);
}
+
+test "URL - parse" {
+ var url = URL.parse("https://url.spec.whatwg.org/foo#include-credentials");
+ try expectString("https", url.protocol);
+ try expectString("url.spec.whatwg.org", url.host);
+ try expectString("/foo", url.pathname);
+ try expectString("#include-credentials", url.hash);
+
+ url = URL.parse("https://url.spec.whatwg.org/#include-credentials");
+ try expectString("https", url.protocol);
+ try expectString("url.spec.whatwg.org", url.host);
+ try expectString("/", url.pathname);
+ try expectString("#include-credentials", url.hash);
+
+ url = URL.parse("://url.spec.whatwg.org/#include-credentials");
+ try expectString("", url.protocol);
+ try expectString("url.spec.whatwg.org", url.host);
+ try expectString("/", url.pathname);
+ try expectString("#include-credentials", url.hash);
+
+ url = URL.parse("/#include-credentials");
+ try expectString("", url.protocol);
+ try expectString("", url.host);
+ try expectString("/", url.pathname);
+ try expectString("#include-credentials", url.hash);
+
+ url = URL.parse("https://username:password@url.spec.whatwg.org/#include-credentials");
+ try expectString("https", url.protocol);
+ try expectString("username", url.username);
+ try expectString("password", url.password);
+ try expectString("url.spec.whatwg.org", url.host);
+ try expectString("/", url.pathname);
+ try expectString("#include-credentials", url.hash);
+
+ url = URL.parse("https://username:password@url.spec.whatwg.org:3000/#include-credentials");
+ try expectString("https", url.protocol);
+ try expectString("username", url.username);
+ try expectString("password", url.password);
+ try expectString("url.spec.whatwg.org:3000", url.host);
+ try expectString("3000", url.port);
+ try expectString("/", url.pathname);
+ try expectString("#include-credentials", url.hash);
+
+ url = URL.parse("example.com/#include-credentials");
+ try expectString("", url.protocol);
+ try expectString("", url.username);
+ try expectString("", url.password);
+ try expectString("example.com", url.host);
+ try expectString("/", url.pathname);
+ try expectString("#include-credentials", url.hash);
+
+ url = URL.parse("example.com:8080/#include-credentials");
+ try expectString("", url.protocol);
+ try expectString("", url.username);
+ try expectString("", url.password);
+ try expectString("example.com:8080", url.host);
+ try expectString("example.com", url.hostname);
+ try expectString("8080", url.port);
+ try expectString("/", url.pathname);
+ try expectString("#include-credentials", url.hash);
+
+ url = URL.parse("example.com:8080/////#include-credentials");
+ try expectString("", url.protocol);
+ try expectString("", url.username);
+ try expectString("", url.password);
+ try expectString("example.com:8080", url.host);
+ try expectString("example.com", url.hostname);
+ try expectString("8080", url.port);
+ try expectString("/////", url.pathname);
+ try expectString("/", url.path);
+ try expectString("#include-credentials", url.hash);
+ url = URL.parse("example.com:8080/////hi?wow#include-credentials");
+ try expectString("", url.protocol);
+ try expectString("", url.username);
+ try expectString("", url.password);
+ try expectString("example.com:8080", url.host);
+ try expectString("example.com", url.hostname);
+ try expectString("8080", url.port);
+ try expectString("/////hi?wow", url.pathname);
+ try expectString("/hi", url.path);
+ try expectString("#include-credentials", url.hash);
+ try expectString("?wow", url.search);
+
+ url = URL.parse("/src/index");
+ try expectString("", url.protocol);
+ try expectString("", url.username);
+ try expectString("", url.password);
+ try expectString("", url.host);
+ try expectString("", url.hostname);
+ try expectString("", url.port);
+ try expectString("/src/index", url.path);
+ try expectString("/src/index", url.pathname);
+
+ try expectString("", url.hash);
+ try expectString("", url.search);
+
+ url = URL.parse("http://localhost:3000/");
+ try expectString("http", url.protocol);
+ try expectString("", url.username);
+ try expectString("", url.password);
+ try expectString("localhost:3000", url.host);
+ try expectString("localhost", url.hostname);
+ try expectString("3000", url.port);
+ try expectString("/", url.path);
+ try expectString("/", url.pathname);
+}
+
+test "URL - joinAlloc" {
+ var url = URL.parse("http://localhost:3000");
+
+ var absolute_url = try url.joinAlloc(std.heap.c_allocator, "/_next/", "src/components", "button", ".js");
+ try expectString("http://localhost:3000/_next/src/components/button.js", absolute_url);
+
+ absolute_url = try url.joinAlloc(std.heap.c_allocator, "compiled-", "src/components", "button", ".js");
+ try expectString("http://localhost:3000/compiled-src/components/button.js", absolute_url);
+
+ absolute_url = try url.joinAlloc(std.heap.c_allocator, "compiled-", "", "button", ".js");
+ try expectString("http://localhost:3000/compiled-button.js", absolute_url);
+}
diff --git a/src/resolver/package_json.zig b/src/resolver/package_json.zig
index 7862de15c..160f748fd 100644
--- a/src/resolver/package_json.zig
+++ b/src/resolver/package_json.zig
@@ -70,6 +70,57 @@ pub const PackageJSON = struct {
}
}
+ // "env": {
+ // "client": {
+ // "NEXT_TRAILING_SLASH": false,
+ // },
+ // "clientPrefix": "NEXT_PUBLIC_",
+ // "server": {
+ // "NEXT_TRAILING_SLASH": false,
+ // },
+ // "serverPrefix": "",
+ // }
+
+ if (json.asProperty("env")) |defines| {
+ if (defines.expr.asProperty("client")) |client| {
+ if (client.expr.data == .e_object) {
+ const object = client.expr.data.e_object;
+ var i: usize = 0;
+ for (object.properties) |prop| {
+ // must be strings
+ const key = prop.key orelse continue;
+ const value = prop.value orelse continue;
+ i += @intCast(usize, @boolToInt(key.data == .e_string and value.data == .e_string));
+ }
+
+ if (i > 0) {
+ if (framework.client_env == null) {
+ framework.client_env = options.Framework.Env.init(allocator, "");
+ }
+ var env = &framework.client_env.?;
+ try env.defaults.ensureUnusedCapacity(i);
+
+ for (object.properties) |prop| {
+ // must be strings
+ // not for any good reason.
+ // we should fix this later
+
+ const key = prop.key orelse continue;
+ const value = prop.value orelse continue;
+ if (key.data != .e_string or value.data != .e_string) continue;
+
+ var res = try define.getOrPut(try key.asString(allocator));
+ if (!res.found_existing) {
+ res.value_ptr.* = try value.asString(allocator);
+ }
+ }
+ }
+ }
+ }
+
+ if (defines.expr.asProperty("server")) |server| {}
+ }
+
if (json.asProperty("server")) |server| {
if (server.expr.asString(allocator)) |str| {
if (str.len > 0) {
@@ -92,6 +143,15 @@ pub const PackageJSON = struct {
}
}
+ if (framework_object.expr.asProperty("assetPrefix")) |asset_prefix| {
+ if (asset_prefix.expr.asString(allocator)) |_str| {
+ const str = std.mem.trimRight(u8, _str, " ");
+ if (str.len > 0) {
+ pair.router.asset_prefix_path = str;
+ }
+ }
+ }
+
if (!pair.router.routes_enabled) {
if (framework_object.expr.asProperty("router")) |router| {
if (router.expr.asProperty("dir")) |route_dir| {
diff --git a/src/router.zig b/src/router.zig
index 884741d3d..7e6867848 100644
--- a/src/router.zig
+++ b/src/router.zig
@@ -43,7 +43,11 @@ pub fn init(
};
}
-pub fn getEntryPoints(this: *const Router, allocator: *std.mem.Allocator) ![]const string {
+pub const EntryPointList = struct {
+ entry_points: []const string,
+ buffer: []u8,
+};
+pub fn getEntryPointsWithBuffer(this: *const Router, allocator: *std.mem.Allocator, comptime absolute: bool) !EntryPointList {
var i: u16 = 0;
const route_count: u16 = @truncate(u16, this.routes.routes.len);
@@ -73,15 +77,26 @@ pub fn getEntryPoints(this: *const Router, allocator: *std.mem.Allocator) ![]con
const children = this.routes.routes.items(.children)[i];
if (children.len == 0) {
if (Fs.FileSystem.DirEntry.EntryStore.instance.at(this.routes.routes.items(.entry_index)[i])) |entry| {
- var parts = [_]string{ entry.dir, entry.base };
- entry_points[entry_point_i] = this.fs.absBuf(&parts, remain);
+ if (comptime absolute) {
+ var parts = [_]string{ entry.dir, entry.base };
+ entry_points[entry_point_i] = this.fs.absBuf(&parts, remain);
+ } else {
+ var parts = [_]string{ "/", this.config.asset_prefix_path, this.fs.relativeTo(entry.dir), entry.base };
+ entry_points[entry_point_i] = this.fs.joinBuf(&parts, remain);
+ }
+
remain = remain[entry_points[entry_point_i].len..];
entry_point_i += 1;
}
}
}
- return entry_points;
+ return EntryPointList{ .entry_points = entry_points, .buffer = buffer };
+}
+
+pub fn getEntryPoints(this: *const Router, allocator: *std.mem.Allocator) ![]const string {
+ const list = try getEntryPointsWithBuffer(this, allocator, true);
+ return list.entry_points;
}
const banned_dirs = [_]string{
diff --git a/src/string_immutable.zig b/src/string_immutable.zig
index 5e651fc5d..618657a64 100644
--- a/src/string_immutable.zig
+++ b/src/string_immutable.zig
@@ -217,7 +217,7 @@ pub fn eqlComptime(self: string, comptime alt: anytype) bool {
return (self.len == alt.len) and first == std.mem.readIntNative(u64, self[0..8]) and second == std.mem.readIntNative(u64, self[8..16]);
},
else => {
- @compileError(alt ++ " is too long.");
+ @compileError(alt ++ " is too long.");
},
}
}
@@ -499,6 +499,21 @@ pub const CodepointIterator = struct {
return it.c;
}
+ pub fn nextCodepointNoReturn(it: *CodepointIterator) void {
+ const slice = it.nextCodepointSlice();
+ it.width = @intCast(u3, slice.len);
+ @setRuntimeSafety(false);
+
+ it.c = switch (it.width) {
+ 0 => -1,
+ 1 => @intCast(CodePoint, slice[0]),
+ 2 => @intCast(CodePoint, std.unicode.utf8Decode2(slice) catch unreachable),
+ 3 => @intCast(CodePoint, std.unicode.utf8Decode3(slice) catch unreachable),
+ 4 => @intCast(CodePoint, std.unicode.utf8Decode4(slice) catch unreachable),
+ else => unreachable,
+ };
+ }
+
/// Look ahead at the next n codepoints without advancing the iterator.
/// If fewer than n codepoints are available, then return the remainder of the string.
pub fn peek(it: *CodepointIterator, n: usize) []const u8 {