aboutsummaryrefslogtreecommitdiff
path: root/src/javascript
diff options
context:
space:
mode:
Diffstat (limited to 'src/javascript')
-rw-r--r--src/javascript/jsc/javascript.zig497
-rw-r--r--src/javascript/jsc/node_env_buf_map.zig2
2 files changed, 303 insertions, 196 deletions
diff --git a/src/javascript/jsc/javascript.zig b/src/javascript/jsc/javascript.zig
index 9f9b21044..7ff4070e5 100644
--- a/src/javascript/jsc/javascript.zig
+++ b/src/javascript/jsc/javascript.zig
@@ -149,8 +149,10 @@ pub const VirtualMachine = struct {
existing_bundle: ?*NodeModuleBundle,
_log: ?*logger.Log,
) !*VirtualMachine {
- var group = js.JSContextGroupCreate();
- var ctx = js.JSGlobalContextCreateInGroup(group, null);
+ var group = js.JSContextGroupRetain(js.JSContextGroupCreate());
+
+ var ctx = js.JSGlobalContextRetain(js.JSGlobalContextCreateInGroup(group, null));
+
var log: *logger.Log = undefined;
if (_log) |__log| {
log = __log;
@@ -168,7 +170,7 @@ pub const VirtualMachine = struct {
try configureTransformOptionsForSpeedy(allocator, _args),
existing_bundle,
),
- .node_module_list = undefined,
+ .node_module_list = try allocator.create(Module.NodeModuleList),
.log = log,
.group = group,
.root = ctx,
@@ -187,7 +189,7 @@ pub const VirtualMachine = struct {
Properties.init();
if (vm.bundler.options.node_modules_bundle) |bundle| {
vm.node_modules = bundle;
- vm.node_module_list = try Module.NodeModuleList.init(vm, bundle);
+ try Module.NodeModuleList.create(vm, bundle, vm.node_module_list.?);
}
return vm;
@@ -398,6 +400,8 @@ pub const Module = struct {
vm: *VirtualMachine,
require_func: js.JSObjectRef = null,
+ loaded: bool = false,
+ exports_function: js.JSValueRef = null,
pub var module_class: js.JSClassRef = undefined;
pub var module_global_class: js.JSClassRef = undefined;
@@ -407,9 +411,10 @@ pub const Module = struct {
pub const NodeModuleList = struct {
tempbuf: []u8,
property_names: [*]u8,
+ module_property_map: []u64,
static_functions: [1]js.JSStaticFunction,
property_getters: []js.JSObjectRef,
- module_property_map: ModuleIDMap,
+
node_module_global_class: js.JSClassRef,
node_module_global_class_def: js.JSClassDefinition,
vm: *VirtualMachine,
@@ -419,18 +424,31 @@ pub const Module = struct {
require_cache: []?*Module,
- pub fn loadBundledModuleById(node_module_list: *NodeModuleList, id: u32) !*Module {
+ exports_function_call: js.JSObjectRef = null,
+
+ const RequireBundleClassName = "requireFromBundle";
+ var require_bundle_class_def: js.JSClassDefinition = undefined;
+ var require_bundle_class_ref: js.JSClassRef = undefined;
+ var require_bundle_class_loaded = false;
+
+ pub fn loadBundledModuleById(node_module_list: *NodeModuleList, id: u32, call_ctx: js.JSContextRef) !*Module {
if (node_module_list.require_cache[id]) |mod| {
return mod;
}
- var module = try Module.NodeModuleList.Instance.evalBundledModule(
+ var module = try node_module_list.vm.allocator.create(Module);
+ node_module_list.require_cache[id] = module;
+ errdefer node_module_list.vm.allocator.destroy(module);
+
+ try Module.NodeModuleList.Instance.evalBundledModule(
+ module,
node_module_list.vm.allocator,
node_module_list.vm,
node_module_list,
id,
+ call_ctx,
);
- node_module_list.require_cache[id] = module;
+
return module;
}
@@ -442,11 +460,13 @@ pub const Module = struct {
threadlocal var source_code_buffer_loaded = false;
pub fn evalBundledModule(
+ module: *Module,
allocator: *std.mem.Allocator,
vm: *VirtualMachine,
node_module_list: *NodeModuleList,
id: u32,
- ) !*Module {
+ call_ctx: js.JSContextRef,
+ ) !void {
const bundled_module = &vm.node_modules.?.bundle.modules[id];
const total_length = bundled_module.code.length + 1;
if (!source_code_buffer_loaded) {
@@ -461,32 +481,61 @@ pub const Module = struct {
var node_module_file = std.fs.File{ .handle = vm.node_modules.?.fd };
const read = try node_module_file.pread(source_code_buffer.list.items, bundled_module.code.offset);
- source_code_buffer.list.items[read] = 0;
- var buf = source_code_buffer.list.items[0..read :0];
+ var buf = source_code_buffer.list.items[0..read];
const bundled_package = &vm.node_modules.?.bundle.packages[bundled_module.package_id];
// We want linear because we expect it to virtually always be at 0
// However, out of caution we check.
+
var start_at: usize = std.mem.indexOfPosLinear(u8, buf, 0, "export var $") orelse return error.FailedCorruptNodeModuleMissingExport;
start_at += "export var $".len;
// export var $fooo = $$m("packageName", "id", (module, exports) => {
// ^
- start_at = std.mem.indexOfPosLinear(u8, "\",", start_at, buf) orelse return error.FailedCorruptNodeModuleMissingModuleWrapper;
+ start_at = std.mem.indexOfPosLinear(
+ u8,
+ buf,
+ start_at,
+ "\",",
+ ) orelse return error.FailedCorruptNodeModuleMissingModuleWrapper;
start_at += 1;
// export var $fooo = $$m("packageName", "id", (module, exports) => {
// ^
- start_at = std.mem.indexOfPosLinear(u8, "\",", start_at, buf) orelse return error.FailedCorruptNodeModuleMissingModuleWrapper;
+ start_at = std.mem.indexOfPosLinear(
+ u8,
+ buf,
+ start_at,
+ "\",",
+ ) orelse return error.FailedCorruptNodeModuleMissingModuleWrapper;
start_at += 1;
- // ((module, exports) => {
- buf[start_at] = '(';
-
- var source_buf = source_code_buffer.list.items[start_at..read :0];
- var source_string = js.JSStringCreateWithUTF8CString(source_buf.ptr);
- defer js.JSStringRelease(source_string);
- var source_url_buf = try std.fmt.allocPrintZ(
+ start_at = std.mem.indexOfPosLinear(
+ u8,
+ buf,
+ start_at,
+ "=>",
+ ) orelse return error.FailedCorruptNodeModuleMissingModuleWrapper;
+ start_at += 2;
+ // (module, exports) => {
+ // ^
+ start_at = std.mem.indexOfPosLinear(
+ u8,
+ buf,
+ start_at,
+ "{",
+ ) orelse return error.FailedCorruptNodeModuleMissingModuleWrapper;
+ start_at += 1;
+ // (module, exports) => {
+ //
+ // ^
+ var curr_buf = buf[start_at..];
+ curr_buf = curr_buf[0 .. std.mem.lastIndexOfScalar(u8, curr_buf, ';') orelse return error.FailedCorruptNodeModuleMissingModuleWrapper];
+ curr_buf = curr_buf[0 .. std.mem.lastIndexOfScalar(u8, curr_buf, ')') orelse return error.FailedCorruptNodeModuleMissingModuleWrapper];
+ curr_buf = curr_buf[0 .. std.mem.lastIndexOfScalar(u8, curr_buf, '}') orelse return error.FailedCorruptNodeModuleMissingModuleWrapper];
+ curr_buf.ptr[curr_buf.len] = 0;
+ var source_buf = curr_buf.ptr[0..curr_buf.len :0];
+ var source_url_buf = try std.fmt.allocPrint(
allocator,
- "node_modules.jsb/{s}/{s}",
+ "{s}/{s}",
.{
vm.node_modules.?.str(bundled_package.name),
vm.node_modules.?.str(bundled_module.path),
@@ -494,76 +543,19 @@ pub const Module = struct {
);
errdefer allocator.free(source_url_buf);
- var source_url = js.JSStringCreateWithUTF8CString(source_url_buf);
- defer js.JSStringRelease(source_url);
var exception: js.JSValueRef = null;
- var return_value: js.JSObjectRef = null;
- var module: *Module = undefined;
- go: {
- // Compile the wrapper function
- var function = js.JSEvaluateScript(
- node_module_list.bundle_ctx,
- source_string,
- null,
- source_url,
- 1,
- &exception,
- );
- if (exception != null) break :go;
- if (!js.JSValueIsObject(node_module_list.bundle_ctx, function)) {
- return error.ExpectedFunction;
- }
-
- // Don't create the instance / module if the script has a syntax error
- module = try allocator.create(Module);
- module.* = Module{
- .path = Fs.Path.initWithPretty(source_url_buf, source_url_buf),
- .ref = undefined,
- .vm = vm,
- };
- module.ref = js.JSObjectMake(node_module_list.bundle_ctx, Module.module_class, module);
- var args = try allocator.alloc(js.JSValueRef, 2);
- args[0] = module.ref;
- args[1] = module.internalGetExports();
-
- // Run the wrapper
- _ = js.JSObjectCallAsFunction(
- node_module_list.bundle_ctx,
- function,
- args[1],
- 2,
- args.ptr,
- &exception,
- );
- if (exception != null) {
- allocator.destroy(module);
- allocator.free(source_url_buf);
- }
- break :go;
- }
-
- if (exception != null) {
- var message = js.JSValueToStringCopy(node_module_list.bundle_ctx, exception.?, null);
- defer js.JSStringRelease(message);
- var message_str_size = js.JSStringGetMaximumUTF8CStringSize(message);
- var message_str_buf = try allocator.alloc(u8, message_str_size);
- defer allocator.free(message_str_buf);
- var message_str_read = js.JSStringGetUTF8CString(message, message_str_buf.ptr, message_str_size);
- defer Output.flush();
- vm.log.addErrorFmt(null, logger.Loc.Empty, allocator, "Error loading \"{s}/{s}\":\n{s}", .{
- vm.node_modules.?.str(bundled_package.name),
- vm.node_modules.?.str(bundled_module.path),
- message_str_buf[0..message_str_read],
- }) catch {};
- Output.prettyErrorln("<r>{s}\n--<r><red>error<r> loading <cyan>\"{s}/{s}\"<r>--", .{
- message_str_buf[0..message_str_read],
- vm.node_modules.?.str(bundled_package.name),
- vm.node_modules.?.str(bundled_module.path),
- });
- return error.FailedException;
- }
-
- return module;
+ try Module.load(
+ module,
+ vm,
+ allocator,
+ vm.log,
+ source_buf,
+ Fs.Path.initWithPretty(source_url_buf, source_url_buf),
+ node_module_list.bundle_ctx,
+ call_ctx,
+ call_ctx,
+ &exception,
+ );
}
};
@@ -597,20 +589,28 @@ pub const Module = struct {
),
);
+ std.mem.set(u8, this.tempbuf, 0);
const size = js.JSStringGetUTF8CString(prop, this.tempbuf.ptr, this.tempbuf.len);
- const key = std.hash.Wyhash.hash(0, this.tempbuf[0..size]);
- const id = this.module_property_map.get(key) orelse return null;
+ const key = std.hash.Wyhash.hash(0, this.tempbuf);
+ const id = @intCast(u32, std.mem.indexOfScalar(u64, this.module_property_map, key) orelse return null);
if (this.property_getters[id] == null) {
- var require_bundled = this.vm.allocator.create(RequireBundledModule) catch unreachable;
- require_bundled.* = RequireBundledModule{ .id = id, .list = this };
- this.property_getters[id] = To.JS.functionWithCallback(
- RequireBundledModule,
- require_bundled,
- prop,
- ctx,
- requireBundledModule,
- );
+ if (!require_bundle_class_loaded) {
+ require_bundle_class_def = js.kJSClassDefinitionEmpty;
+ require_bundle_class_def.className = RequireBundleClassName[0.. :0];
+ require_bundle_class_def.callAsFunction = To.JS.Callback(RequireBundledModule, requireBundledModule).rfn;
+ require_bundle_class_ref = js.JSClassRetain(js.JSClassCreate(&require_bundle_class_def));
+ require_bundle_class_loaded = true;
+ }
+
+ // TODO: remove this allocation by ptr casting
+ var require_from_bundle = this.vm.allocator.create(RequireBundledModule) catch unreachable;
+ require_from_bundle.* = RequireBundledModule{
+ .list = this,
+ .id = id,
+ };
+ this.property_getters[id] = js.JSObjectMake(this.bundle_ctx, require_bundle_class_ref, require_from_bundle);
+ js.JSValueProtect(this.bundle_ctx, this.property_getters[id]);
}
return this.property_getters[id];
@@ -628,8 +628,7 @@ pub const Module = struct {
const bundle = &obj.list.vm.node_modules.?.bundle;
const bundled_module = &bundle.modules[obj.id];
const bundled_pkg = &bundle.packages[bundled_module.package_id];
-
- const result = loadBundledModuleById(obj.list, obj.id) catch |err| {
+ var module = loadBundledModuleById(obj.list, obj.id, obj.list.bundle_ctx) catch |err| {
Output.prettyErrorln("<r><red>RequireError<r>: <b>{s}<r> in \"<cyan>{s}/{s}<r>\"", .{
@errorName(err),
obj.list.vm.node_modules.?.str(bundled_pkg.name),
@@ -648,74 +647,58 @@ pub const Module = struct {
return js.JSValueMakeUndefined(ctx);
};
- return result.internalGetExports();
+ return module.internalGetExports(js.JSContextGetGlobalContext(ctx));
}
- pub fn init(vm: *VirtualMachine, bundle: *const NodeModuleBundle) !*NodeModuleList {
+ pub fn create(vm: *VirtualMachine, bundle: *const NodeModuleBundle, node_module_list: *NodeModuleList) !void {
var size: usize = 0;
var longest_size: usize = 0;
for (bundle.bundle.modules) |module, i| {
- var hasher = std.hash.Wyhash.init(0);
- hasher.update(bundle.str(module.path));
- hasher.update(
- std.mem.asBytes(
- &bundle.bundle.packages[module.package_id].hash,
- ),
- );
// Add one for null-terminated string offset
const this_size = std.fmt.count(
"${x}" ++ "\\x0",
.{
- @truncate(
- u32,
- hasher.final(),
- ),
+ module.id,
},
);
size += this_size;
longest_size = std.math.max(this_size, longest_size);
}
- var static_properties = try vm.allocator.alloc(js.JSStaticValue, bundle.bundle.modules.len);
- var utf8 = try vm.allocator.alloc(u8, size + longest_size);
-
+ var static_properties = try vm.allocator.alloc(js.JSStaticValue, bundle.bundle.modules.len + 1);
+ static_properties[static_properties.len - 1] = std.mem.zeroes(js.JSStaticValue);
+ var utf8 = try vm.allocator.alloc(u8, size + std.math.max(longest_size, 32));
+ std.mem.set(u8, utf8, 0);
var tempbuf = utf8[size..];
var names_buf = utf8[0..size];
- var module_property_map = ModuleIDMap.init(vm.allocator);
- try module_property_map.ensureCapacity(@truncate(u32, bundle.bundle.modules.len));
+ var module_property_map = try vm.allocator.alloc(u64, bundle.bundle.modules.len);
for (bundle.bundle.modules) |module, i| {
var hasher = std.hash.Wyhash.init(0);
- hasher.update(bundle.str(module.path));
- hasher.update(
- std.mem.asBytes(
- &bundle.bundle.packages[module.package_id].hash,
- ),
- );
const hash = @truncate(
u32,
- hasher.final(),
+ module.id,
);
// The variable name is the hash of the module path
- var name = std.fmt.bufPrintZ(names_buf, "${x}", .{hash}) catch unreachable;
+ var name = std.fmt.bufPrint(names_buf, "${x}", .{hash}) catch unreachable;
+ std.mem.set(u8, tempbuf, 0);
+ std.mem.copy(u8, tempbuf, name);
+ name.ptr[name.len] = 0;
// But we don't store that for the hash map. Instead, we store the hash of name.
// This lets us avoid storing pointers to the name in the hash table, so if we free it later
// or something it won't cause issues.
- hasher = std.hash.Wyhash.init(0);
- hasher.update(name[0..]);
- var property_key = hasher.final();
+ module_property_map[i] = std.hash.Wyhash.hash(0, tempbuf);
static_properties[i] = js.JSStaticValue{
.name = name.ptr,
.getProperty = getRequireFromBundleProperty,
.setProperty = null,
.attributes = .kJSPropertyAttributeReadOnly,
};
- names_buf = names_buf[name.len..];
- module_property_map.putAssumeCapacityNoClobberWithHash(property_key, property_key, @truncate(u32, i));
+ names_buf = names_buf[name.len + 1 ..];
}
var node_module_global_class_def = js.kJSClassDefinitionEmpty;
@@ -725,14 +708,13 @@ pub const Module = struct {
var property_getters = try vm.allocator.alloc(js.JSObjectRef, bundle.bundle.modules.len);
std.mem.set(js.JSObjectRef, property_getters, null);
- var node_module_list = try vm.allocator.create(NodeModuleList);
node_module_list.* = NodeModuleList{
.module_property_map = module_property_map,
.node_module_global_class_def = node_module_global_class_def,
.vm = vm,
.tempbuf = tempbuf,
- .property_names = names_buf.ptr,
+ .property_names = utf8.ptr,
.bundle_ctx = undefined,
.property_getters = property_getters,
.node_module_global_class = undefined,
@@ -748,10 +730,9 @@ pub const Module = struct {
// };
// node_module_global_class_def.staticFunctions = &node_module_list.static_functions;
node_module_list.node_module_global_class_def = node_module_global_class_def;
- node_module_list.node_module_global_class = js.JSClassCreate(&node_module_list.node_module_global_class_def);
- node_module_list.bundle_ctx = js.JSGlobalContextCreateInGroup(vm.group, node_module_list.node_module_global_class);
-
- return node_module_list;
+ node_module_list.node_module_global_class = js.JSClassRetain(js.JSClassCreate(&node_module_list.node_module_global_class_def));
+ node_module_list.bundle_ctx = js.JSGlobalContextRetain(js.JSGlobalContextCreateInGroup(vm.group, node_module_list.node_module_global_class));
+ _ = js.JSObjectSetPrivate(js.JSContextGetGlobalObject(node_module_list.bundle_ctx), node_module_list);
}
};
pub const node_module_global_class_name = "NodeModuleGlobal";
@@ -759,6 +740,21 @@ pub const Module = struct {
threadlocal var require_buf: MutableString = undefined;
threadlocal var require_buf_loaded: bool = false;
+ pub fn callExportsAsFunction(
+ this: *Module,
+ ctx: js.JSContextRef,
+ function: js.JSObjectRef,
+ thisObject: js.JSObjectRef,
+ arguments: []const js.JSValueRef,
+ exception: js.ExceptionRef,
+ ) js.JSValueRef {
+ if (js.JSObjectIsFunction(ctx, this.exports_function)) {
+ return js.JSObjectCallAsFunction(ctx, this.exports_function, this.ref, arguments.len, arguments.ptr, exception);
+ }
+
+ return this.exports;
+ }
+
pub fn require(
this: *Module,
ctx: js.JSContextRef,
@@ -784,18 +780,20 @@ pub const Module = struct {
const len = js.JSStringGetLength(arguments[0]);
- if (!require_buf_loaded) {
- require_buf = MutableString.init(this.vm.allocator, len + 1) catch unreachable;
- require_buf_loaded = true;
- } else {
- require_buf.reset();
- require_buf.growIfNeeded(len + 1) catch {};
- }
+ // if (!require_buf_loaded) {
+ // require_buf = MutableString.init(this.vm.allocator, len + 1) catch unreachable;
+ // require_buf_loaded = true;
+ // } else {
+ // require_buf.reset();
+ // require_buf.growIfNeeded(len + 1) catch {};
+ // }
- require_buf.list.resize(this.vm.allocator, len + 1) catch unreachable;
+ // require_buf.list.resize(this.vm.allocator, len + 1) catch unreachable;
- var end = js.JSStringGetUTF8CString(arguments[0], require_buf.list.items.ptr, require_buf.list.items.len);
- var import_path = require_buf.list.items[0 .. end - 1];
+ var require_buf_ = this.vm.allocator.alloc(u8, len + 1) catch unreachable;
+ var end = js.JSStringGetUTF8CString(arguments[0], require_buf_.ptr, require_buf_.len);
+ // var end = js.JSStringGetUTF8CString(arguments[0], require_buf.list.items.ptr, require_buf.list.items.len);
+ var import_path = require_buf_[0 .. end - 1];
var module = this;
if (this.vm.bundler.linker.resolver.resolve(module.path.name.dirWithTrailingSlash(), import_path, .require)) |resolved| {
@@ -805,7 +803,14 @@ pub const Module = struct {
switch (load_result) {
.Module => |new_module| {
- return new_module.internalGetExports();
+ if (isDebug) {
+ Output.prettyln(
+ "Input: {s}\nOutput: {s}",
+ .{ import_path, load_result.Module.path.text },
+ );
+ Output.flush();
+ }
+ return new_module.internalGetExports(js.JSContextGetGlobalContext(ctx));
},
.Path => |path| {
return js.JSStringCreateWithUTF8CString(path.text.ptr);
@@ -831,6 +836,10 @@ pub const Module = struct {
.get = getId,
.ro = true,
},
+ .@"loaded" = .{
+ .get = getLoaded,
+ .ro = true,
+ },
.@"exports" = .{
.get = getExports,
.set = setExports,
@@ -848,6 +857,8 @@ pub const Module = struct {
pub fn boot(vm: *VirtualMachine) void {
ExportsClass = std.mem.zeroes(js.JSClassDefinition);
ExportsClass.className = ExportsClassName[0.. :0];
+ ExportsClass.callAsFunction = To.JS.Callback(Module, callExportsAsFunction).rfn;
+ // ExportsClass.callAsConstructor = To.JS.Callback(Module, callExportsAsConstructor);
exports_class_ref = js.JSClassRetain(js.JSClassCreate(&ExportsClass));
@@ -869,22 +880,26 @@ pub const Module = struct {
threadlocal var source_code_printer_loaded: bool = false;
var require_module_params: [3]js.JSStringRef = undefined;
var require_module_params_loaded: bool = false;
+ threadlocal var module_wrapper_params: [2]js.JSStringRef = undefined;
+ threadlocal var module_wrapper_loaded = false;
pub fn load(
+ module: *Module,
vm: *VirtualMachine,
allocator: *std.mem.Allocator,
log: *logger.Log,
source: [:0]u8,
path: Fs.Path,
+ global_ctx: js.JSContextRef,
call_ctx: js.JSContextRef,
function_ctx: js.JSContextRef,
exception: js.ExceptionRef,
- ) !*Module {
- var source_code_ref = js.JSStringRetain(js.JSStringCreateWithUTF8CString(source.ptr));
+ ) !void {
+ var source_code_ref = js.JSStringCreateWithUTF8CString(source.ptr);
defer js.JSStringRelease(source_code_ref);
var source_url = try allocator.dupeZ(u8, path.text);
defer allocator.free(source_url);
- var source_url_ref = js.JSStringRetain(js.JSStringCreateWithUTF8CString(source_url.ptr));
+ var source_url_ref = js.JSStringCreateWithUTF8CString(source_url.ptr);
defer js.JSStringRelease(source_url_ref);
if (isDebug) {
@@ -892,43 +907,49 @@ pub const Module = struct {
Output.flush();
}
- var module = try allocator.create(Module);
module.* = Module{
.path = path,
.ref = undefined,
.vm = vm,
};
- module.ref = js.JSObjectMake(function_ctx, Module.module_class, module);
+ module.ref = js.JSObjectMake(global_ctx, Module.module_class, module);
- js.JSValueProtect(function_ctx, module.ref);
+ js.JSValueProtect(global_ctx, module.ref);
- // TODO: move these allocations to only occur once
- var args = try allocator.alloc(js.JSValueRef, 2);
- var params = try allocator.alloc(js.JSStringRef, 2);
- params[0] = js.JSStringCreateWithUTF8CString(Properties.UTF8.module[0.. :0]);
- params[1] = js.JSStringCreateWithUTF8CString(Properties.UTF8.exports[0.. :0]);
- args[0] = module.ref;
- args[1] = module.internalGetExports();
- js.JSValueProtect(function_ctx, args[1]);
+ if (!module_wrapper_loaded) {
+ module_wrapper_params[0] = js.JSStringCreateWithUTF8CString(Properties.UTF8.module[0.. :0]);
+ module_wrapper_params[1] = js.JSStringCreateWithUTF8CString(Properties.UTF8.exports[0.. :0]);
+ module_wrapper_loaded = true;
+ }
- defer allocator.free(args);
+ var module_wrapper_args: [2]js.JSValueRef = undefined;
+ module_wrapper_args[0] = module.ref;
+ module_wrapper_args[1] = module.internalGetExports(global_ctx);
+ js.JSValueProtect(global_ctx, module_wrapper_args[1]);
var except: js.JSValueRef = null;
go: {
var commonjs_wrapper = js.JSObjectMakeFunction(
- function_ctx,
+ global_ctx,
null,
- @truncate(c_uint, params.len),
- params.ptr,
+ @truncate(c_uint, module_wrapper_params.len),
+ &module_wrapper_params,
source_code_ref,
null,
1,
&except,
);
+ js.JSValueProtect(global_ctx, commonjs_wrapper);
if (except != null) {
break :go;
}
-
- _ = js.JSObjectCallAsFunction(call_ctx, commonjs_wrapper, null, 2, args.ptr, &except);
+ // var module = {exports: {}}; ((module, exports) => {
+ _ = js.JSObjectCallAsFunction(call_ctx, commonjs_wrapper, null, 2, &module_wrapper_args, &except);
+ // module.exports = exports;
+ // })(module, module.exports);
+
+ // module.exports = module_wrapper_args[1];
+ js.JSValueProtect(global_ctx, module.exports);
+ js.JSValueUnprotect(global_ctx, commonjs_wrapper);
}
if (except != null) {
var message = js.JSValueToStringCopy(function_ctx, except.?, null);
@@ -948,7 +969,8 @@ pub const Module = struct {
});
return error.FailedException;
}
- return module;
+
+ module.loaded = true;
}
pub fn loadFromResolveResult(
@@ -963,7 +985,14 @@ pub const Module = struct {
}
const path = resolved.path_pair.primary;
- const loader = vm.bundler.options.loaders.get(path.name.ext) orelse .file;
+ const loader: options.Loader = brk: {
+ if (resolved.is_external) {
+ break :brk options.Loader.file;
+ }
+
+ break :brk vm.bundler.options.loaders.get(path.name.ext) orelse .file;
+ };
+
switch (loader) {
.js,
.jsx,
@@ -971,21 +1000,42 @@ pub const Module = struct {
.tsx,
.json,
=> {
- if (resolved.package_json) |package_json| {
+ const package_json_ = resolved.package_json orelse brk: {
+ // package_json is sometimes null when we're loading as an absolute path
+ if (resolved.isLikelyNodeModule()) {
+ break :brk vm.bundler.resolver.packageJSONForResolvedNodeModule(&resolved);
+ }
+ break :brk null;
+ };
+
+ if (package_json_) |package_json| {
if (package_json.hash > 0) {
if (vm.node_modules) |node_modules| {
- if (node_modules.getPackageIDByHash(package_json.hash)) |package_id| {
- const package_relative_path = vm.bundler.fs.relative(
- package_json.source.path.name.dirWithTrailingSlash(),
- path.text,
- );
-
- if (node_modules.findModuleIDInPackage(
- &node_modules.bundle.packages[package_id],
- package_relative_path,
- )) |id| {
- var list = vm.node_module_list.?;
- return LoadResult{ .Module = try list.loadBundledModuleById(id) };
+ if (node_modules.getPackageIDByName(package_json.name)) |possible_package_ids| {
+ const package_id: ?u32 = brk: {
+ for (possible_package_ids) |pid| {
+ const pkg = node_modules.bundle.packages[pid];
+ if (pkg.hash == package_json.hash) {
+ break :brk pid;
+ }
+ }
+
+ break :brk null;
+ };
+
+ if (package_id) |pid| {
+ const package_relative_path = vm.bundler.fs.relative(
+ package_json.source.path.name.dirWithTrailingSlash(),
+ path.text,
+ );
+
+ if (node_modules.findModuleIDInPackage(
+ &node_modules.bundle.packages[pid],
+ package_relative_path,
+ )) |id| {
+ var list = vm.node_module_list.?;
+ return LoadResult{ .Module = try list.loadBundledModuleById(id + node_modules.bundle.packages[pid].modules_offset, ctx) };
+ }
}
}
}
@@ -1044,18 +1094,23 @@ pub const Module = struct {
if (written == 0) {
return error.PrintingErrorWriteFailed;
}
+ var module = try vm.allocator.create(Module);
+ errdefer vm.allocator.destroy(module);
+ try vm.require_cache.put(hash, module);
- var module = try Module.load(
+ try Module.load(
+ module,
vm,
vm.allocator,
vm.log,
source_code_printer.ctx.sentinel,
path,
- ctx,
vm.global.ctx,
+ ctx,
+ ctx,
exception,
);
- try vm.require_cache.put(hash, module);
+
return LoadResult{ .Module = module };
},
@@ -1119,6 +1174,16 @@ pub const Module = struct {
}
}
+ pub fn getLoaded(
+ this: *Module,
+ ctx: js.JSContextRef,
+ thisObject: js.JSValueRef,
+ prop: js.JSStringRef,
+ exception: js.ExceptionRef,
+ ) callconv(.C) js.JSValueRef {
+ return js.JSValueMakeBoolean(ctx, this.loaded);
+ }
+
pub fn getId(
this: *Module,
ctx: js.JSContextRef,
@@ -1140,12 +1205,12 @@ pub const Module = struct {
prop: js.JSStringRef,
exception: js.ExceptionRef,
) callconv(.C) js.JSValueRef {
- return this.internalGetExports();
+ return this.exports;
}
- pub fn internalGetExports(this: *Module) js.JSValueRef {
+ pub fn internalGetExports(this: *Module, globalContext: js.JSContextRef) js.JSValueRef {
if (this.exports == null) {
- this.exports = js.JSObjectMake(this.vm.global.ctx, exports_class_ref, this);
+ this.exports = js.JSObjectMake(globalContext, exports_class_ref, this);
}
return this.exports;
@@ -1178,8 +1243,35 @@ pub const Module = struct {
js.JSStringRelease(this.exports);
}
}
+ switch (js.JSValueGetType(ctx, value)) {
+ .kJSTypeObject => {
+ if (js.JSValueIsObjectOfClass(ctx, value, exports_class_ref)) {
+ var other = @ptrCast(
+ *Module,
+ @alignCast(
+ @alignOf(
+ *Module,
+ ),
+ js.JSObjectGetPrivate(value).?,
+ ),
+ );
+
+ if (other != this) {
+ this.exports = other.exports;
+ }
+
+ return true;
+ } else {
+ if (js.JSObjectIsFunction(ctx, value)) {
+ this.exports_function = value;
+ }
+ }
+ },
+ else => {},
+ }
this.exports = value;
+
return true;
}
@@ -1264,9 +1356,15 @@ pub const GlobalObject = struct {
std.debug.assert(js.JSObjectSetPrivate(js.JSContextGetGlobalObject(global.ctx), private));
global.ref = js.JSContextGetGlobalObject(global.ctx);
+
+ if (!printer_buf_loaded) {
+ printer_buf_loaded = true;
+ printer_buf = try MutableString.init(global.vm.allocator, 0);
+ }
}
- threadlocal var printer_buf: [4092]u8 = undefined;
+ threadlocal var printer_buf: MutableString = undefined;
+ threadlocal var printer_buf_loaded: bool = false;
fn valuePrinter(comptime ValueType: js.JSType, ctx: js.JSContextRef, arg: js.JSValueRef, writer: anytype) !void {
switch (ValueType) {
.kJSTypeUndefined => {
@@ -1289,8 +1387,17 @@ pub const GlobalObject = struct {
);
},
.kJSTypeString => {
- const used = js.JSStringGetUTF8CString(arg, (&printer_buf), printer_buf.len);
- try writer.writeAll(printer_buf[0..used]);
+ printer_buf.reset();
+ var string_ref = js.JSValueToStringCopy(ctx, arg, null);
+ const len = js.JSStringGetMaximumUTF8CStringSize(string_ref) + 1;
+
+ printer_buf.growIfNeeded(len) catch {};
+ printer_buf.inflate(len) catch {};
+ var slice = printer_buf.toOwnedSliceLeaky();
+
+ defer js.JSStringRelease(string_ref);
+ const used = js.JSStringGetUTF8CString(string_ref, slice.ptr, slice.len);
+ try writer.writeAll(slice[0..used]);
},
.kJSTypeObject => {
// TODO:
diff --git a/src/javascript/jsc/node_env_buf_map.zig b/src/javascript/jsc/node_env_buf_map.zig
index 4e965a8e8..7625ee6a1 100644
--- a/src/javascript/jsc/node_env_buf_map.zig
+++ b/src/javascript/jsc/node_env_buf_map.zig
@@ -12,7 +12,7 @@ pub const NodeEnvBufMap = struct {
pub fn get(this: *const NodeEnvBufMap, key: string) ?string {
return this.backing.get(key);
}
- pub threadlocal var bufkeybuf: [1024]u8 = undefined;
+ pub threadlocal var bufkeybuf: [4096]u8 = undefined;
pub threadlocal var bufkeybuf_first = true;
pub fn iterator(this: *NodeEnvBufMap) @typeInfo(@TypeOf(std.BufMap.iterator)).Fn.return_type.? {