diff options
-rw-r--r-- | src/bun.js/ResolveMessage.zig | 22 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGeneratedClasses.cpp | 38 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGeneratedClasses.h | 1 | ||||
-rw-r--r-- | src/bun.js/bindings/generated_classes.zig | 26 | ||||
-rw-r--r-- | src/bun.js/javascript.zig | 2 | ||||
-rw-r--r-- | src/bun.js/resolve_message.classes.ts | 7 | ||||
-rw-r--r-- | src/bundler.zig | 1 | ||||
-rw-r--r-- | src/js/builtins/Module.ts | 12 | ||||
-rw-r--r-- | src/js/out/WebCoreJSBuiltins.cpp | 4 | ||||
-rw-r--r-- | src/js_printer.zig | 3 | ||||
-rw-r--r-- | test/js/bun/resolve/resolve-error.test.ts | 25 |
11 files changed, 122 insertions, 19 deletions
diff --git a/src/bun.js/ResolveMessage.zig b/src/bun.js/ResolveMessage.zig index 457a8ec4f..cf2c5f496 100644 --- a/src/bun.js/ResolveMessage.zig +++ b/src/bun.js/ResolveMessage.zig @@ -26,6 +26,28 @@ pub const ResolveMessage = struct { return null; } + pub fn getCode(this: *ResolveMessage, globalObject: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { + switch (this.msg.metadata) { + .resolve => |resolve| { + const label: []const u8 = brk: { + if (resolve.import_kind.isCommonJS()) { + break :brk "MODULE_NOT_FOUND"; + } + + break :brk switch (resolve.import_kind) { + .stmt, .dynamic => "ERR_MODULE_NOT_FOUND", + else => "RESOLVE_ERROR", + }; + }; + + var atom = bun.String.createAtom(label); + defer atom.deref(); + return atom.toJS(globalObject); + }, + else => return .undefined, + } + } + pub fn fmt(allocator: std.mem.Allocator, specifier: string, referrer: string, err: anyerror) !string { switch (err) { error.ModuleNotFound => { diff --git a/src/bun.js/bindings/ZigGeneratedClasses.cpp b/src/bun.js/bindings/ZigGeneratedClasses.cpp index 225fb5385..7106357b2 100644 --- a/src/bun.js/bindings/ZigGeneratedClasses.cpp +++ b/src/bun.js/bindings/ZigGeneratedClasses.cpp @@ -17471,6 +17471,9 @@ extern "C" void ResolveMessageClass__finalize(void*); extern "C" EncodedJSValue ResolveMessagePrototype__toPrimitive(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); JSC_DECLARE_HOST_FUNCTION(ResolveMessagePrototype__toPrimitiveCallback); +extern "C" JSC::EncodedJSValue ResolveMessagePrototype__getCode(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); +JSC_DECLARE_CUSTOM_GETTER(ResolveMessagePrototype__codeGetterWrap); + extern "C" JSC::EncodedJSValue ResolveMessagePrototype__getImportKind(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); JSC_DECLARE_CUSTOM_GETTER(ResolveMessagePrototype__importKindGetterWrap); @@ -17498,6 +17501,7 @@ JSC_DECLARE_HOST_FUNCTION(ResolveMessagePrototype__toStringCallback); STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSResolveMessagePrototype, JSResolveMessagePrototype::Base); static const HashTableValue JSResolveMessagePrototypeTableValues[] = { + { "code"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, ResolveMessagePrototype__codeGetterWrap, 0 } }, { "importKind"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, ResolveMessagePrototype__importKindGetterWrap, 0 } }, { "level"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, ResolveMessagePrototype__levelGetterWrap, 0 } }, { "message"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, ResolveMessagePrototype__messageGetterWrap, 0 } }, @@ -17550,6 +17554,37 @@ JSC_DEFINE_HOST_FUNCTION(ResolveMessagePrototype__toPrimitiveCallback, (JSGlobal return ResolveMessagePrototype__toPrimitive(thisObject->wrapped(), lexicalGlobalObject, callFrame); } +JSC_DEFINE_CUSTOM_GETTER(ResolveMessagePrototype__codeGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + auto& vm = lexicalGlobalObject->vm(); + Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + JSResolveMessage* thisObject = jsCast<JSResolveMessage*>(JSValue::decode(thisValue)); + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + + if (JSValue cachedValue = thisObject->m_code.get()) + return JSValue::encode(cachedValue); + + JSC::JSValue result = JSC::JSValue::decode( + ResolveMessagePrototype__getCode(thisObject->wrapped(), globalObject)); + RETURN_IF_EXCEPTION(throwScope, {}); + thisObject->m_code.set(vm, thisObject, result); + RELEASE_AND_RETURN(throwScope, JSValue::encode(result)); +} + +extern "C" void ResolveMessagePrototype__codeSetCachedValue(JSC::EncodedJSValue thisValue, JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue value) +{ + auto& vm = globalObject->vm(); + auto* thisObject = jsCast<JSResolveMessage*>(JSValue::decode(thisValue)); + thisObject->m_code.set(vm, thisObject, JSValue::decode(value)); +} + +extern "C" EncodedJSValue ResolveMessagePrototype__codeGetCachedValue(JSC::EncodedJSValue thisValue) +{ + auto* thisObject = jsCast<JSResolveMessage*>(JSValue::decode(thisValue)); + return JSValue::encode(thisObject->m_code.get()); +} + JSC_DEFINE_CUSTOM_GETTER(ResolveMessagePrototype__importKindGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) { auto& vm = lexicalGlobalObject->vm(); @@ -17797,7 +17832,6 @@ void JSResolveMessagePrototype::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* Base::finishCreation(vm); reifyStaticProperties(vm, JSResolveMessage::info(), JSResolveMessagePrototypeTableValues, *this); this->putDirect(vm, vm.propertyNames->toPrimitiveSymbol, JSFunction::create(vm, globalObject, 1, String("toPrimitive"_s), ResolveMessagePrototype__toPrimitiveCallback, ImplementationVisibility::Public), PropertyAttribute::Function | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum | 0); - this->putDirect(vm, Identifier::fromString(vm, "code"_s), jsString(vm, String("ERR_MODULE_NOT_FOUND"_s)), PropertyAttribute::ReadOnly | 0); this->putDirect(vm, vm.propertyNames->name, jsString(vm, String("ResolveMessage"_s)), PropertyAttribute::ReadOnly | 0); JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); } @@ -17953,6 +17987,7 @@ void JSResolveMessage::visitChildrenImpl(JSCell* cell, Visitor& visitor) ASSERT_GC_OBJECT_INHERITS(thisObject, info()); Base::visitChildren(thisObject, visitor); + visitor.append(thisObject->m_code); visitor.append(thisObject->m_importKind); visitor.append(thisObject->m_level); visitor.append(thisObject->m_message); @@ -17969,6 +18004,7 @@ void JSResolveMessage::visitAdditionalChildren(Visitor& visitor) JSResolveMessage* thisObject = this; ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + visitor.append(thisObject->m_code); visitor.append(thisObject->m_importKind); visitor.append(thisObject->m_level); visitor.append(thisObject->m_message); diff --git a/src/bun.js/bindings/ZigGeneratedClasses.h b/src/bun.js/bindings/ZigGeneratedClasses.h index 6ed7eb5de..b8b694068 100644 --- a/src/bun.js/bindings/ZigGeneratedClasses.h +++ b/src/bun.js/bindings/ZigGeneratedClasses.h @@ -1854,6 +1854,7 @@ public: template<typename Visitor> void visitAdditionalChildren(Visitor&); DECLARE_VISIT_OUTPUT_CONSTRAINTS; + mutable JSC::WriteBarrier<JSC::Unknown> m_code; mutable JSC::WriteBarrier<JSC::Unknown> m_importKind; mutable JSC::WriteBarrier<JSC::Unknown> m_level; mutable JSC::WriteBarrier<JSC::Unknown> m_message; diff --git a/src/bun.js/bindings/generated_classes.zig b/src/bun.js/bindings/generated_classes.zig index bf1942fd6..50e1a620b 100644 --- a/src/bun.js/bindings/generated_classes.zig +++ b/src/bun.js/bindings/generated_classes.zig @@ -4357,6 +4357,28 @@ pub const JSResolveMessage = struct { return ResolveMessage__fromJS(value); } + extern fn ResolveMessagePrototype__codeSetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) void; + + extern fn ResolveMessagePrototype__codeGetCachedValue(JSC.JSValue) JSC.JSValue; + + /// `ResolveMessage.code` setter + /// This value will be visited by the garbage collector. + pub fn codeSetCached(thisValue: JSC.JSValue, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) void { + JSC.markBinding(@src()); + ResolveMessagePrototype__codeSetCachedValue(thisValue, globalObject, value); + } + + /// `ResolveMessage.code` getter + /// This value will be visited by the garbage collector. + pub fn codeGetCached(thisValue: JSC.JSValue) ?JSC.JSValue { + JSC.markBinding(@src()); + const result = ResolveMessagePrototype__codeGetCachedValue(thisValue); + if (result == .zero) + return null; + + return result; + } + extern fn ResolveMessagePrototype__importKindSetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) void; extern fn ResolveMessagePrototype__importKindGetCachedValue(JSC.JSValue) JSC.JSValue; @@ -4538,6 +4560,9 @@ pub const JSResolveMessage = struct { if (@TypeOf(ResolveMessage.toPrimitive) != CallbackType) @compileLog("Expected ResolveMessage.toPrimitive to be a callback but received " ++ @typeName(@TypeOf(ResolveMessage.toPrimitive))); + if (@TypeOf(ResolveMessage.getCode) != GetterType) + @compileLog("Expected ResolveMessage.getCode to be a getter"); + if (@TypeOf(ResolveMessage.getImportKind) != GetterType) @compileLog("Expected ResolveMessage.getImportKind to be a getter"); @@ -4563,6 +4588,7 @@ pub const JSResolveMessage = struct { if (!JSC.is_bindgen) { @export(ResolveMessage.constructor, .{ .name = "ResolveMessageClass__construct" }); @export(ResolveMessage.finalize, .{ .name = "ResolveMessageClass__finalize" }); + @export(ResolveMessage.getCode, .{ .name = "ResolveMessagePrototype__getCode" }); @export(ResolveMessage.getImportKind, .{ .name = "ResolveMessagePrototype__getImportKind" }); @export(ResolveMessage.getLevel, .{ .name = "ResolveMessagePrototype__getLevel" }); @export(ResolveMessage.getMessage, .{ .name = "ResolveMessagePrototype__getMessage" }); diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig index 07d3f64cf..a016129e2 100644 --- a/src/bun.js/javascript.zig +++ b/src/bun.js/javascript.zig @@ -1652,7 +1652,7 @@ pub const VirtualMachine = struct { ), .metadata = .{ // import_kind is wrong probably - .resolve = .{ .specifier = logger.BabyString.in(printed, specifier_utf8.slice()), .import_kind = .stmt }, + .resolve = .{ .specifier = logger.BabyString.in(printed, specifier_utf8.slice()), .import_kind = if (is_esm) .stmt else .require }, }, }; }; diff --git a/src/bun.js/resolve_message.classes.ts b/src/bun.js/resolve_message.classes.ts index 734e766ba..3e3c6d083 100644 --- a/src/bun.js/resolve_message.classes.ts +++ b/src/bun.js/resolve_message.classes.ts @@ -13,6 +13,10 @@ export default [ getter: "getMessage", cache: true, }, + code: { + getter: "getCode", + cache: true, + }, name: { value: "ResolveMessage", }, @@ -32,9 +36,6 @@ export default [ getter: "getImportKind", cache: true, }, - code: { - value: "ERR_MODULE_NOT_FOUND", - }, position: { getter: "getPosition", cache: true, diff --git a/src/bundler.zig b/src/bundler.zig index ce7d9fc42..4e8d92e3c 100644 --- a/src/bundler.zig +++ b/src/bundler.zig @@ -1126,6 +1126,7 @@ pub const Bundler = struct { .minify_identifiers = bundler.options.minify_identifiers, .transform_only = bundler.options.transform_only, .module_type = if (ast.exports_kind == .cjs) .cjs else .esm, + .inline_require_and_import_errors = false, }, enable_source_map, ), diff --git a/src/js/builtins/Module.ts b/src/js/builtins/Module.ts index ca7c0fa91..d6ebc8578 100644 --- a/src/js/builtins/Module.ts +++ b/src/js/builtins/Module.ts @@ -82,17 +82,7 @@ export function require(this: CommonJSModuleRecord, id: string) { } export function requireResolve(this: string | { path: string }, id: string) { - // This try catch is needed because err.code on ESM resolves is ERR_MODULE_NOT_FOUND - // while in require.resolve this error code is only MODULE_NOT_FOUND. - // `local-pkg` will check for .code's exact value, and log extra messages if we don't match it. - try { - return $resolveSync(id, typeof this === "string" ? this : this?.path, false); - } catch (error) { - var e = new Error(`Cannot find module '${id}'`); - e.code = "MODULE_NOT_FOUND"; - // e.requireStack = []; // TODO: we might have to implement this - throw e; - } + return $resolveSync(id, typeof this === "string" ? this : this?.path, false); } export function requireNativeModule(id: string) { diff --git a/src/js/out/WebCoreJSBuiltins.cpp b/src/js/out/WebCoreJSBuiltins.cpp index 285c4b899..70822eaca 100644 --- a/src/js/out/WebCoreJSBuiltins.cpp +++ b/src/js/out/WebCoreJSBuiltins.cpp @@ -722,9 +722,9 @@ const char* const s_moduleRequireCode = "(function (id){\"use strict\";const exi const JSC::ConstructAbility s_moduleRequireResolveCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; const JSC::ConstructorKind s_moduleRequireResolveCodeConstructorKind = JSC::ConstructorKind::None; const JSC::ImplementationVisibility s_moduleRequireResolveCodeImplementationVisibility = JSC::ImplementationVisibility::Public; -const int s_moduleRequireResolveCodeLength = 194; +const int s_moduleRequireResolveCodeLength = 96; static const JSC::Intrinsic s_moduleRequireResolveCodeIntrinsic = JSC::NoIntrinsic; -const char* const s_moduleRequireResolveCode = "(function (id){\"use strict\";try{return @resolveSync(id,typeof this===\"string\"\?this:this\?.path,!1)}catch(error){var e=new Error(`Cannot find module '${id}'`);throw e.code=\"MODULE_NOT_FOUND\",e}})\n"; +const char* const s_moduleRequireResolveCode = "(function (id){\"use strict\";return @resolveSync(id,typeof this===\"string\"\?this:this\?.path,!1)})\n"; // requireNativeModule const JSC::ConstructAbility s_moduleRequireNativeModuleCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; diff --git a/src/js_printer.zig b/src/js_printer.zig index 0cdf21f08..ca8b18ad0 100644 --- a/src/js_printer.zig +++ b/src/js_printer.zig @@ -501,6 +501,7 @@ pub const Options = struct { minify_identifiers: bool = false, minify_syntax: bool = false, transform_only: bool = false, + inline_require_and_import_errors: bool = true, require_or_import_meta_for_source_callback: RequireOrImportMeta.Callback = .{}, @@ -1827,7 +1828,7 @@ fn NewPrinter( if (record.kind != .dynamic) { p.printSpaceBeforeIdentifier(); - if (record.path.is_disabled and record.handles_import_errors and !is_external) { + if (record.path.is_disabled and record.handles_import_errors and !is_external and p.options.inline_require_and_import_errors) { p.printRequireError(record.path.text); return; } diff --git a/test/js/bun/resolve/resolve-error.test.ts b/test/js/bun/resolve/resolve-error.test.ts index 9d2e09fad..3b42fc72d 100644 --- a/test/js/bun/resolve/resolve-error.test.ts +++ b/test/js/bun/resolve/resolve-error.test.ts @@ -8,6 +8,31 @@ describe("ResolveMessage", () => { expect(Bun.inspect(e.position).length > 0).toBe(true); } }); + + it("has code for esm", async () => { + try { + await import("./file-importing-nonexistent-file.js"); + } catch (e: any) { + expect(e.code).toBe("ERR_MODULE_NOT_FOUND"); + } + }); + + it("has code for require.resolve", () => { + try { + require.resolve("./file-importing-nonexistent-file.js"); + } catch (e: any) { + expect(e.code).toBe("MODULE_NOT_FOUND"); + } + }); + + it("has code for require", () => { + try { + require("./file-importing-nonexistent-file.cjs"); + } catch (e: any) { + expect(e.code).toBe("MODULE_NOT_FOUND"); + } + }); + it("invalid data URL import", async () => { expect(async () => { // @ts-ignore |