diff options
author | 2021-06-29 17:47:58 -0700 | |
---|---|---|
committer | 2021-06-29 17:47:58 -0700 | |
commit | 3f197d1ce0c197864ad4c7c7b8238af4370275b4 (patch) | |
tree | 7d76dcc182e80c5b67db1568e769977229649980 | |
parent | 26745bb5f300481fc242c8e81de6f252f698c863 (diff) | |
download | bun-3f197d1ce0c197864ad4c7c7b8238af4370275b4.tar.gz bun-3f197d1ce0c197864ad4c7c7b8238af4370275b4.tar.zst bun-3f197d1ce0c197864ad4c7c7b8238af4370275b4.zip |
Fix crash, fix detecting node_modules, fix undefined not being simplified
-rw-r--r-- | demos/css-stress-test/react-inject.js | 1 | ||||
-rw-r--r-- | demos/css-stress-test/src/index.tsx | 27 | ||||
-rw-r--r-- | demos/css-stress-test/src/main.tsx | 2 | ||||
-rw-r--r-- | src/bundler.zig | 10 | ||||
-rw-r--r-- | src/defines.zig | 38 | ||||
-rw-r--r-- | src/javascript/jsc/javascript.zig | 192 | ||||
-rw-r--r-- | src/js_parser/js_parser.zig | 18 | ||||
-rw-r--r-- | src/linker.zig | 18 | ||||
-rw-r--r-- | src/options.zig | 10 |
9 files changed, 199 insertions, 117 deletions
diff --git a/demos/css-stress-test/react-inject.js b/demos/css-stress-test/react-inject.js new file mode 100644 index 000000000..199dbaa80 --- /dev/null +++ b/demos/css-stress-test/react-inject.js @@ -0,0 +1 @@ +export { default as React } from "react"; diff --git a/demos/css-stress-test/src/index.tsx b/demos/css-stress-test/src/index.tsx index 3db53a67f..267691467 100644 --- a/demos/css-stress-test/src/index.tsx +++ b/demos/css-stress-test/src/index.tsx @@ -1,20 +1,33 @@ -import ReactDOM from "react-dom"; -import React from "react"; +import ReactDOMServer from "react-dom/server.browser"; + import { Main } from "./main"; import classNames from "classnames"; - const Base = ({}) => { - const name = decodeURIComponent(location.search.substring(1)); + const name = + typeof location !== "undefined" + ? decodeURIComponent(location.search.substring(1)) + : null; return <Main productName={name || "Bundler"} />; }; function startReact() { + const ReactDOM = require("react-dom"); ReactDOM.render(<Base />, document.querySelector("#reactroot")); } -globalThis.addEventListener("DOMContentLoaded", () => { +function ssr() { + console.log(ReactDOMServer.renderToString(<Base />)); +} + +if (typeof window !== "undefined") { + console.log("HERE!!"); + globalThis.addEventListener("DOMContentLoaded", () => { + startReact(); + }); + startReact(); -}); -startReact(); +} else { + ssr(); +} export { Base }; diff --git a/demos/css-stress-test/src/main.tsx b/demos/css-stress-test/src/main.tsx index 1a9948fe8..c95d0f0eb 100644 --- a/demos/css-stress-test/src/main.tsx +++ b/demos/css-stress-test/src/main.tsx @@ -1,5 +1,3 @@ -import React from "react"; - export const Main = ({ productName }) => { return ( <> diff --git a/src/bundler.zig b/src/bundler.zig index 1d227c178..802b7cd82 100644 --- a/src/bundler.zig +++ b/src/bundler.zig @@ -491,7 +491,7 @@ pub fn NewBundler(cache_files: bool) type { var resolve = _resolve; if (resolve.is_external) return; - resolve.is_from_node_modules = strings.contains(resolve.path_pair.primary.text, node_module_root_string); + const is_from_node_modules = resolve.isLikelyNodeModule(); const loader = this.bundler.options.loaders.get(resolve.path_pair.primary.name.ext) orelse .file; var bundler = this.bundler; defer this.scan_pass_result.reset(); @@ -500,7 +500,7 @@ pub fn NewBundler(cache_files: bool) type { var hasher = std.hash.Wyhash.init(0); // If we're in a node_module, build that almost normally - if (resolve.is_from_node_modules) { + if (is_from_node_modules) { switch (loader) { .jsx, .tsx, @@ -971,8 +971,6 @@ pub fn NewBundler(cache_files: bool) type { ), .input_fd = result.input_fd, }; - // output_file.version = if (resolve_result.is_from_node_modules) resolve_result.package_json_version else null; - }, } } @@ -1158,7 +1156,7 @@ pub fn NewBundler(cache_files: bool) type { var result = ScanResult{ .path = file_path, .file_size = @truncate(u32, source.contents.len), - .is_node_module = resolve_result.is_from_node_modules or strings.contains(file_path.text, "node_modules" ++ std.fs.path.sep_str), + .is_node_module = resolve_result.isLikelyNodeModule(), .import_record_start = @truncate(u32, import_records.items.len), .import_record_length = 0, }; @@ -1290,7 +1288,7 @@ pub fn NewBundler(cache_files: bool) type { jsx.parse = loader.isJSX(); var opts = js_parser.Parser.Options.init(jsx, loader); opts.enable_bundling = false; - opts.transform_require_to_import = false; + opts.transform_require_to_import = !bundler.options.platform.implementsRequire(); opts.force_commonjs = bundler.options.platform == .speedy; opts.can_import_from_bundle = bundler.options.node_modules_bundle != null; opts.features.hot_module_reloading = bundler.options.hot_module_reloading and bundler.options.platform != .speedy; diff --git a/src/defines.zig b/src/defines.zig index 58764c241..88665aa06 100644 --- a/src/defines.zig +++ b/src/defines.zig @@ -78,17 +78,33 @@ pub const DefineData = struct { } if (js_lexer.isIdentifier(entry.value_ptr.*) and !js_lexer.Keywords.has(entry.value_ptr.*)) { - var ident: *js_ast.E.Identifier = try allocator.create(js_ast.E.Identifier); - ident.ref = Ref.None; - ident.can_be_removed_if_unused = true; - user_defines.putAssumeCapacity( - entry.key_ptr.*, - DefineData{ - .value = js_ast.Expr.Data{ .e_identifier = ident }, - .original_name = entry.value_ptr.*, - .can_be_removed_if_unused = true, - }, - ); + + // Special-case undefined. it's not an identifier here + // https://github.com/evanw/esbuild/issues/1407 + if (strings.eqlComptime(entry.value_ptr.*, "undefined")) { + user_defines.putAssumeCapacity( + entry.key_ptr.*, + DefineData{ + .value = js_ast.Expr.Data{ .e_undefined = js_ast.E.Undefined{} }, + .original_name = entry.value_ptr.*, + .can_be_removed_if_unused = true, + }, + ); + } else { + var ident: *js_ast.E.Identifier = try allocator.create(js_ast.E.Identifier); + ident.ref = Ref.None; + ident.can_be_removed_if_unused = true; + + user_defines.putAssumeCapacity( + entry.key_ptr.*, + DefineData{ + .value = js_ast.Expr.Data{ .e_identifier = ident }, + .original_name = entry.value_ptr.*, + .can_be_removed_if_unused = true, + }, + ); + } + // user_defines.putAssumeCapacity( // entry.key_ptr, // DefineData{ .value = js_ast.Expr.Data{.e_identifier = } }, diff --git a/src/javascript/jsc/javascript.zig b/src/javascript/jsc/javascript.zig index 7ff4070e5..338e05490 100644 --- a/src/javascript/jsc/javascript.zig +++ b/src/javascript/jsc/javascript.zig @@ -43,6 +43,15 @@ pub fn JSStringMap(comptime V: type) type { return std.HashMap(js.JSStringRef, V, JSStringMapContext, 60); } +const DefaultSpeedyDefines = struct { + pub const Keys = struct { + const window = "window"; + }; + pub const Values = struct { + const window = "undefined"; + }; +}; + pub fn configureTransformOptionsForSpeedy(allocator: *std.mem.Allocator, _args: Api.TransformOptions) !Api.TransformOptions { var args = _args; @@ -63,6 +72,7 @@ pub fn configureTransformOptionsForSpeedy(allocator: *std.mem.Allocator, _args: } } var needs_node_env = env_map.get("NODE_ENV") == null; + var needs_window_undefined = true; var needs_regenerate = args.define == null and env_count > 0; if (args.define) |def| { @@ -72,12 +82,16 @@ pub fn configureTransformOptionsForSpeedy(allocator: *std.mem.Allocator, _args: for (def.keys) |key| { if (strings.eql(key, "process.env.NODE_ENV")) { needs_node_env = false; + } else if (strings.eql(key, "window")) { + needs_window_undefined = false; } } } + var extras_count = @intCast(usize, @boolToInt(needs_node_env)) + @intCast(usize, @boolToInt(needs_window_undefined)); + if (needs_regenerate) { - var new_list = try allocator.alloc([]const u8, env_count * 2 + @intCast(usize, @boolToInt(needs_node_env)) * 2); + var new_list = try allocator.alloc([]const u8, env_count * 2 + extras_count * 2); var keys = new_list[0 .. new_list.len / 2]; var values = new_list[keys.len..]; var new_map = Api.StringMap{ @@ -119,7 +133,16 @@ pub fn configureTransformOptionsForSpeedy(allocator: *std.mem.Allocator, _args: if (needs_node_env) { keys[last] = options.DefaultUserDefines.NodeEnv.Key; values[last] = options.DefaultUserDefines.NodeEnv.Value; + last += 1; } + + if (needs_window_undefined) { + keys[last] = DefaultSpeedyDefines.Keys.window; + values[last] = DefaultSpeedyDefines.Values.window; + last += 1; + } + + args.define = new_map; } return args; @@ -130,7 +153,7 @@ pub fn configureTransformOptionsForSpeedy(allocator: *std.mem.Allocator, _args: // Its unavailable on Linux pub const VirtualMachine = struct { const RequireCacheType = std.AutoHashMap(u32, *Module); - root: js.JSGlobalContextRef, + // root: js.JSGlobalContextRef, ctx: js.JSGlobalContextRef = undefined, group: js.JSContextGroupRef, allocator: *std.mem.Allocator, @@ -151,8 +174,6 @@ pub const VirtualMachine = struct { ) !*VirtualMachine { var group = js.JSContextGroupRetain(js.JSContextGroupCreate()); - var ctx = js.JSGlobalContextRetain(js.JSGlobalContextCreateInGroup(group, null)); - var log: *logger.Log = undefined; if (_log) |__log| { log = __log; @@ -170,10 +191,10 @@ pub const VirtualMachine = struct { try configureTransformOptionsForSpeedy(allocator, _args), existing_bundle, ), - .node_module_list = try allocator.create(Module.NodeModuleList), + .node_module_list = null, .log = log, .group = group, - .root = ctx, + .require_cache = RequireCacheType.init(allocator), .global = global, }; @@ -189,7 +210,9 @@ pub const VirtualMachine = struct { Properties.init(); if (vm.bundler.options.node_modules_bundle) |bundle| { vm.node_modules = bundle; + vm.node_module_list = try allocator.create(Module.NodeModuleList); try Module.NodeModuleList.create(vm, bundle, vm.node_module_list.?); + vm.global.ctx = vm.node_module_list.?.bundle_ctx; } return vm; @@ -425,6 +448,7 @@ pub const Module = struct { require_cache: []?*Module, exports_function_call: js.JSObjectRef = null, + console: js.JSObjectRef = null, const RequireBundleClassName = "requireFromBundle"; var require_bundle_class_def: js.JSClassDefinition = undefined; @@ -650,6 +674,24 @@ pub const Module = struct { return module.internalGetExports(js.JSContextGetGlobalContext(ctx)); } + pub fn getConsole( + ctx: js.JSContextRef, + thisObject: js.JSObjectRef, + prop: js.JSStringRef, + exception: js.ExceptionRef, + ) callconv(.C) js.JSValueRef { + var this = @ptrCast( + *NodeModuleList, + @alignCast(@alignOf(*NodeModuleList), js.JSObjectGetPrivate(thisObject) orelse return null), + ); + + if (this.console == null) { + this.console = js.JSObjectMake(js.JSContextGetGlobalContext(ctx), this.vm.global.console_class, this.vm.global); + } + + return this.console; + } + pub fn create(vm: *VirtualMachine, bundle: *const NodeModuleBundle, node_module_list: *NodeModuleList) !void { var size: usize = 0; var longest_size: usize = 0; @@ -664,7 +706,13 @@ pub const Module = struct { 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 + 1); + var static_properties = try vm.allocator.alloc(js.JSStaticValue, bundle.bundle.modules.len + 2); + static_properties[static_properties.len - 2] = js.JSStaticValue{ + .name = Properties.UTF8.console[0.. :0], + .getProperty = getConsole, + .setProperty = null, + .attributes = .kJSPropertyAttributeNone, + }; 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); @@ -780,20 +828,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 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 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.list.items[0 .. end - 1]; var module = this; if (this.vm.bundler.linker.resolver.resolve(module.path.name.dirWithTrailingSlash(), import_path, .require)) |resolved| { @@ -803,13 +851,13 @@ pub const Module = struct { switch (load_result) { .Module => |new_module| { - if (isDebug) { - Output.prettyln( - "Input: {s}\nOutput: {s}", - .{ import_path, load_result.Module.path.text }, - ); - Output.flush(); - } + // 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| { @@ -862,7 +910,7 @@ pub const Module = struct { exports_class_ref = js.JSClassRetain(js.JSClassCreate(&ExportsClass)); - module_class_def = ModuleClass.define(vm.root); + module_class_def = ModuleClass.define(); module_class = js.JSClassRetain(js.JSClassCreate(&module_class_def)); } @@ -913,19 +961,18 @@ pub const Module = struct { .vm = vm, }; module.ref = js.JSObjectMake(global_ctx, Module.module_class, module); - js.JSValueProtect(global_ctx, module.ref); - - 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; - } + // if (!module_wrapper_loaded) { + module_wrapper_params[0] = js.JSStringRetain(js.JSStringCreateWithUTF8CString(Properties.UTF8.module[0.. :0])); + module_wrapper_params[1] = js.JSStringRetain(js.JSStringCreateWithUTF8CString(Properties.UTF8.exports[0.. :0])); + // module_wrapper_loaded = true; + // } 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( @@ -942,13 +989,14 @@ pub const Module = struct { if (except != null) { break :go; } + // 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) { @@ -1000,17 +1048,17 @@ pub const Module = struct { .tsx, .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 (vm.node_modules) |node_modules| { + 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 (package_json_) |package_json| { + if (package_json.hash > 0) { if (node_modules.getPackageIDByName(package_json.name)) |possible_package_ids| { const package_id: ?u32 = brk: { for (possible_package_ids) |pid| { @@ -1105,7 +1153,7 @@ pub const Module = struct { vm.log, source_code_printer.ctx.sentinel, path, - vm.global.ctx, + js.JSContextGetGlobalContext(ctx), ctx, ctx, exception, @@ -1287,7 +1335,6 @@ pub const GlobalObject = struct { console_definition: js.JSClassDefinition = undefined, global_class_def: js.JSClassDefinition = undefined, global_class: js.JSClassRef = undefined, - root_obj: js.JSObjectRef = undefined, pub const ConsoleClass = NewClass( GlobalObject, @@ -1324,42 +1371,28 @@ pub const GlobalObject = struct { obj: js.JSObjectRef, exception: js.ExceptionRef, ) js.JSValueRef { - return global.console; - } + // if (global.console == null) { + // global.console = js.JSObjectMake(js.JSContextGetGlobalContext(ctx), global.console_class, global); + // js.JSValueProtect(js.JSContextGetGlobalContext(ctx), global.console); + // } - pub fn onMissingProperty( - global: *GlobalObject, - ctx: js.JSContextRef, - obj: js.JSObjectRef, - prop: js.JSStringRef, - exception: js.ExceptionRef, - ) js.JSValueRef { - if (js.JSObjectHasProperty(ctx, global.root_obj, prop)) { - return js.JSObjectGetProperty(ctx, global.root_obj, prop, exception); - } else { - return js.JSValueMakeUndefined(ctx); - } + return js.JSObjectMake(js.JSContextGetGlobalContext(ctx), global.console_class, global); } pub fn boot(global: *GlobalObject) !void { - var private: ?*c_void = global; - global.root_obj = js.JSContextGetGlobalObject(global.vm.root); - - global.console_definition = ConsoleClass.define(global.vm.root); + global.console_definition = ConsoleClass.define(); global.console_class = js.JSClassRetain(js.JSClassCreate(&global.console_definition)); - global.console = js.JSObjectMake(global.vm.root, global.console_class, private); - global.global_class_def = GlobalClass.define(global.vm.root); + global.global_class_def = GlobalClass.define(); global.global_class = js.JSClassRetain(js.JSClassCreate(&global.global_class_def)); global.ctx = js.JSGlobalContextRetain(js.JSGlobalContextCreateInGroup(global.vm.group, global.global_class)); - std.debug.assert(js.JSObjectSetPrivate(js.JSContextGetGlobalObject(global.ctx), private)); - global.ref = js.JSContextGetGlobalObject(global.ctx); + std.debug.assert(js.JSObjectSetPrivate(js.JSContextGetGlobalObject(global.ctx), global)); if (!printer_buf_loaded) { printer_buf_loaded = true; - printer_buf = try MutableString.init(global.vm.allocator, 0); + printer_buf = try MutableString.init(global.vm.allocator, 4096); } } @@ -1562,7 +1595,7 @@ pub fn NewClass( exception: js.ExceptionRef, ) callconv(.C) js.JSValueRef { var instance_pointer_ = js.JSObjectGetPrivate(obj); - if (instance_pointer_ == null) return js.JSValueMakeUndefined(ctx); + if (instance_pointer_ == null) return null; var instance_pointer = instance_pointer_.?; var ptr = @ptrCast( *ZigType, @@ -1610,7 +1643,7 @@ pub fn NewClass( exception: js.ExceptionRef, ) callconv(.C) js.JSValueRef { var instance_pointer_ = js.JSObjectGetPrivate(obj); - if (instance_pointer_ == null) return js.JSValueMakeUndefined(ctx); + if (instance_pointer_ == null) return null; var this: *ZigType = @ptrCast( *ZigType, @alignCast( @@ -1634,7 +1667,7 @@ pub fn NewClass( )( this, ctx, - this.ref, + obj, exception, ); }, @@ -1648,7 +1681,7 @@ pub fn NewClass( )( this, ctx, - this.ref, + obj, prop, exception, ); @@ -1692,7 +1725,7 @@ pub fn NewClass( )( this, ctx, - this.ref, + obj, prop, value, exception, @@ -1704,16 +1737,14 @@ pub fn NewClass( }; } - pub fn define(ctx: js.JSContextRef) js.JSClassDefinition { + pub fn define() js.JSClassDefinition { var def = js.kJSClassDefinitionEmpty; if (static_functions.len > 0) { + std.mem.set(js.JSStaticFunction, &static_functions, std.mem.zeroes(js.JSStaticFunction)); + inline for (function_name_literals) |function_name, i| { var callback = To.JS.Callback(ZigType, @field(staticFunctions, function_names[i])).rfn; - function_name_refs[i] = js.JSStringCreateWithCharactersNoCopy( - function_name.ptr, - function_name.len, - ); static_functions[i] = js.JSStaticFunction{ .name = (function_names[i][0.. :0]).ptr, @@ -1725,6 +1756,7 @@ pub fn NewClass( // instance_functions[i] = function; // } } + def.staticFunctions = &static_functions; } diff --git a/src/js_parser/js_parser.zig b/src/js_parser/js_parser.zig index 63af5964d..be442728b 100644 --- a/src/js_parser/js_parser.zig +++ b/src/js_parser/js_parser.zig @@ -1892,8 +1892,8 @@ pub const Parser = struct { }, loc, ); - // Otherwise, it looks like this - // var + // Otherwise, it looks like this + // var } else { jsx_part_stmts[stmt_i] = p.s(S.Import{ .namespace_ref = automatic_namespace_ref, @@ -2196,6 +2196,7 @@ pub const Prefill = struct { }; pub const Value = struct { pub var EThis = E.This{}; + pub var Zero = E.Number{ .value = 0.0 }; }; pub const String = struct { pub var Key = E.String{ .value = &Prefill.StringLiteral.Key }; @@ -2218,6 +2219,7 @@ pub const Prefill = struct { pub var LineNumber = Expr.Data{ .e_string = &Prefill.String.LineNumber }; pub var ColumnNumber = Expr.Data{ .e_string = &Prefill.String.ColumnNumber }; pub var This = Expr.Data{ .e_this = E.This{} }; + pub var Zero = Expr.Data{ .e_number = &Value.Zero }; }; pub const Runtime = struct { pub var JSXFilename = "__jsxFilename"; @@ -10781,7 +10783,19 @@ pub fn NewParser( .e_unary => |e_| { switch (e_.op) { .un_typeof => { + const id_before = std.meta.activeTag(e_.value.data) == Expr.Tag.e_identifier; e_.value = p.visitExprInOut(e_.value, ExprIn{ .assign_target = e_.op.unaryAssignTarget() }); + const id_after = std.meta.activeTag(e_.value.data) == Expr.Tag.e_identifier; + + // The expression "typeof (0, x)" must not become "typeof x" if "x" + // is unbound because that could suppress a ReferenceError from "x" + if (!id_before and id_after and p.symbols.items[e_.value.data.e_identifier.ref.inner_index].kind == .unbound) { + e_.value = Expr.joinWithComma( + Expr{ .loc = e_.value.loc, .data = Prefill.Data.Zero }, + e_.value, + p.allocator, + ); + } if (SideEffects.toTypeof(e_.value.data)) |typeof| { return p.e(E.String{ .utf8 = typeof }, expr.loc); diff --git a/src/linker.zig b/src/linker.zig index 46d2114ca..44fd140c2 100644 --- a/src/linker.zig +++ b/src/linker.zig @@ -204,16 +204,21 @@ pub fn NewLinker(comptime BundlerType: type) type { continue; } - if (linker.resolver.resolve(source_dir, import_record.path.text, import_record.kind)) |*_resolved_import| { - var resolved_import: *Resolver.Result = _resolved_import; + const resolved_import: *const Resolver.Result = _resolved_import; if (resolved_import.is_external) { externals.append(record_index) catch unreachable; continue; } + if (linker.options.node_modules_bundle) |node_modules_bundle| { + const package_json_ = resolved_import.package_json orelse brk: { + if (resolved_import.isLikelyNodeModule()) { + break :brk linker.resolver.packageJSONForResolvedNodeModule(resolved_import); + } - if (resolved_import.package_json) |package_json| { - if (linker.options.node_modules_bundle) |node_modules_bundle| { + break :brk null; + }; + if (package_json_) |package_json| { if (strings.contains(package_json.source.path.name.dirWithTrailingSlash(), "node_modules")) { if (node_modules_bundle.getPackageIDByName(package_json.name)) |possible_pkg_ids| { const pkg_id: u32 = brk: { @@ -537,14 +542,11 @@ pub fn NewLinker(comptime BundlerType: type) type { linker: *ThisLinker, loader: Options.Loader, source_dir: string, - resolve_result: *Resolver.Result, + resolve_result: *const Resolver.Result, import_record: *ImportRecord, comptime import_path_format: Options.BundleOptions.ImportPathFormat, ) !void { - // extremely naive. - resolve_result.is_from_node_modules = resolve_result.package_json != null or strings.contains(resolve_result.path_pair.primary.text, "/node_modules"); - // lazy means: // Run the resolver // Don't parse/print automatically. diff --git a/src/options.zig b/src/options.zig index 132de8ca3..50f3efb11 100644 --- a/src/options.zig +++ b/src/options.zig @@ -249,6 +249,13 @@ pub const Platform = enum { speedy, node, + pub fn implementsRequire(platform: Platform) bool { + return switch (platform) { + .speedy, .node => true, + else => false, + }; + } + pub const Extensions = struct { pub const In = struct { pub const JavaScript = [_]string{ ".js", ".ts", ".tsx", ".jsx", ".json" }; @@ -754,7 +761,7 @@ pub const BundleOptions = struct { opts.output_dir_handle = try openOutputDir(opts.output_dir); } - if (opts.resolve_mode == .lazy and !(transform.generate_node_module_bundle orelse false)) { + if (!(transform.generate_node_module_bundle orelse false)) { if (node_modules_bundle_existing) |node_mods| { opts.node_modules_bundle = node_mods; const pretty_path = fs.relativeTo(transform.node_modules_bundle_path.?); @@ -768,6 +775,7 @@ pub const BundleOptions = struct { const pretty_path = fs.relativeTo(bundle_path); var bundle_file = std.fs.openFileAbsolute(bundle_path, .{ .read = true, .write = true }) catch |err| { Output.disableBuffering(); + defer Output.enableBuffering(); Output.prettyErrorln("<r>error opening <d>\"<r><b>{s}<r><d>\":<r> <b><red>{s}<r>", .{ pretty_path, @errorName(err) }); break :load_bundle; }; |