diff --git a/cmake/tools/SetupGit.cmake b/cmake/tools/SetupGit.cmake index 769735b7b0..7f28fe7743 100644 --- a/cmake/tools/SetupGit.cmake +++ b/cmake/tools/SetupGit.cmake @@ -36,7 +36,8 @@ endif() string(REPLACE "\n" ";" GIT_CHANGED_SOURCES "${GIT_DIFF}") if(CI) - setx(GIT_CHANGED_SOURCES ${GIT_CHANGED_SOURCES}) + set(GIT_CHANGED_SOURCES "${GIT_CHANGED_SOURCES}") + message(STATUS "Set GIT_CHANGED_SOURCES: ${GIT_CHANGED_SOURCES}") endif() list(TRANSFORM GIT_CHANGED_SOURCES PREPEND ${CWD}/) diff --git a/src/bake/production.zig b/src/bake/production.zig index e4441ee5df..5c8892bc65 100644 --- a/src/bake/production.zig +++ b/src/bake/production.zig @@ -633,7 +633,7 @@ export fn BakeProdResolve(global: *JSC.JSGlobalObject, a_str: bun.String, specif const specifier = specifier_str.toUTF8(alloc); defer specifier.deinit(); - if (JSC.HardcodedModule.Aliases.get(specifier.slice(), .bun)) |alias| { + if (JSC.HardcodedModule.Alias.get(specifier.slice(), .bun)) |alias| { return bun.String.static(alias.path); } diff --git a/src/bun.js/ResolveMessage.zig b/src/bun.js/ResolveMessage.zig index 99e8344250..bcbb5c70a9 100644 --- a/src/bun.js/ResolveMessage.zig +++ b/src/bun.js/ResolveMessage.zig @@ -25,18 +25,35 @@ pub const ResolveMessage = struct { pub fn getCode(this: *ResolveMessage, globalObject: *JSC.JSGlobalObject) JSC.JSValue { switch (this.msg.metadata) { .resolve => |resolve| { - const label: []const u8 = brk: { - if (resolve.import_kind.isCommonJS()) { - break :brk "MODULE_NOT_FOUND"; - } + const code: []const u8 = brk: { + const specifier = this.msg.metadata.resolve.specifier.slice(this.msg.data.text); break :brk switch (resolve.import_kind) { - .stmt, .dynamic => "ERR_MODULE_NOT_FOUND", - else => "RESOLVE_ERROR", + // Match Node.js error codes. CommonJS is historic + // before they started prefixing with 'ERR_' + .require => if (bun.strings.hasPrefixComptime(specifier, "node:")) + break :brk "ERR_UNKNOWN_BUILTIN_MODULE" + else + break :brk "MODULE_NOT_FOUND", + // require resolve does not have the UNKNOWN_BUILTIN_MODULE error code + .require_resolve => "MODULE_NOT_FOUND", + .stmt, .dynamic => if (bun.strings.hasPrefixComptime(specifier, "node:")) + break :brk "ERR_UNKNOWN_BUILTIN_MODULE" + else + break :brk "ERR_MODULE_NOT_FOUND", + + .entry_point_run, + .entry_point_build, + .at, + .at_conditional, + .url, + .internal, + .composes, + => "RESOLVE_ERROR", }; }; - var atom = bun.String.createAtomASCII(label); + var atom = bun.String.createAtomASCII(code); defer atom.deref(); return atom.toJS(globalObject); }, @@ -61,7 +78,11 @@ pub const ResolveMessage = struct { return JSC.JSValue.jsNumber(@as(i32, 0)); } - pub fn fmt(allocator: std.mem.Allocator, specifier: string, referrer: string, err: anyerror) !string { + pub fn fmt(allocator: std.mem.Allocator, specifier: string, referrer: string, err: anyerror, import_kind: bun.ImportKind) !string { + if (import_kind != .require_resolve and bun.strings.hasPrefixComptime(specifier, "node:")) { + // This matches Node.js exactly. + return try std.fmt.allocPrint(allocator, "No such built-in module: {s}", .{specifier}); + } switch (err) { error.ModuleNotFound => { if (strings.eqlComptime(referrer, "bun:main")) { @@ -76,6 +97,9 @@ pub const ResolveMessage = struct { error.InvalidDataURL => { return try std.fmt.allocPrint(allocator, "Cannot resolve invalid data URL '{s}' from '{s}'", .{ specifier, referrer }); }, + error.InvalidURL => { + return try std.fmt.allocPrint(allocator, "Cannot resolve invalid URL '{s}' from '{s}'", .{ specifier, referrer }); + }, else => { if (Resolver.isPackagePath(specifier)) { return try std.fmt.allocPrint(allocator, "{s} while resolving package '{s}' from '{s}'", .{ @errorName(err), specifier, referrer }); diff --git a/src/bun.js/api/BunObject.zig b/src/bun.js/api/BunObject.zig index 92ce440073..205fb6c3e8 100644 --- a/src/bun.js/api/BunObject.zig +++ b/src/bun.js/api/BunObject.zig @@ -234,7 +234,6 @@ const JSInternalPromise = bun.JSC.JSInternalPromise; const JSModuleLoader = bun.JSC.JSModuleLoader; const JSPromiseRejectionOperation = bun.JSC.JSPromiseRejectionOperation; const ErrorableZigString = bun.JSC.ErrorableZigString; -const ZigGlobalObject = bun.JSC.ZigGlobalObject; const VM = bun.JSC.VM; const JSFunction = bun.JSC.JSFunction; const Config = @import("../config.zig"); @@ -894,10 +893,11 @@ fn doResolve(globalThis: *JSC.JSGlobalObject, arguments: []const JSValue) bun.JS from_str, is_esm, false, + false, ); } -fn doResolveWithArgs(ctx: js.JSContextRef, specifier: bun.String, from: bun.String, is_esm: bool, comptime is_file_path: bool) bun.JSError!JSC.JSValue { +fn doResolveWithArgs(ctx: js.JSContextRef, specifier: bun.String, from: bun.String, is_esm: bool, comptime is_file_path: bool, is_user_require_resolve: bool) bun.JSError!JSC.JSValue { var errorable: ErrorableString = undefined; var query_string = ZigString.Empty; @@ -907,25 +907,16 @@ fn doResolveWithArgs(ctx: js.JSContextRef, specifier: bun.String, from: bun.Stri specifier.dupeRef(); defer specifier_decoded.deref(); - if (comptime is_file_path) { - VirtualMachine.resolveFilePathForAPI( - &errorable, - ctx, - specifier_decoded, - from, - &query_string, - is_esm, - ); - } else { - VirtualMachine.resolveForAPI( - &errorable, - ctx, - specifier_decoded, - from, - &query_string, - is_esm, - ); - } + try VirtualMachine.resolveMaybeNeedsTrailingSlash( + &errorable, + ctx, + specifier_decoded, + from, + &query_string, + is_esm, + is_file_path, + is_user_require_resolve, + ); if (!errorable.success) { return ctx.throwValue(bun.cast(JSC.JSValueRef, errorable.result.err.ptr.?).?.value()); @@ -948,8 +939,7 @@ fn doResolveWithArgs(ctx: js.JSContextRef, specifier: bun.String, from: bun.Stri } pub fn resolveSync(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { - const arguments = callframe.arguments_old(3); - return try doResolve(globalObject, arguments.slice()); + return try doResolve(globalObject, callframe.arguments()); } pub fn resolve(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { @@ -968,7 +958,7 @@ export fn Bun__resolve(global: *JSGlobalObject, specifier: JSValue, source: JSVa const source_str = source.toBunString(global) catch return .zero; defer source_str.deref(); - const value = doResolveWithArgs(global, specifier_str, source_str, is_esm, true) catch { + const value = doResolveWithArgs(global, specifier_str, source_str, is_esm, true, false) catch { const err = global.tryTakeException().?; return JSC.JSPromise.rejectedPromiseValue(global, err); }; @@ -976,25 +966,32 @@ export fn Bun__resolve(global: *JSGlobalObject, specifier: JSValue, source: JSVa return JSC.JSPromise.resolvedPromiseValue(global, value); } -export fn Bun__resolveSync(global: *JSGlobalObject, specifier: JSValue, source: JSValue, is_esm: bool) JSC.JSValue { +export fn Bun__resolveSync(global: *JSGlobalObject, specifier: JSValue, source: JSValue, is_esm: bool, is_user_require_resolve: bool) JSC.JSValue { const specifier_str = specifier.toBunString(global) catch return .zero; defer specifier_str.deref(); + if (specifier_str.length() == 0) { + return global.ERR_INVALID_ARG_VALUE("The argument 'id' must be a non-empty string. Received ''", .{}).throw() catch .zero; + } + const source_str = source.toBunString(global) catch return .zero; defer source_str.deref(); - return JSC.toJSHostValue(global, doResolveWithArgs(global, specifier_str, source_str, is_esm, true)); + return JSC.toJSHostValue(global, doResolveWithArgs(global, specifier_str, source_str, is_esm, true, is_user_require_resolve)); } export fn Bun__resolveSyncWithStrings(global: *JSGlobalObject, specifier: *bun.String, source: *bun.String, is_esm: bool) JSC.JSValue { Output.scoped(.importMetaResolve, false)("source: {s}, specifier: {s}", .{ source.*, specifier.* }); - return JSC.toJSHostValue(global, doResolveWithArgs(global, specifier.*, source.*, is_esm, true)); + return JSC.toJSHostValue(global, doResolveWithArgs(global, specifier.*, source.*, is_esm, true, false)); } -export fn Bun__resolveSyncWithSource(global: *JSGlobalObject, specifier: JSValue, source: *bun.String, is_esm: bool) JSC.JSValue { +export fn Bun__resolveSyncWithSource(global: *JSGlobalObject, specifier: JSValue, source: *bun.String, is_esm: bool, is_user_require_resolve: bool) JSC.JSValue { const specifier_str = specifier.toBunString(global) catch return .zero; defer specifier_str.deref(); - return JSC.toJSHostValue(global, doResolveWithArgs(global, specifier_str, source.*, is_esm, true)); + if (specifier_str.length() == 0) { + return global.ERR_INVALID_ARG_VALUE("The argument 'id' must be a non-empty string. Received ''", .{}).throw() catch .zero; + } + return JSC.toJSHostValue(global, doResolveWithArgs(global, specifier_str, source.*, is_esm, true, is_user_require_resolve)); } extern fn dump_zone_malloc_stats() void; diff --git a/src/bun.js/api/bun/subprocess.zig b/src/bun.js/api/bun/subprocess.zig index 93d4c9d10d..3fc051a084 100644 --- a/src/bun.js/api/bun/subprocess.zig +++ b/src/bun.js/api/bun/subprocess.zig @@ -750,7 +750,6 @@ pub fn doSend(this: *Subprocess, global: *JSC.JSGlobalObject, callFrame: *JSC.Ca } }; - const zigGlobal: *JSC.ZigGlobalObject = @ptrCast(global); const ipc_data = &(this.ipc_data orelse { if (this.hasExited()) { return global.ERR_IPC_CHANNEL_CLOSED("Subprocess.send() cannot be used after the process has exited.", .{}).throw(); @@ -770,17 +769,17 @@ pub fn doSend(this: *Subprocess, global: *JSC.JSGlobalObject, callFrame: *JSC.Ca if (good) { if (callback.isFunction()) { - JSC.Bun__Process__queueNextTick1(zigGlobal, callback, .null); + JSC.Bun__Process__queueNextTick1(global, callback, .null); // we need to wait until the send is actually completed to trigger the callback } } else { const ex = global.createTypeErrorInstance("process.send() failed", .{}); ex.put(global, JSC.ZigString.static("syscall"), bun.String.static("write").toJS(global)); if (callback.isFunction()) { - JSC.Bun__Process__queueNextTick1(zigGlobal, callback, ex); + JSC.Bun__Process__queueNextTick1(global, callback, ex); } else { const fnvalue = JSC.JSFunction.create(global, "", S.impl, 1, .{}); - JSC.Bun__Process__queueNextTick1(zigGlobal, fnvalue, ex); + JSC.Bun__Process__queueNextTick1(global, fnvalue, ex); } } diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig index 8927c6c9f7..1a8d1da21f 100644 --- a/src/bun.js/api/server.zig +++ b/src/bun.js/api/server.zig @@ -62,7 +62,6 @@ const JSInternalPromise = bun.JSC.JSInternalPromise; const JSModuleLoader = bun.JSC.JSModuleLoader; const JSPromiseRejectionOperation = bun.JSC.JSPromiseRejectionOperation; const ErrorableZigString = bun.JSC.ErrorableZigString; -const ZigGlobalObject = bun.JSC.ZigGlobalObject; const VM = bun.JSC.VM; const JSFunction = bun.JSC.JSFunction; const Config = @import("../config.zig"); diff --git a/src/bun.js/bindings/BunObject.cpp b/src/bun.js/bindings/BunObject.cpp index 8b48e654b3..e619e7b6da 100644 --- a/src/bun.js/bindings/BunObject.cpp +++ b/src/bun.js/bindings/BunObject.cpp @@ -860,6 +860,9 @@ static void exportBunObject(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC: object->getOwnNonIndexPropertyNames(globalObject, propertyNames, DontEnumPropertiesMode::Exclude); RETURN_IF_EXCEPTION(scope, void()); + exportNames.append(vm.propertyNames->defaultKeyword); + exportValues.append(object); + for (const auto& propertyName : propertyNames) { exportNames.append(propertyName); auto catchScope = DECLARE_CATCH_SCOPE(vm); @@ -873,9 +876,6 @@ static void exportBunObject(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC: } exportValues.append(value); } - - exportNames.append(vm.propertyNames->defaultKeyword); - exportValues.append(object); } } diff --git a/src/bun.js/bindings/BunPlugin.cpp b/src/bun.js/bindings/BunPlugin.cpp index f39bddf3b9..1124e61958 100644 --- a/src/bun.js/bindings/BunPlugin.cpp +++ b/src/bun.js/bindings/BunPlugin.cpp @@ -31,6 +31,8 @@ #include "CommonJSModuleRecord.h" #include "isBuiltinModule.h" +#include "ImportMetaObject.h" + namespace Zig { extern "C" void Bun__onDidAppendPlugin(void* bunVM, JSGlobalObject* globalObject); @@ -481,7 +483,6 @@ JSObject* JSModuleMock::executeOnce(JSC::JSGlobalObject* lexicalGlobalObject) return object; } -extern "C" JSC::EncodedJSValue Bun__resolveSyncWithSource(JSC::JSGlobalObject* global, JSC::EncodedJSValue specifier, BunString* from, bool is_esm); BUN_DECLARE_HOST_FUNCTION(JSMock__jsModuleMock); extern "C" JSC_DEFINE_HOST_FUNCTION(JSMock__jsModuleMock, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callframe)) { @@ -500,8 +501,8 @@ extern "C" JSC_DEFINE_HOST_FUNCTION(JSMock__jsModuleMock, (JSC::JSGlobalObject * JSC::JSString* specifierString = callframe->argument(0).toString(globalObject); RETURN_IF_EXCEPTION(scope, {}); - WTF::String specifier = specifierString->value(globalObject); + RETURN_IF_EXCEPTION(scope, {}); if (specifier.isEmpty()) { scope.throwException(lexicalGlobalObject, JSC::createTypeError(lexicalGlobalObject, "mock(module, fn) requires a module and function"_s)); @@ -529,7 +530,7 @@ extern "C" JSC_DEFINE_HOST_FUNCTION(JSMock__jsModuleMock, (JSC::JSGlobalObject * auto fromString = url.fileSystemPath(); BunString from = Bun::toString(fromString); auto catchScope = DECLARE_CATCH_SCOPE(vm); - auto result = JSValue::decode(Bun__resolveSyncWithSource(globalObject, JSValue::encode(specifierString), &from, true)); + auto result = JSValue::decode(Bun__resolveSyncWithSource(globalObject, JSValue::encode(specifierString), &from, true, false)); if (catchScope.exception()) { catchScope.clearException(); } diff --git a/src/bun.js/bindings/BunProcess.cpp b/src/bun.js/bindings/BunProcess.cpp index f78dc8d2bf..4713202a83 100644 --- a/src/bun.js/bindings/BunProcess.cpp +++ b/src/bun.js/bindings/BunProcess.cpp @@ -1,3 +1,4 @@ +#include "ModuleLoader.h" #include "napi.h" #include "BunProcess.h" @@ -465,9 +466,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionDlopen, (JSC::JSGlobalObject * globalOb while (charCount > 0 && (messageBuffer[charCount - 1] == L'\r' || messageBuffer[charCount - 1] == L'\n' || messageBuffer[charCount - 1] == L' ')) charCount--; - // Create a span of the wide characters - auto wideCharSpan = std::span(reinterpret_cast(messageBuffer), charCount); - errorBuilder.append(WTF::StringView(wideCharSpan)); + errorBuilder.append(WTF::StringView(messageBuffer, charCount, false)); } else { errorBuilder.append("error code "_s); errorBuilder.append(WTF::String::number(errorId)); @@ -2641,12 +2640,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_availableMemory, (JSGlobalObject * globalObject inline JSValue processBindingUtil(Zig::GlobalObject* globalObject, JSC::VM& vm) { - auto& builtinNames = WebCore::builtinNames(vm); - auto fn = globalObject->getDirect(vm, builtinNames.requireNativeModulePrivateName()); - auto callData = JSC::getCallData(fn); - JSC::MarkedArgumentBuffer args; - args.append(jsString(vm, String("util/types"_s))); - return JSC::profiledCall(globalObject, ProfilingReason::API, fn, callData, globalObject, args); + return globalObject->internalModuleRegistry()->requireId(globalObject, vm, InternalModuleRegistry::NodeUtilTypes); } inline JSValue processBindingConfig(Zig::GlobalObject* globalObject, JSC::VM& vm) @@ -3303,7 +3297,7 @@ JSC_DEFINE_CUSTOM_GETTER(processTitle, (JSC::JSGlobalObject * globalObject, JSC: #if !OS(WINDOWS) ZigString str; Bun__Process__getTitle(globalObject, &str); - return JSValue::encode(Zig::toJSStringValue(str, globalObject)); + return JSValue::encode(Zig::toJSString(str, globalObject)); #else auto& vm = JSC::getVM(globalObject); char title[1024]; @@ -3452,6 +3446,29 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionKill, (JSC::JSGlobalObject * globalObje return JSValue::encode(jsBoolean(true)); } +JSC_DEFINE_HOST_FUNCTION(Process_functionLoadBuiltinModule, (JSGlobalObject * globalObject, CallFrame* callFrame)) +{ + auto* zigGlobalObject = jsCast(globalObject); + VM& vm = zigGlobalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + JSValue id = callFrame->argument(0); + if (!id.isString()) { + return Bun::ERR::INVALID_ARG_TYPE(scope, globalObject, "moduleName"_s, "string"_s, id); + } + + String idWtfStr = id.toWTFString(zigGlobalObject); + RETURN_IF_EXCEPTION(scope, {}); + BunString idStr = Bun::toString(idWtfStr); + + JSValue fetchResult = Bun::resolveAndFetchBuiltinModule(zigGlobalObject, &idStr); + if (fetchResult) { + RELEASE_AND_RETURN(scope, JSC::JSValue::encode(fetchResult)); + } + + RELEASE_AND_RETURN(scope, JSValue::encode(jsUndefined())); +} + extern "C" void Process__emitMessageEvent(Zig::GlobalObject* global, EncodedJSValue value) { auto* process = static_cast(global->processObject()); @@ -3557,6 +3574,7 @@ extern "C" void Process__emitErrorEvent(Zig::GlobalObject* global, EncodedJSValu _stopProfilerIdleNotifier Process_stubEmptyFunction Function 0 _tickCallback Process_stubEmptyFunction Function 0 _kill Process_functionReallyKill Function 2 + getBuiltinModule Process_functionLoadBuiltinModule Function 1 #if !OS(WINDOWS) getegid Process_functiongetegid Function 0 diff --git a/src/bun.js/bindings/BunString.cpp b/src/bun.js/bindings/BunString.cpp index 9afa7aca97..6818f955e8 100644 --- a/src/bun.js/bindings/BunString.cpp +++ b/src/bun.js/bindings/BunString.cpp @@ -152,24 +152,24 @@ extern "C" int64_t BunString__toInt32(BunString* bunString) namespace Bun { -JSC::JSValue toJS(JSC::JSGlobalObject* globalObject, BunString bunString) +JSC::JSString* toJS(JSC::JSGlobalObject* globalObject, BunString bunString) { if (bunString.tag == BunStringTag::Empty || bunString.tag == BunStringTag::Dead) { - return JSValue(JSC::jsEmptyString(globalObject->vm())); + return JSC::jsEmptyString(globalObject->vm()); } if (bunString.tag == BunStringTag::WTFStringImpl) { #if ASSERT_ENABLED ASSERT(bunString.impl.wtf->hasAtLeastOneRef() && !bunString.impl.wtf->isEmpty()); #endif - return JSValue(jsString(globalObject->vm(), String(bunString.impl.wtf))); + return JSC::jsString(globalObject->vm(), String(bunString.impl.wtf)); } if (bunString.tag == BunStringTag::StaticZigString) { - return JSValue(jsString(globalObject->vm(), Zig::toStringStatic(bunString.impl.zig))); + return JSC::jsString(globalObject->vm(), Zig::toStringStatic(bunString.impl.zig)); } - return JSValue(Zig::toJSStringGC(bunString.impl.zig, globalObject)); + return Zig::toJSStringGC(bunString.impl.zig, globalObject); } BunString toString(const char* bytes, size_t length) diff --git a/src/bun.js/bindings/CommonJSModuleRecord.cpp b/src/bun.js/bindings/CommonJSModuleRecord.cpp index 641971f38c..91489a844f 100644 --- a/src/bun.js/bindings/CommonJSModuleRecord.cpp +++ b/src/bun.js/bindings/CommonJSModuleRecord.cpp @@ -83,6 +83,7 @@ namespace Bun { using namespace JSC; JSC_DECLARE_HOST_FUNCTION(jsFunctionRequireCommonJS); +JSC_DECLARE_HOST_FUNCTION(jsFunctionRequireNativeModule); static bool canPerformFastEnumeration(Structure* s) { @@ -104,15 +105,14 @@ static bool canPerformFastEnumeration(Structure* s) extern "C" bool Bun__VM__specifierIsEvalEntryPoint(void*, EncodedJSValue); extern "C" void Bun__VM__setEntryPointEvalResultCJS(void*, EncodedJSValue); -static bool evaluateCommonJSModuleOnce(JSC::VM& vm, Zig::GlobalObject* globalObject, JSCommonJSModule* moduleObject, JSString* dirname, JSValue filename, WTF::NakedPtr& exception) +static bool evaluateCommonJSModuleOnce(JSC::VM& vm, Zig::GlobalObject* globalObject, JSCommonJSModule* moduleObject, JSString* dirname, JSValue filename) { + auto scope = DECLARE_THROW_SCOPE(vm); SourceCode code = std::move(moduleObject->sourceCode); // If an exception occurred somewhere else, we might have cleared the source code. if (UNLIKELY(code.isNull())) { - auto throwScope = DECLARE_THROW_SCOPE(vm); - throwException(globalObject, throwScope, createError(globalObject, "Failed to evaluate module"_s)); - exception = throwScope.exception(); + throwException(globalObject, scope, createError(globalObject, "Failed to evaluate module"_s)); return false; } @@ -122,7 +122,7 @@ static bool evaluateCommonJSModuleOnce(JSC::VM& vm, Zig::GlobalObject* globalObj resolveFunction = JSC::JSBoundFunction::create(vm, globalObject, globalObject->requireResolveFunctionUnbound(), - moduleObject->id(), + moduleObject->filename(), ArgList(), 1, globalObject->commonStrings().resolveString(globalObject)); requireFunction = JSC::JSBoundFunction::create(vm, globalObject, @@ -144,40 +144,45 @@ static bool evaluateCommonJSModuleOnce(JSC::VM& vm, Zig::GlobalObject* globalObj globalObject->putDirect(vm, Identifier::fromString(vm, "module"_s), moduleObject, 0); globalObject->putDirect(vm, Identifier::fromString(vm, "__filename"_s), filename, 0); globalObject->putDirect(vm, Identifier::fromString(vm, "__dirname"_s), dirname, 0); + scope.assertNoException(); - JSValue result = JSC::evaluate(globalObject, code, jsUndefined(), exception); - - if (UNLIKELY(exception.get() || result.isEmpty())) { + WTF::NakedPtr returnedException; + JSValue result = JSC::evaluate(globalObject, code, jsUndefined(), returnedException); + if (UNLIKELY(returnedException)) { + scope.throwException(globalObject, returnedException.get()); return false; } + ASSERT(!scope.exception()); + ASSERT(result); Bun__VM__setEntryPointEvalResultCJS(globalObject->bunVM(), JSValue::encode(result)); - return true; + RELEASE_AND_RETURN(scope, true); } - // This will return 0 if there was a syntax error or an allocation failure - JSValue fnValue = JSC::evaluate(globalObject, code, jsUndefined(), exception); - - if (UNLIKELY(exception.get() || fnValue.isEmpty())) { - return false; + WTF::NakedPtr returnedException; + JSValue fnValue = JSC::evaluate(globalObject, code, jsUndefined(), returnedException); + if (UNLIKELY(returnedException)) { + scope.throwException(globalObject, returnedException.get()); + RELEASE_AND_RETURN(scope, false); } + ASSERT(!scope.exception()); + ASSERT(fnValue); JSObject* fn = fnValue.getObject(); - if (UNLIKELY(!fn)) { - exception = Exception::create(vm, createTypeError(globalObject, "Expected CommonJS module to have a function wrapper. If you weren't messing around with Bun's internals, this is a bug in Bun"_s)); - return false; + scope.throwException(globalObject, createTypeError(globalObject, "Expected CommonJS module to have a function wrapper. If you weren't messing around with Bun's internals, this is a bug in Bun"_s)); + RELEASE_AND_RETURN(scope, false); } JSC::CallData callData = JSC::getCallData(fn); - if (UNLIKELY(callData.type == CallData::Type::None)) { - exception = Exception::create(vm, createTypeError(globalObject, "Expected CommonJS module to have a function wrapper. If you weren't messing around with Bun's internals, this is a bug in Bun"_s)); - return false; + scope.throwException(globalObject, createTypeError(globalObject, "Expected CommonJS module to have a function wrapper. If you weren't messing around with Bun's internals, this is a bug in Bun"_s)); + RELEASE_AND_RETURN(scope, false); } initializeModuleObject(); + RETURN_IF_EXCEPTION(scope, false); MarkedArgumentBuffer args; args.append(moduleObject->exportsObject()); // exports @@ -200,13 +205,18 @@ static bool evaluateCommonJSModuleOnce(JSC::VM& vm, Zig::GlobalObject* globalObj // // fn(exports, require, module, __filename, __dirname) { /* code */ }(exports, require, module, __filename, __dirname) // - JSC::profiledCall(globalObject, ProfilingReason::API, fn, callData, moduleObject, args, exception); - - return exception.get() == nullptr; + JSC::profiledCall(globalObject, ProfilingReason::API, fn, callData, moduleObject, args, returnedException); + if (UNLIKELY(returnedException)) { + scope.throwException(globalObject, returnedException.get()); + return false; + } + ASSERT(!scope.exception()); + RELEASE_AND_RETURN(scope, true); } -bool JSCommonJSModule::load(JSC::VM& vm, Zig::GlobalObject* globalObject, WTF::NakedPtr& exception) +bool JSCommonJSModule::load(JSC::VM& vm, Zig::GlobalObject* globalObject) { + auto scope = DECLARE_THROW_SCOPE(vm); if (this->hasEvaluated || this->sourceCode.isNull()) { return true; } @@ -216,39 +226,43 @@ bool JSCommonJSModule::load(JSC::VM& vm, Zig::GlobalObject* globalObject, WTF::N jsCast(globalObject), this, this->m_dirname.get(), - this->m_filename.get(), - exception); + this->m_filename.get()); + + if (auto exception = scope.exception()) { + scope.clearException(); - if (exception.get()) { // On error, remove the module from the require map/ // so that it can be re-evaluated on the next require. - globalObject->requireMap()->remove(globalObject, this->id()); + bool wasRemoved = globalObject->requireMap()->remove(globalObject, this->filename()); + ASSERT(wasRemoved); + scope.throwException(globalObject, exception); return false; } return true; } -JSC_DEFINE_HOST_FUNCTION(jsFunctionLoadModule, (JSGlobalObject * lexicalGlobalObject, CallFrame* callframe)) +JSC_DEFINE_HOST_FUNCTION(jsFunctionEvaluateCommonJSModule, (JSGlobalObject * lexicalGlobalObject, CallFrame* callframe)) { auto& vm = JSC::getVM(lexicalGlobalObject); auto* globalObject = jsCast(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); - JSCommonJSModule* moduleObject = jsDynamicCast(callframe->argument(0)); - if (!moduleObject) { - RELEASE_AND_RETURN(throwScope, JSValue::encode(jsBoolean(true))); + // These casts are jsDynamicCast because require.cache pollution + invalid + // this calls can put arbitrary values here instead of JSCommonJSModule* + ASSERT(callframe->argumentCount() == 2); + JSCommonJSModule* moduleObject = jsDynamicCast(callframe->uncheckedArgument(0)); + JSCommonJSModule* referrer = jsDynamicCast(callframe->uncheckedArgument(1)); + if (UNLIKELY(!moduleObject)) { + RELEASE_AND_RETURN(throwScope, JSValue::encode(jsUndefined())); } - WTF::NakedPtr exception; + UNUSED_PARAM(referrer); - if (!moduleObject->load(vm, globalObject, exception)) { - throwException(globalObject, throwScope, exception.get()); - exception.clear(); - return {}; - } + moduleObject->load(vm, globalObject); + RETURN_IF_EXCEPTION(throwScope, {}); - RELEASE_AND_RETURN(throwScope, JSValue::encode(jsBoolean(true))); + RELEASE_AND_RETURN(throwScope, JSValue::encode(jsUndefined())); } JSC_DEFINE_HOST_FUNCTION(requireResolvePathsFunction, (JSGlobalObject * globalObject, CallFrame* callframe)) @@ -397,9 +411,8 @@ JSC_DEFINE_CUSTOM_GETTER(getterParent, (JSC::JSGlobalObject * globalObject, JSC: // dont need `module.parent` and creating commonjs module records is done a ton. auto idValue = thisObject->m_id.get(); if (idValue) { - auto id = idValue->value(globalObject); - auto idStr = Bun::toString(id); - if (Bun__isBunMain(globalObject, &idStr)) { + auto id = idValue->view(globalObject); + if (id == "."_s) { thisObject->m_overriddenParent.set(globalObject->vm(), thisObject, jsNull()); return JSValue::encode(jsNull()); } @@ -537,10 +550,19 @@ JSC_DEFINE_HOST_FUNCTION(functionCommonJSModuleRecord_compile, (JSGlobalObject * String filenameString = filenameValue.toWTFString(globalObject); RETURN_IF_EXCEPTION(throwScope, {}); - String wrappedString = makeString( - "(function(exports,require,module,__filename,__dirname){"_s, - sourceString, - "\n})"_s); + String wrappedString; + auto* zigGlobalObject = jsCast(globalObject); + if (UNLIKELY(zigGlobalObject->hasOverriddenModuleWrapper)) { + wrappedString = makeString( + zigGlobalObject->m_moduleWrapperStart, + sourceString, + zigGlobalObject->m_moduleWrapperEnd); + } else { + wrappedString = makeString( + "(function(exports,require,module,__filename,__dirname){"_s, + sourceString, + "\n})"_s); + } moduleObject->sourceCode = makeSource( WTFMove(wrappedString), @@ -566,14 +588,8 @@ JSC_DEFINE_HOST_FUNCTION(functionCommonJSModuleRecord_compile, (JSGlobalObject * jsCast(globalObject), moduleObject, jsString(vm, dirnameString), - jsString(vm, filenameString), - exception); - - if (exception) { - throwException(globalObject, throwScope, exception.get()); - exception.clear(); - return {}; - } + jsString(vm, filenameString)); + RETURN_IF_EXCEPTION(throwScope, {}); return JSValue::encode(jsUndefined()); } @@ -640,6 +656,12 @@ public: clientData(vm)->builtinNames().requirePrivateName(), 2, jsFunctionRequireCommonJS, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete); + this->putDirectNativeFunction( + vm, + globalObject, + clientData(vm)->builtinNames().requireNativeModulePrivateName(), + 0, + jsFunctionRequireNativeModule, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete); } }; @@ -769,25 +791,6 @@ JSCommonJSModule::~JSCommonJSModule() { } -bool JSCommonJSModule::evaluate( - Zig::GlobalObject* globalObject, - const WTF::String& key, - const SyntheticSourceProvider::SyntheticSourceGenerator& generator) -{ - Vector propertyNames; - JSC::MarkedArgumentBuffer arguments; - auto& vm = JSC::getVM(globalObject); - auto throwScope = DECLARE_THROW_SCOPE(vm); - generator(globalObject, JSC::Identifier::fromString(vm, key), propertyNames, arguments); - RETURN_IF_EXCEPTION(throwScope, false); - // This goes off of the assumption that you only call this `evaluate` using a generator that explicitly - // assigns the `default` export first. - JSValue defaultValue = arguments.at(0); - this->putDirect(vm, WebCore::clientData(vm)->builtinNames().exportsPublicName(), defaultValue, 0); - this->hasEvaluated = true; - RELEASE_AND_RETURN(throwScope, true); -} - void populateESMExports( JSC::JSGlobalObject* globalObject, JSValue result, @@ -798,7 +801,7 @@ void populateESMExports( auto& vm = JSC::getVM(globalObject); const Identifier& esModuleMarker = vm.propertyNames->__esModule; - // Bun's intepretation of the "__esModule" annotation: + // Bun's interpretation of the "__esModule" annotation: // // - If a "default" export does not exist OR the __esModule annotation is not present, then we // set the default export to the exports object @@ -994,16 +997,6 @@ void JSCommonJSModule::setExportsObject(JSC::JSValue exportsObject) this->putDirect(vm(), JSC::PropertyName(clientData(vm())->builtinNames().exportsPublicName()), exportsObject, 0); } -JSValue JSCommonJSModule::exportsObject() -{ - return this->get(globalObject(), JSC::PropertyName(clientData(vm())->builtinNames().exportsPublicName())); -} - -JSValue JSCommonJSModule::id() -{ - return m_id.get(); -} - Structure* createCommonJSModuleStructure( Zig::GlobalObject* globalObject) { @@ -1062,10 +1055,10 @@ void JSCommonJSModule::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) } if (thisObject->m_overriddenParent) { - JSValue overridenParent = thisObject->m_overriddenParent.get(); - if (overridenParent.isCell()) { - const Identifier overridenParentIdentifier = Identifier::fromString(vm, "parent"_s); - analyzer.analyzePropertyNameEdge(cell, overridenParent.asCell(), overridenParentIdentifier.impl()); + JSValue overriddenParent = thisObject->m_overriddenParent.get(); + if (overriddenParent.isCell()) { + const Identifier overriddenParentIdentifier = Identifier::fromString(vm, "parent"_s); + analyzer.analyzePropertyNameEdge(cell, overriddenParent.asCell(), overriddenParentIdentifier.impl()); } } } @@ -1074,36 +1067,42 @@ const JSC::ClassInfo JSCommonJSModule::s_info = { "Module"_s, &Base::s_info, nul const JSC::ClassInfo RequireResolveFunctionPrototype::s_info = { "resolve"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(RequireResolveFunctionPrototype) }; const JSC::ClassInfo RequireFunctionPrototype::s_info = { "require"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(RequireFunctionPrototype) }; +// JSCommonJSModule.$require(resolvedId, newModule, userArgumentCount, userOptions) JSC_DEFINE_HOST_FUNCTION(jsFunctionRequireCommonJS, (JSGlobalObject * lexicalGlobalObject, CallFrame* callframe)) { auto* globalObject = jsCast(lexicalGlobalObject); auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); - - JSCommonJSModule* thisObject = jsDynamicCast(callframe->thisValue()); - if (!thisObject) + ASSERT(callframe->argumentCount() == 4); + // If overriddenRequire is called with invalid this, execution could potentially reach here. + JSCommonJSModule* referrerModule = jsDynamicCast(callframe->thisValue()); + if (!referrerModule) return throwVMTypeError(globalObject, throwScope); - - JSValue specifierValue = callframe->argument(0); + JSValue specifierValue = callframe->uncheckedArgument(0); + // If Module._resolveFilename is overridden, this could cause this to be a non-string WTF::String specifier = specifierValue.toWTFString(globalObject); RETURN_IF_EXCEPTION(throwScope, {}); - - WTF::String referrer = thisObject->id().toWTFString(globalObject); + // If this.filename is overridden, this could cause this to be a non-string + WTF::String referrer = referrerModule->filename().toWTFString(globalObject); RETURN_IF_EXCEPTION(throwScope, {}); + // This is always a new JSCommonJSModule object; cast cannot fail. + JSCommonJSModule* child = jsCast(callframe->uncheckedArgument(1)); + BunString specifierStr = Bun::toString(specifier); BunString referrerStr = Bun::toString(referrer); BunString typeAttributeStr = { BunStringTag::Dead }; String typeAttribute = String(); // We need to be able to wire in the "type" import attribute from bundled code.. - // so we do it via CommonJS require(). - int32_t previousArgumentCount = callframe->argument(2).asInt32(); + // So we do it via CommonJS require(). + // $argumentCount() always returns a Int32 JSValue + int32_t userArgumentCount = callframe->argument(2).asInt32(); // If they called require(id), skip the check for the type attribute - if (UNLIKELY(previousArgumentCount == 2)) { - JSValue val = callframe->argument(3); - if (val.isObject()) { - JSObject* obj = val.getObject(); + if (UNLIKELY(userArgumentCount >= 2)) { + JSValue options = callframe->uncheckedArgument(3); + if (options.isObject()) { + JSObject* obj = options.getObject(); // This getter is expensive and rare. if (auto typeValue = obj->getIfPropertyExists(globalObject, vm.propertyNames->type)) { if (typeValue.isString()) { @@ -1116,9 +1115,10 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionRequireCommonJS, (JSGlobalObject * lexicalGlo } } + // Load the module JSValue fetchResult = Bun::fetchCommonJSModule( globalObject, - jsCast(callframe->argument(1)), + child, specifierValue, &specifierStr, &referrerStr, @@ -1126,9 +1126,44 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionRequireCommonJS, (JSGlobalObject * lexicalGlo ? nullptr : &typeAttributeStr); + if (auto exception = throwScope.exception()) { + throwScope.clearException(); + + // On error, remove the module from the require map/ + // so that it can be re-evaluated on the next require. + bool wasRemoved = globalObject->requireMap()->remove(globalObject, specifierValue); + ASSERT(wasRemoved); + + throwScope.throwException(globalObject, exception); + RELEASE_AND_RETURN(throwScope, {}); + } + RELEASE_AND_RETURN(throwScope, JSValue::encode(fetchResult)); } +JSC_DEFINE_HOST_FUNCTION(jsFunctionRequireNativeModule, (JSGlobalObject * lexicalGlobalObject, CallFrame* callframe)) +{ + auto* globalObject = jsCast(lexicalGlobalObject); + auto& vm = JSC::getVM(globalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + + JSCommonJSModule* thisObject = jsDynamicCast(callframe->thisValue()); + if (!thisObject) + return throwVMTypeError(globalObject, throwScope); + + JSValue specifierValue = callframe->argument(0); + WTF::String specifier = specifierValue.toWTFString(globalObject); + RETURN_IF_EXCEPTION(throwScope, {}); + ErrorableResolvedSource res; + BunString specifierStr = Bun::toString(specifier); + if (auto result = fetchBuiltinModuleWithoutResolution(globalObject, &specifierStr, &res)) { + if (res.success) + return JSC::JSValue::encode(result); + } + ASSERT_WITH_MESSAGE(false, "Failed to fetch builtin module %s", specifier.utf8().data()); + return throwVMError(globalObject, throwScope, "Failed to fetch builtin module"_s); +} + void RequireResolveFunctionPrototype::finishCreation(JSC::VM& vm) { Base::finishCreation(vm); @@ -1138,48 +1173,54 @@ void RequireResolveFunctionPrototype::finishCreation(JSC::VM& vm) JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); } -bool JSCommonJSModule::evaluate( +void JSCommonJSModule::evaluate( Zig::GlobalObject* globalObject, const WTF::String& key, ResolvedSource& source, bool isBuiltIn) { auto& vm = JSC::getVM(globalObject); + + if (UNLIKELY(globalObject->hasOverriddenModuleWrapper)) { + auto string = source.source_code.toWTFString(BunString::ZeroCopy); + auto trimStart = string.find('\n'); + if (trimStart != WTF::notFound) { + if (source.needsDeref && !isBuiltIn) { + source.needsDeref = false; + source.source_code.deref(); + } + auto wrapperStart = globalObject->m_moduleWrapperStart; + auto wrapperEnd = globalObject->m_moduleWrapperEnd; + source.source_code = Bun::toStringRef(makeString( + wrapperStart, + string.substring(trimStart, string.length() - trimStart - 4), + wrapperEnd)); + source.needsDeref = true; + } + } + auto sourceProvider = Zig::SourceProvider::create(jsCast(globalObject), source, JSC::SourceProviderSourceType::Program, isBuiltIn); this->ignoreESModuleAnnotation = source.tag == ResolvedSourceTagPackageJSONTypeModule; if (this->hasEvaluated) - return true; + return; this->sourceCode = JSC::SourceCode(WTFMove(sourceProvider)); - WTF::NakedPtr exception; - evaluateCommonJSModuleOnce(vm, globalObject, this, this->m_dirname.get(), this->m_filename.get(), exception); + evaluateCommonJSModuleOnce(vm, globalObject, this, this->m_dirname.get(), this->m_filename.get()); - if (exception.get()) { - // On error, remove the module from the require map/ - // so that it can be re-evaluated on the next require. - globalObject->requireMap()->remove(globalObject, this->id()); - - auto throwScope = DECLARE_THROW_SCOPE(vm); - throwException(globalObject, throwScope, exception.get()); - exception.clear(); - - return false; - } - - return true; + return; } std::optional createCommonJSModule( Zig::GlobalObject* globalObject, - JSValue specifierValue, + JSString* requireMapKey, ResolvedSource& source, bool isBuiltIn) { JSCommonJSModule* moduleObject = nullptr; WTF::String sourceURL = source.source_url.toWTFString(); - JSValue entry = globalObject->requireMap()->get(globalObject, specifierValue); + JSValue entry = globalObject->requireMap()->get(globalObject, requireMapKey); bool ignoreESModuleAnnotation = source.tag == ResolvedSourceTagPackageJSONTypeModule; SourceOrigin sourceOrigin; @@ -1188,9 +1229,8 @@ std::optional createCommonJSModule( } if (!moduleObject) { - auto& vm = JSC::getVM(globalObject); - auto* requireMapKey = specifierValue.toString(globalObject); - auto index = sourceURL.reverseFind(PLATFORM_SEP, sourceURL.length()); + VM& vm = JSC::getVM(globalObject); + size_t index = sourceURL.reverseFind(PLATFORM_SEP, sourceURL.length()); JSString* dirname; JSString* filename = requireMapKey; if (index != WTF::notFound) { @@ -1198,6 +1238,19 @@ std::optional createCommonJSModule( } else { dirname = jsEmptyString(vm); } + auto requireMap = globalObject->requireMap(); + if (requireMap->size() == 0) { + requireMapKey = JSC::jsString(vm, WTF::String("."_s)); + } + + if (UNLIKELY(globalObject->hasOverriddenModuleWrapper)) { + auto concat = makeString( + globalObject->m_moduleWrapperStart, + source.source_code.toWTFString(BunString::ZeroCopy), + globalObject->m_moduleWrapperEnd); + source.source_code.deref(); + source.source_code = Bun::toStringRef(concat); + } auto sourceProvider = Zig::SourceProvider::create(jsCast(globalObject), source, JSC::SourceProviderSourceType::Program, isBuiltIn); sourceOrigin = sourceProvider->sourceOrigin(); @@ -1210,7 +1263,7 @@ std::optional createCommonJSModule( WebCore::clientData(vm)->builtinNames().exportsPublicName(), JSC::constructEmptyObject(globalObject, globalObject->objectPrototype()), 0); - globalObject->requireMap()->set(globalObject, requireMapKey, moduleObject); + requireMap->set(globalObject, filename, moduleObject); } else { sourceOrigin = Zig::toSourceOrigin(sourceURL, isBuiltIn); } @@ -1232,21 +1285,21 @@ std::optional createCommonJSModule( if (entry) { if (auto* moduleObject = jsDynamicCast(entry)) { if (!moduleObject->hasEvaluated) { - WTF::NakedPtr exception; - if (!evaluateCommonJSModuleOnce( - vm, - globalObject, - moduleObject, - moduleObject->m_dirname.get(), - moduleObject->m_filename.get(), exception)) { + auto scope = DECLARE_THROW_SCOPE(vm); + evaluateCommonJSModuleOnce( + vm, + globalObject, + moduleObject, + moduleObject->m_dirname.get(), + moduleObject->m_filename.get()); + if (auto exception = scope.exception()) { + scope.clearException(); // On error, remove the module from the require map // so that it can be re-evaluated on the next require. - globalObject->requireMap()->remove(globalObject, moduleObject->id()); + globalObject->requireMap()->remove(globalObject, moduleObject->filename()); - auto scope = DECLARE_THROW_SCOPE(vm); - throwException(globalObject, scope, exception.get()); - exception.clear(); + scope.throwException(globalObject, exception); return; } } @@ -1290,7 +1343,7 @@ JSObject* JSCommonJSModule::createBoundRequireFunction(VM& vm, JSGlobalObject* l JSFunction* resolveFunction = JSC::JSBoundFunction::create(vm, globalObject, globalObject->requireResolveFunctionUnbound(), - moduleObject, + moduleObject->filename(), ArgList(), 1, globalObject->commonStrings().resolveString(globalObject)); requireFunction->putDirect(vm, vm.propertyNames->resolve, resolveFunction, 0); diff --git a/src/bun.js/bindings/CommonJSModuleRecord.h b/src/bun.js/bindings/CommonJSModuleRecord.h index 658b58ef24..a7a1400fff 100644 --- a/src/bun.js/bindings/CommonJSModuleRecord.h +++ b/src/bun.js/bindings/CommonJSModuleRecord.h @@ -22,7 +22,7 @@ namespace Bun { using namespace JSC; JSC_DECLARE_HOST_FUNCTION(jsFunctionCreateCommonJSModule); -JSC_DECLARE_HOST_FUNCTION(jsFunctionLoadModule); +JSC_DECLARE_HOST_FUNCTION(jsFunctionEvaluateCommonJSModule); void populateESMExports( JSC::JSGlobalObject* globalObject, @@ -36,9 +36,13 @@ public: using Base = JSC::JSDestructibleObject; static constexpr unsigned StructureFlags = Base::StructureFlags; + // `module.id` Initialized eagerly; can be overridden. mutable JSC::WriteBarrier m_id; + // Initialized eagerly; can be overridden. mutable JSC::WriteBarrier m_filename; + // Initialized eagerly; can be overridden. mutable JSC::WriteBarrier m_dirname; + // Initialized lazily; can be overridden. mutable JSC::WriteBarrier m_paths; // Visited by the GC. When the module is assigned a non-JSCommonJSModule @@ -47,7 +51,6 @@ public: // module.parent = parent; // mutable JSC::WriteBarrier m_overriddenParent; - // Not visited by the GC. // When the module is assigned a JSCommonJSModule parent, it is assigned to this field. // This is the normal state. @@ -71,13 +74,11 @@ public: static JSC::Structure* createStructure(JSC::JSGlobalObject* globalObject); - bool evaluate(Zig::GlobalObject* globalObject, const WTF::String& sourceURL, ResolvedSource& resolvedSource, bool isBuiltIn); - inline bool evaluate(Zig::GlobalObject* globalObject, const WTF::String& sourceURL, ResolvedSource& resolvedSource) + void evaluate(Zig::GlobalObject* globalObject, const WTF::String& sourceURL, ResolvedSource& resolvedSource, bool isBuiltIn); + inline void evaluate(Zig::GlobalObject* globalObject, const WTF::String& sourceURL, ResolvedSource& resolvedSource) { return evaluate(globalObject, sourceURL, resolvedSource, false); } - bool evaluate(Zig::GlobalObject* globalObject, const WTF::String& key, const SyntheticSourceProvider::SyntheticSourceGenerator& generator); - bool evaluate(Zig::GlobalObject* globalObject, const WTF::String& key, const JSC::SourceCode& sourceCode); static JSCommonJSModule* create(JSC::VM& vm, JSC::Structure* structure, JSC::JSString* id, @@ -106,11 +107,15 @@ public: Vector& exportNames, JSC::MarkedArgumentBuffer& exportValues); - JSValue exportsObject(); + JSValue exportsObject() + { + return this->get(globalObject(), JSC::PropertyName(WebCore::clientData(vm())->builtinNames().exportsPublicName())); + } void setExportsObject(JSC::JSValue exportsObject); - JSValue id(); + JSValue idOrDot() { return m_id.get(); } + JSValue filename() { return m_filename.get(); } - bool load(JSC::VM& vm, Zig::GlobalObject* globalObject, WTF::NakedPtr&); + bool load(JSC::VM& vm, Zig::GlobalObject* globalObject); DECLARE_INFO; DECLARE_VISIT_CHILDREN; @@ -143,13 +148,13 @@ JSC::Structure* createCommonJSModuleStructure( std::optional createCommonJSModule( Zig::GlobalObject* globalObject, - JSC::JSValue specifierValue, + JSC::JSString* specifierValue, ResolvedSource& source, bool isBuiltIn); inline std::optional createCommonJSModule( Zig::GlobalObject* globalObject, - JSC::JSValue specifierValue, + JSC::JSString* specifierValue, ResolvedSource& source) { return createCommonJSModule(globalObject, specifierValue, source, false); diff --git a/src/bun.js/bindings/ExposeNodeModuleGlobals.cpp b/src/bun.js/bindings/ExposeNodeModuleGlobals.cpp index 6e51689579..95a24b19fe 100644 --- a/src/bun.js/bindings/ExposeNodeModuleGlobals.cpp +++ b/src/bun.js/bindings/ExposeNodeModuleGlobals.cpp @@ -1,4 +1,5 @@ // clang-format off +#include "ModuleLoader.h" #include "root.h" #include @@ -47,8 +48,10 @@ v(sqlite, Bun::InternalModuleRegistry::BunSqlite) \ v(worker_threads, Bun::InternalModuleRegistry::NodeWorkerThreads) \ v(zlib, Bun::InternalModuleRegistry::NodeZlib) \ - - + v(constants, Bun::InternalModuleRegistry::NodeConstants) \ + v(string_decoder, Bun::InternalModuleRegistry::NodeStringDecoder) \ + v(buffer, Bun::InternalModuleRegistry::NodeBuffer) \ + v(jsc, Bun::InternalModuleRegistry::BunJSC) \ namespace ExposeNodeModuleGlobalGetters { @@ -62,25 +65,6 @@ namespace ExposeNodeModuleGlobalGetters { FOREACH_EXPOSED_BUILTIN_IMR(DECL_GETTER) #undef DECL_GETTER - -JSC_DEFINE_CUSTOM_GETTER(jsCustomGetterGetNativeModule, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName propertyName)) -{ - Zig::GlobalObject* globalObject = defaultGlobalObject(lexicalGlobalObject); - JSC::VM& vm = globalObject->vm(); - - JSC::JSValue key = JSC::identifierToJSValue(vm, propertyName == "jsc"_s ? JSC::Identifier::fromString(vm, "bun:jsc"_s) : JSC::Identifier::fromUid(vm, propertyName.uid())); - JSC::JSValue result = globalObject->requireMap()->get(globalObject, key); - if (!result || result.isUndefinedOrNull()) { - auto& builtinNames = WebCore::builtinNames(vm); - JSC::JSFunction* function = jsCast(globalObject->getDirect(vm, builtinNames.requireNativeModulePrivateName())); - JSC::MarkedArgumentBuffer arguments = JSC::MarkedArgumentBuffer(); - arguments.append(key); - auto callData = JSC::getCallData(function); - return JSC::JSValue::encode(call(globalObject, function, callData, JSC::jsUndefined(), arguments)); - } - return JSC::JSValue::encode(result); -} - } // namespace ExposeNodeModuleGlobalGetters extern "C" void Bun__ExposeNodeModuleGlobals(Zig::GlobalObject* globalObject) @@ -100,27 +84,4 @@ extern "C" void Bun__ExposeNodeModuleGlobals(Zig::GlobalObject* globalObject) FOREACH_EXPOSED_BUILTIN_IMR(PUT_CUSTOM_GETTER_SETTER) #undef PUT_CUSTOM_GETTER_SETTER - - - JSC::CustomGetterSetter *nativeModuleGetter = JSC::CustomGetterSetter::create( - vm, - ExposeNodeModuleGlobalGetters::jsCustomGetterGetNativeModule, - nullptr - ); - - static constexpr ASCIILiteral nativeModuleNames[] = { - "constants"_s, - "string_decoder"_s, - "buffer"_s, - "jsc"_s, - }; - - for (auto name : nativeModuleNames) { - globalObject->putDirectCustomAccessor( - vm, - JSC::Identifier::fromString(vm, name), - nativeModuleGetter, - 0 | JSC::PropertyAttribute::CustomValue - ); - } } diff --git a/src/bun.js/bindings/ImportMetaObject.cpp b/src/bun.js/bindings/ImportMetaObject.cpp index 5eabac8118..a115b3162f 100644 --- a/src/bun.js/bindings/ImportMetaObject.cpp +++ b/src/bun.js/bindings/ImportMetaObject.cpp @@ -1,3 +1,4 @@ +#include "ErrorCode.h" #include "root.h" #include "headers.h" @@ -49,6 +50,8 @@ #include "PathInlines.h" #include "wtf/text/StringView.h" +#include "isBuiltinModule.h" + namespace Zig { using namespace JSC; using namespace WebCore; @@ -80,7 +83,7 @@ static JSC::EncodedJSValue functionRequireResolve(JSC::JSGlobalObject* globalObj } BunString from = Bun::toString(fromStr); - auto result = Bun__resolveSyncWithSource(globalObject, JSC::JSValue::encode(moduleName), &from, false); + auto result = Bun__resolveSyncWithSource(globalObject, JSC::JSValue::encode(moduleName), &from, false, true); RETURN_IF_EXCEPTION(scope, {}); if (!JSC::JSValue::decode(result).isString()) { @@ -259,7 +262,7 @@ extern "C" JSC::EncodedJSValue functionImportMeta__resolveSync(JSC::JSGlobalObje } } - auto result = Bun__resolveSync(globalObject, JSC::JSValue::encode(moduleName), from, isESM); + auto result = Bun__resolveSync(globalObject, JSC::JSValue::encode(moduleName), from, isESM, false); RETURN_IF_EXCEPTION(scope, {}); if (!JSC::JSValue::decode(result).isString()) { @@ -282,12 +285,7 @@ extern "C" JSC::EncodedJSValue functionImportMeta__resolveSyncPrivate(JSC::JSGlo JSC::JSValue moduleName = callFrame->argument(0); JSValue from = callFrame->argument(1); bool isESM = callFrame->argument(2).asBoolean(); - - if (moduleName.isUndefinedOrNull()) { - JSC::throwTypeError(lexicalGlobalObject, scope, "expected module name as a string"_s); - scope.release(); - return {}; - } + bool isRequireDotResolve = callFrame->argument(3).isTrue(); RETURN_IF_EXCEPTION(scope, {}); @@ -304,7 +302,7 @@ extern "C" JSC::EncodedJSValue functionImportMeta__resolveSyncPrivate(JSC::JSGlo if (!isESM) { if (LIKELY(globalObject)) { - if (UNLIKELY(globalObject->hasOverridenModuleResolveFilenameFunction)) { + if (UNLIKELY(globalObject->hasOverriddenModuleResolveFilenameFunction)) { auto overrideHandler = jsCast(globalObject->m_moduleResolveFilenameFunction.getInitializedOnMainThread(globalObject)); if (UNLIKELY(overrideHandler)) { ASSERT(overrideHandler->isCallable()); @@ -312,7 +310,7 @@ extern "C" JSC::EncodedJSValue functionImportMeta__resolveSyncPrivate(JSC::JSGlo JSValue parentID = jsUndefined(); if (auto* parent = jsDynamicCast(parentModuleObject)) { - parentID = parent->id(); + parentID = parent->filename(); } else { parentID = from; } @@ -324,13 +322,32 @@ extern "C" JSC::EncodedJSValue functionImportMeta__resolveSyncPrivate(JSC::JSGlo auto bunStr = Bun::toString(parentIdStr); args.append(jsBoolean(Bun__isBunMain(lexicalGlobalObject, &bunStr))); - return JSValue::encode(JSC::profiledCall(lexicalGlobalObject, ProfilingReason::API, overrideHandler, JSC::getCallData(overrideHandler), parentModuleObject, args)); + JSValue result = JSC::profiledCall(lexicalGlobalObject, ProfilingReason::API, overrideHandler, JSC::getCallData(overrideHandler), parentModuleObject, args); + RETURN_IF_EXCEPTION(scope, {}); + if (!isRequireDotResolve) { + JSString* string = result.toString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto str = string->value(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + WTF::String prefixed = Bun::isUnprefixedNodeBuiltin(str); + if (!prefixed.isNull()) { + return JSValue::encode(jsString(vm, prefixed)); + } + return JSC::JSValue::encode(string); + } + return JSC::JSValue::encode(result); } } } } - auto result = Bun__resolveSync(lexicalGlobalObject, JSC::JSValue::encode(moduleName), JSValue::encode(from), isESM); + if (!moduleName.isString()) { + Bun::ERR::INVALID_ARG_TYPE(scope, globalObject, "id"_s, "string"_s, moduleName); + scope.release(); + return {}; + } + + auto result = Bun__resolveSync(lexicalGlobalObject, JSC::JSValue::encode(moduleName), JSValue::encode(from), isESM, isRequireDotResolve); RETURN_IF_EXCEPTION(scope, {}); if (!JSC::JSValue::decode(result).isString()) { diff --git a/src/bun.js/bindings/ImportMetaObject.h b/src/bun.js/bindings/ImportMetaObject.h index 078f8b6b8c..401107aaf1 100644 --- a/src/bun.js/bindings/ImportMetaObject.h +++ b/src/bun.js/bindings/ImportMetaObject.h @@ -11,8 +11,8 @@ extern "C" JSC_DECLARE_HOST_FUNCTION(functionImportMeta__resolveSync); extern "C" JSC_DECLARE_HOST_FUNCTION(functionImportMeta__resolveSyncPrivate); extern "C" JSC::EncodedJSValue Bun__resolve(JSC::JSGlobalObject* global, JSC::EncodedJSValue specifier, JSC::EncodedJSValue from, bool is_esm); -extern "C" JSC::EncodedJSValue Bun__resolveSync(JSC::JSGlobalObject* global, JSC::EncodedJSValue specifier, JSC::EncodedJSValue from, bool is_esm); -extern "C" JSC::EncodedJSValue Bun__resolveSyncWithSource(JSC::JSGlobalObject* global, JSC::EncodedJSValue specifier, BunString* from, bool is_esm); +extern "C" JSC::EncodedJSValue Bun__resolveSync(JSC::JSGlobalObject* global, JSC::EncodedJSValue specifier, JSC::EncodedJSValue from, bool is_esm, bool isUserRequireResolve); +extern "C" JSC::EncodedJSValue Bun__resolveSyncWithSource(JSC::JSGlobalObject* global, JSC::EncodedJSValue specifier, BunString* from, bool is_esm, bool isUserRequireResolve); extern "C" JSC::EncodedJSValue Bun__resolveSyncWithStrings(JSC::JSGlobalObject* global, BunString* specifier, BunString* from, bool is_esm); namespace Zig { diff --git a/src/bun.js/bindings/InternalModuleRegistry.cpp b/src/bun.js/bindings/InternalModuleRegistry.cpp index ca110c7138..e5ceda2a96 100644 --- a/src/bun.js/bindings/InternalModuleRegistry.cpp +++ b/src/bun.js/bindings/InternalModuleRegistry.cpp @@ -12,6 +12,7 @@ #include "InternalModuleRegistryConstants.h" #include "wtf/Forward.h" +#include "NativeModuleImpl.h" namespace Bun { extern "C" bool BunTest__shouldGenerateCodeCoverage(BunString sourceURL); @@ -74,6 +75,30 @@ JSC::JSValue generateModule(JSC::JSGlobalObject* globalObject, JSC::VM& vm, cons return result; } +ALWAYS_INLINE JSC::JSValue generateNativeModule( + JSC::JSGlobalObject* globalObject, + JSC::VM& vm, + const SyntheticSourceProvider::SyntheticSourceGenerator& generator) +{ + Vector propertyNames; + JSC::MarkedArgumentBuffer arguments; + auto throwScope = DECLARE_THROW_SCOPE(vm); + generator( + globalObject, + JSC::Identifier::EmptyIdentifier, // Our generators do not do anything with the key + propertyNames, + arguments); + RETURN_IF_EXCEPTION(throwScope, {}); + // This goes off of the assumption that you only call this `evaluate` using a generator that explicitly + // assigns the `default` export first. + ASSERT_WITH_MESSAGE( + propertyNames.at(0) == vm.propertyNames->defaultKeyword, + "The native module must export a default value first."); + JSValue defaultValue = arguments.at(0); + ASSERT(defaultValue); + return defaultValue; +} + #ifdef BUN_DYNAMIC_JS_LOAD_PATH JSValue initializeInternalModuleFromDisk( JSGlobalObject* globalObject, diff --git a/src/bun.js/bindings/InternalModuleRegistry.h b/src/bun.js/bindings/InternalModuleRegistry.h index 922445c600..78bb392307 100644 --- a/src/bun.js/bindings/InternalModuleRegistry.h +++ b/src/bun.js/bindings/InternalModuleRegistry.h @@ -4,13 +4,15 @@ #include #include "BunClientData.h" #include "InternalModuleRegistry+numberOfModules.h" +#include "_NativeModule.h" namespace Bun { using namespace JSC; -// Internal module registry is an array of lazily initialized "modules". Module IDs are generated -// pre-build by `make js` and inlined into JS code and the C++ enum (InternalModuleRegistry::Field) -// This allows modules depending on each other to skip the module resolver. +// Internal module registry is an array of lazily initialized "modules". Module +// IDs are generated pre-build by `bundle-modules.ts` and inlined into JS code +// and the C++ enum (InternalModuleRegistry::Field) This allows modules +// depending on each other to skip the module resolver. // // Modules come from two sources: // - some are written in JS (src/js, there is a readme file that explain those files more. diff --git a/src/bun.js/bindings/JSGlobalObject.zig b/src/bun.js/bindings/JSGlobalObject.zig index 1321ed2571..b35d576033 100644 --- a/src/bun.js/bindings/JSGlobalObject.zig +++ b/src/bun.js/bindings/JSGlobalObject.zig @@ -232,7 +232,7 @@ pub const JSGlobalObject = opaque { defer buf.deinit(); var writer = buf.writer(); writer.print(fmt, args) catch - // if an exception occurs in the middle of formatting the error message, it's better to just return the formatting string than an error about an error + // if an exception occurs in the middle of formatting the error message, it's better to just return the formatting string than an error about an error return ZigString.static(fmt).toErrorInstance(this); // Ensure we clone it. @@ -663,6 +663,10 @@ pub const JSGlobalObject = opaque { pub usingnamespace @import("ErrorCode").JSGlobalObjectExtensions; + pub fn ERR(global: *JSGlobalObject, comptime code: JSC.Error, comptime fmt: [:0]const u8, args: anytype) @import("ErrorCode").ErrorBuilder(code, fmt, @TypeOf(args)) { + return .{ .global = global, .args = args }; + } + extern fn JSC__JSGlobalObject__bunVM(*JSGlobalObject) *VM; extern fn JSC__JSGlobalObject__vm(*JSGlobalObject) *VM; extern fn JSC__JSGlobalObject__deleteModuleRegistryEntry(*JSGlobalObject, *const ZigString) void; @@ -672,6 +676,60 @@ pub const JSGlobalObject = opaque { extern fn JSGlobalObject__setTimeZone(this: *JSGlobalObject, timeZone: *const ZigString) bool; extern fn JSGlobalObject__tryTakeException(*JSGlobalObject) JSValue; extern fn JSGlobalObject__throwTerminationException(this: *JSGlobalObject) void; + + extern fn Zig__GlobalObject__create(*anyopaque, i32, bool, bool, ?*anyopaque) *JSGlobalObject; + pub fn create( + v: *JSC.VirtualMachine, + console: *anyopaque, + context_id: i32, + mini_mode: bool, + eval_mode: bool, + worker_ptr: ?*anyopaque, + ) *JSGlobalObject { + v.eventLoop().ensureWaker(); + const global = Zig__GlobalObject__create(console, context_id, mini_mode, eval_mode, worker_ptr); + + // JSC might mess with the stack size. + bun.StackCheck.configureThread(); + + return global; + } + + extern fn Zig__GlobalObject__getModuleRegistryMap(*JSGlobalObject) *anyopaque; + pub fn getModuleRegistryMap(global: *JSGlobalObject) *anyopaque { + return Zig__GlobalObject__getModuleRegistryMap(global); + } + + extern fn Zig__GlobalObject__resetModuleRegistryMap(*JSGlobalObject, *anyopaque) bool; + pub fn resetModuleRegistryMap(global: *JSGlobalObject, map: *anyopaque) bool { + return Zig__GlobalObject__resetModuleRegistryMap(global, map); + } + + pub fn resolve(res: *ErrorableString, global: *JSGlobalObject, specifier: *bun.String, source: *bun.String, query: *ZigString) callconv(.C) void { + JSC.markBinding(@src()); + return JSC.VirtualMachine.resolve(res, global, specifier.*, source.*, query, true) catch { + bun.debugAssert(res.success == false); + }; + } + + pub fn reportUncaughtException(global: *JSGlobalObject, exception: *JSC.Exception) callconv(.C) JSValue { + JSC.markBinding(@src()); + return JSC.VirtualMachine.reportUncaughtException(global, exception); + } + + pub fn onCrash() callconv(.C) void { + JSC.markBinding(@src()); + bun.Output.flush(); + @panic("A C++ exception occurred"); + } + + pub const Extern = [_][]const u8{ "create", "getModuleRegistryMap", "resetModuleRegistryMap" }; + + comptime { + @export(&resolve, .{ .name = "Zig__GlobalObject__resolve" }); + @export(&reportUncaughtException, .{ .name = "Zig__GlobalObject__reportUncaughtException" }); + @export(&onCrash, .{ .name = "Zig__GlobalObject__onCrash" }); + } }; const CommonStrings = JSC.CommonStrings; diff --git a/src/bun.js/bindings/ModuleLoader.cpp b/src/bun.js/bindings/ModuleLoader.cpp index f6ef7510ab..ae5a3b69ae 100644 --- a/src/bun.js/bindings/ModuleLoader.cpp +++ b/src/bun.js/bindings/ModuleLoader.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include "EventEmitter.h" #include "JSEventEmitter.h" @@ -32,11 +33,9 @@ #include #include -#include "../modules/_NativeModule.h" -#include "NativeModuleImpl.h" - #include "../modules/ObjectModule.h" #include "CommonJSModuleRecord.h" +#include "../modules/_NativeModule.h" namespace Bun { using namespace JSC; @@ -472,6 +471,102 @@ extern "C" void Bun__onFulfillAsyncModule( } } +JSValue fetchBuiltinModuleWithoutResolution( + Zig::GlobalObject* globalObject, + BunString* specifier, + ErrorableResolvedSource* res) +{ + void* bunVM = globalObject->bunVM(); + auto& vm = JSC::getVM(globalObject); + auto scope = DECLARE_THROW_SCOPE(vm); + BunString referrer = BunStringEmpty; + if (Bun__fetchBuiltinModule(bunVM, globalObject, specifier, &referrer, res)) { + if (!res->success) { + return {}; + } + + auto tag = res->result.value.tag; + switch (tag) { + // require("bun") + case SyntheticModuleType::BunObject: { + return globalObject->bunObject(); + } + // require("module"), require("node:module") + case SyntheticModuleType::NodeModule: { + return globalObject->m_nodeModuleConstructor.getInitializedOnMainThread(globalObject); + } + // require("process"), require("node:process") + case SyntheticModuleType::NodeProcess: { + return globalObject->processObject(); + } + + case SyntheticModuleType::ESM: { + res->success = false; + RELEASE_AND_RETURN(scope, jsNumber(-1)); + } + + default: { + if (tag & SyntheticModuleType::InternalModuleRegistryFlag) { + constexpr auto mask = (SyntheticModuleType::InternalModuleRegistryFlag - 1); + auto result = globalObject->internalModuleRegistry()->requireId(globalObject, vm, static_cast(tag & mask)); + RETURN_IF_EXCEPTION(scope, {}); + return result; + } else { + res->success = false; + RELEASE_AND_RETURN(scope, jsNumber(-1)); + } + } + } + } + return {}; +} + +JSValue resolveAndFetchBuiltinModule( + Zig::GlobalObject* globalObject, + BunString* specifier) +{ + void* bunVM = globalObject->bunVM(); + auto& vm = JSC::getVM(globalObject); + auto scope = DECLARE_THROW_SCOPE(vm); + ErrorableResolvedSource res; + memset(&res, 0, sizeof(ErrorableResolvedSource)); + if (Bun__resolveAndFetchBuiltinModule(bunVM, specifier, &res)) { + ASSERT(res.success); + + auto tag = res.result.value.tag; + switch (tag) { + // require("bun") + case SyntheticModuleType::BunObject: { + return globalObject->bunObject(); + } + // require("module"), require("node:module") + case SyntheticModuleType::NodeModule: { + return globalObject->m_nodeModuleConstructor.getInitializedOnMainThread(globalObject); + } + // require("process"), require("node:process") + case SyntheticModuleType::NodeProcess: { + return globalObject->processObject(); + } + + case SyntheticModuleType::ESM: { + return {}; + } + + default: { + if (tag & SyntheticModuleType::InternalModuleRegistryFlag) { + constexpr auto mask = (SyntheticModuleType::InternalModuleRegistryFlag - 1); + auto result = globalObject->internalModuleRegistry()->requireId(globalObject, vm, static_cast(tag & mask)); + RETURN_IF_EXCEPTION(scope, {}); + return result; + } + + return {}; + } + } + } + return {}; +} + JSValue fetchCommonJSModule( Zig::GlobalObject* globalObject, JSCommonJSModule* target, @@ -488,7 +583,6 @@ JSValue fetchCommonJSModule( ErrorableResolvedSource* res = &resValue; ResolvedSourceCodeHolder sourceCodeHolder(res); - auto& builtinNames = WebCore::clientData(vm)->builtinNames(); bool wasModuleMock = false; @@ -531,63 +625,13 @@ JSValue fetchCommonJSModule( } } - if (Bun__fetchBuiltinModule(bunVM, globalObject, specifier, referrer, res)) { + if (auto builtin = fetchBuiltinModuleWithoutResolution(globalObject, specifier, res)) { if (!res->success) { - throwException(scope, res->result.err, globalObject); - return JSValue(); - } - - auto tag = res->result.value.tag; - switch (tag) { - // require("bun") - case SyntheticModuleType::BunObject: { - target->setExportsObject(globalObject->bunObject()); - target->hasEvaluated = true; - RELEASE_AND_RETURN(scope, target); - } - // require("module"), require("node:module") - case SyntheticModuleType::NodeModule: { - target->setExportsObject(globalObject->m_nodeModuleConstructor.getInitializedOnMainThread(globalObject)); - target->hasEvaluated = true; - RELEASE_AND_RETURN(scope, target); - } - // require("process"), require("node:process") - case SyntheticModuleType::NodeProcess: { - target->setExportsObject(globalObject->processObject()); - target->hasEvaluated = true; - RELEASE_AND_RETURN(scope, target); - } -// Generated native module cases -#define CASE(str, name) \ - case SyntheticModuleType::name: { \ - target->evaluate(globalObject, specifier->toWTFString(BunString::ZeroCopy), generateNativeModule_##name); \ - RETURN_IF_EXCEPTION(scope, {}); \ - RELEASE_AND_RETURN(scope, target); \ - } - BUN_FOREACH_CJS_NATIVE_MODULE(CASE) -#undef CASE - - case SyntheticModuleType::ESM: { - RELEASE_AND_RETURN(scope, jsNumber(-1)); - } - - default: { - if (tag & SyntheticModuleType::InternalModuleRegistryFlag) { - constexpr auto mask = (SyntheticModuleType::InternalModuleRegistryFlag - 1); - auto result = globalObject->internalModuleRegistry()->requireId(globalObject, vm, static_cast(tag & mask)); - RETURN_IF_EXCEPTION(scope, {}); - - target->putDirect( - vm, - builtinNames.exportsPublicName(), - result, - JSC::PropertyAttribute::ReadOnly | 0); - RELEASE_AND_RETURN(scope, target); - } else { - RELEASE_AND_RETURN(scope, jsNumber(-1)); - } - } + RELEASE_AND_RETURN(scope, builtin); } + target->setExportsObject(builtin); + target->hasEvaluated = true; + RELEASE_AND_RETURN(scope, target); } // When "bun test" is NOT enabled, disable users from overriding builtin modules @@ -702,7 +746,7 @@ extern "C" bool isBunTest; template static JSValue fetchESMSourceCode( Zig::GlobalObject* globalObject, - JSC::JSValue specifierJS, + JSC::JSString* specifierJS, ErrorableResolvedSource* res, BunString* specifier, BunString* referrer, @@ -916,7 +960,7 @@ static JSValue fetchESMSourceCode( JSValue fetchESMSourceCodeSync( Zig::GlobalObject* globalObject, - JSC::JSValue specifierJS, + JSC::JSString* specifierJS, ErrorableResolvedSource* res, BunString* specifier, BunString* referrer, @@ -927,7 +971,7 @@ JSValue fetchESMSourceCodeSync( JSValue fetchESMSourceCodeAsync( Zig::GlobalObject* globalObject, - JSC::JSValue specifierJS, + JSC::JSString* specifierJS, ErrorableResolvedSource* res, BunString* specifier, BunString* referrer, diff --git a/src/bun.js/bindings/ModuleLoader.h b/src/bun.js/bindings/ModuleLoader.h index d38ed441e1..6285d428a2 100644 --- a/src/bun.js/bindings/ModuleLoader.h +++ b/src/bun.js/bindings/ModuleLoader.h @@ -92,7 +92,7 @@ public: JSValue fetchESMSourceCodeSync( Zig::GlobalObject* globalObject, - JSValue spceifierJS, + JSString* spceifierJS, ErrorableResolvedSource* res, BunString* specifier, BunString* referrer, @@ -100,7 +100,7 @@ JSValue fetchESMSourceCodeSync( JSValue fetchESMSourceCodeAsync( Zig::GlobalObject* globalObject, - JSValue spceifierJS, + JSString* spceifierJS, ErrorableResolvedSource* res, BunString* specifier, BunString* referrer, @@ -114,4 +114,13 @@ JSValue fetchCommonJSModule( BunString* referrer, BunString* typeAttribute); +JSValue resolveAndFetchBuiltinModule( + Zig::GlobalObject* globalObject, + BunString* specifier); + +JSValue fetchBuiltinModuleWithoutResolution( + Zig::GlobalObject* globalObject, + BunString* specifier, + ErrorableResolvedSource* res); + } // namespace Bun diff --git a/src/bun.js/bindings/NodeModuleModule.zig b/src/bun.js/bindings/NodeModuleModule.zig index 03f48fefd9..3d80dcef9e 100644 --- a/src/bun.js/bindings/NodeModuleModule.zig +++ b/src/bun.js/bindings/NodeModuleModule.zig @@ -54,14 +54,22 @@ fn findPathInner( global: *JSGlobalObject, ) ?bun.String { var errorable: ErrorableString = undefined; - JSC.VirtualMachine.resolve( + JSC.VirtualMachine.resolveMaybeNeedsTrailingSlash( &errorable, global, request, cur_path, null, false, - ); + true, + true, + ) catch |err| switch (err) { + error.JSError => { + global.clearException(); + return null; + }, + else => return null, + }; return errorable.unwrap() catch null; } diff --git a/src/bun.js/bindings/ScriptExecutionContext.h b/src/bun.js/bindings/ScriptExecutionContext.h index 675a37f5b1..c17894f892 100644 --- a/src/bun.js/bindings/ScriptExecutionContext.h +++ b/src/bun.js/bindings/ScriptExecutionContext.h @@ -79,7 +79,7 @@ public: { return m_url; } - bool isMainThread() const { return static_cast(m_identifier) == 1; } + bool isMainThread() const { return m_identifier == 1; } bool activeDOMObjectsAreSuspended() { return false; } bool activeDOMObjectsAreStopped() { return false; } bool isContextThread(); diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index 4decf57721..9e7ae94535 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -928,7 +928,7 @@ extern "C" JSC__JSGlobalObject* Zig__GlobalObject__create(void* console_client, WebCore::JSVMClientData::create(&vm, Bun__getVM()); const auto createGlobalObject = [&]() -> Zig::GlobalObject* { - if (UNLIKELY(executionContextId == std::numeric_limits::max() || executionContextId > -1)) { + if (UNLIKELY(executionContextId == std::numeric_limits::max() || executionContextId > 1)) { auto* structure = Zig::GlobalObject::createStructure(vm); if (UNLIKELY(!structure)) { return nullptr; @@ -1028,12 +1028,15 @@ JSC_DEFINE_HOST_FUNCTION(functionFulfillModuleSync, auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); - JSC::JSValue key = callFrame->argument(0); - - auto moduleKey = key.toWTFString(globalObject); + JSC::JSValue keyAny = callFrame->argument(0); + JSC::JSString* moduleKeyString = keyAny.toString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto moduleKey = moduleKeyString->value(globalObject); RETURN_IF_EXCEPTION(scope, {}); - if (moduleKey.endsWith(".node"_s)) { + RETURN_IF_EXCEPTION(scope, {}); + + if (moduleKey->endsWith(".node"_s)) { throwException(globalObject, scope, createTypeError(globalObject, "To load Node-API modules, use require() or process.dlopen instead of importSync."_s)); return {}; } @@ -1046,7 +1049,7 @@ JSC_DEFINE_HOST_FUNCTION(functionFulfillModuleSync, JSValue result = Bun::fetchESMSourceCodeSync( globalObject, - key, + moduleKeyString, &res, &specifier, &specifier, @@ -1056,7 +1059,7 @@ JSC_DEFINE_HOST_FUNCTION(functionFulfillModuleSync, RELEASE_AND_RETURN(scope, JSValue::encode(JSC::jsUndefined())); } - globalObject->moduleLoader()->provideFetch(globalObject, key, jsCast(result)->sourceCode()); + globalObject->moduleLoader()->provideFetch(globalObject, keyAny, jsCast(result)->sourceCode()); RELEASE_AND_RETURN(scope, JSValue::encode(JSC::jsUndefined())); } @@ -3818,7 +3821,6 @@ void GlobalObject::addBuiltinGlobals(JSC::VM& vm) putDirectBuiltinFunction(vm, this, builtinNames.requireESMPrivateName(), importMetaObjectRequireESMCodeGenerator(vm), PropertyAttribute::Builtin | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); putDirectBuiltinFunction(vm, this, builtinNames.loadCJS2ESMPrivateName(), importMetaObjectLoadCJS2ESMCodeGenerator(vm), PropertyAttribute::Builtin | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); putDirectBuiltinFunction(vm, this, builtinNames.internalRequirePrivateName(), importMetaObjectInternalRequireCodeGenerator(vm), PropertyAttribute::Builtin | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); - putDirectBuiltinFunction(vm, this, builtinNames.requireNativeModulePrivateName(), moduleRequireNativeModuleCodeGenerator(vm), PropertyAttribute::Builtin | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); putDirectBuiltinFunction(vm, this, builtinNames.overridableRequirePrivateName(), moduleOverridableRequireCodeGenerator(vm), 0); @@ -3836,7 +3838,7 @@ void GlobalObject::addBuiltinGlobals(JSC::VM& vm) putDirectNativeFunction(vm, this, builtinNames.evaluateCommonJSModulePrivateName(), 2, - Bun::jsFunctionLoadModule, + Bun::jsFunctionEvaluateCommonJSModule, ImplementationVisibility::Public, NoIntrinsic, PropertyAttribute::ReadOnly | PropertyAttribute::DontDelete | 0); @@ -4445,11 +4447,13 @@ JSC::JSInternalPromise* GlobalObject::moduleLoaderFetch(JSGlobalObject* globalOb auto scope = DECLARE_THROW_SCOPE(vm); - auto moduleKey = key.toWTFString(globalObject); + auto moduleKeyJS = key.toString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto moduleKey = moduleKeyJS->value(globalObject); if (UNLIKELY(scope.exception())) return rejectedInternalPromise(globalObject, scope.exception()->value()); - if (moduleKey.endsWith(".node"_s)) { + if (moduleKey->endsWith(".node"_s)) { return rejectedInternalPromise(globalObject, createTypeError(globalObject, "To load Node-API modules, use require() or process.dlopen instead of import."_s)); } @@ -4482,7 +4486,7 @@ JSC::JSInternalPromise* GlobalObject::moduleLoaderFetch(JSGlobalObject* globalOb JSValue result = Bun::fetchESMSourceCodeAsync( reinterpret_cast(globalObject), - key, + moduleKeyJS, &res, &moduleKeyBun, &source, diff --git a/src/bun.js/bindings/ZigGlobalObject.h b/src/bun.js/bindings/ZigGlobalObject.h index d94a173325..bfc8d6eee0 100644 --- a/src/bun.js/bindings/ZigGlobalObject.h +++ b/src/bun.js/bindings/ZigGlobalObject.h @@ -402,6 +402,9 @@ public: mutable WriteBarrier m_nextTickQueue; + WTF::String m_moduleWrapperStart; + WTF::String m_moduleWrapperEnd; + // mutable WriteBarrier m_JSBunDebuggerValue; mutable WriteBarrier m_thenables[promiseFunctionsSize + 1]; @@ -624,7 +627,10 @@ public: LazyProperty m_statFsValues; LazyProperty m_bigintStatFsValues; - bool hasOverridenModuleResolveFilenameFunction = false; + // De-optimization once `require("module")._resolveFilename` is written to + bool hasOverriddenModuleResolveFilenameFunction = false; + // De-optimization once `require("module").wrapper` or `require("module").wrap` is written to + bool hasOverriddenModuleWrapper = false; WTF::Vector> m_napiEnvs; napi_env makeNapiEnv(const napi_module&); diff --git a/src/bun.js/bindings/ZigGlobalObject.zig b/src/bun.js/bindings/ZigGlobalObject.zig deleted file mode 100644 index 73fabdadb7..0000000000 --- a/src/bun.js/bindings/ZigGlobalObject.zig +++ /dev/null @@ -1,84 +0,0 @@ -const bun = @import("root").bun; -const JSC = bun.JSC; -const JSGlobalObject = JSC.JSGlobalObject; -const ZigString = JSC.ZigString; -const String = bun.String; -const JSValue = JSC.JSValue; -const JSPromise = JSC.JSPromise; -const JSPromiseRejectionOperation = JSC.JSPromiseRejectionOperation; -const Exception = JSC.Exception; -const ErrorableString = JSC.ErrorableString; -const NewGlobalObject = JSC.NewGlobalObject; - -/// Global object for Zig JavaScript environment -pub const ZigGlobalObject = opaque { - const interface = NewGlobalObject(JSC.VirtualMachine); - pub fn create( - vm: *JSC.VirtualMachine, - console: *anyopaque, - context_id: i32, - mini_mode: bool, - eval_mode: bool, - worker_ptr: ?*anyopaque, - ) *JSGlobalObject { - vm.eventLoop().ensureWaker(); - const global = Zig__GlobalObject__create(console, context_id, mini_mode, eval_mode, worker_ptr); - - // JSC might mess with the stack size. - bun.StackCheck.configureThread(); - - return global; - } - - pub fn getModuleRegistryMap(global: *JSGlobalObject) *anyopaque { - return Zig__GlobalObject__getModuleRegistryMap(global); - } - - pub fn resetModuleRegistryMap(global: *JSGlobalObject, map: *anyopaque) bool { - return Zig__GlobalObject__resetModuleRegistryMap(global, map); - } - - extern fn Zig__GlobalObject__create( - console: *anyopaque, - context_id: i32, - mini_mode: bool, - eval_mode: bool, - worker_ptr: ?*anyopaque, - ) *JSGlobalObject; - - extern fn Zig__GlobalObject__getModuleRegistryMap(global: *JSGlobalObject) *anyopaque; - extern fn Zig__GlobalObject__resetModuleRegistryMap(global: *JSGlobalObject, map: *anyopaque) bool; - - pub fn import(global: *JSGlobalObject, specifier: *bun.String, source: *bun.String) callconv(.C) ErrorableString { - JSC.markBinding(@src()); - return @call(bun.callmod_inline, interface.import, .{ global, specifier, source }); - } - - pub fn resolve(res: *ErrorableString, global: *JSGlobalObject, specifier: *bun.String, source: *bun.String, query: *ZigString) callconv(.C) void { - JSC.markBinding(@src()); - @call(bun.callmod_inline, interface.resolve, .{ res, global, specifier, source, query }); - } - - pub fn promiseRejectionTracker(global: *JSGlobalObject, promise: *JSPromise, rejection: JSPromiseRejectionOperation) callconv(.C) JSValue { - JSC.markBinding(@src()); - return @call(bun.callmod_inline, interface.promiseRejectionTracker, .{ global, promise, rejection }); - } - - pub fn reportUncaughtException(global: *JSGlobalObject, exception: *Exception) callconv(.C) JSValue { - JSC.markBinding(@src()); - return @call(bun.callmod_inline, interface.reportUncaughtException, .{ global, exception }); - } - - pub fn onCrash() callconv(.C) void { - JSC.markBinding(@src()); - return @call(bun.callmod_inline, interface.onCrash, .{}); - } - - comptime { - @export(&import, .{ .name = "Zig__GlobalObject__import" }); - @export(&resolve, .{ .name = "Zig__GlobalObject__resolve" }); - @export(&promiseRejectionTracker, .{ .name = "Zig__GlobalObject__promiseRejectionTracker" }); - @export(&reportUncaughtException, .{ .name = "Zig__GlobalObject__reportUncaughtException" }); - @export(&onCrash, .{ .name = "Zig__GlobalObject__onCrash" }); - } -}; diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index 646ac55c18..2fd039f4ab 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -2792,7 +2792,7 @@ JSC__JSValue JSC__JSValue__createRangeError(const ZigString* message, const ZigS if (code.len > 0) { auto clientData = WebCore::clientData(vm); - JSC::JSValue codeValue = Zig::toJSStringValue(code, globalObject); + JSC::JSValue codeValue = Zig::toJSString(code, globalObject); rangeError->putDirect(vm, clientData->builtinNames().codePublicName(), codeValue, JSC::PropertyAttribute::ReadOnly | 0); } @@ -2809,7 +2809,7 @@ JSC__JSValue JSC__JSValue__createTypeError(const ZigString* message, const ZigSt if (code.len > 0) { auto clientData = WebCore::clientData(vm); - JSC::JSValue codeValue = Zig::toJSStringValue(code, globalObject); + JSC::JSValue codeValue = Zig::toJSString(code, globalObject); typeError->putDirect(vm, clientData->builtinNames().codePublicName(), codeValue, 0); } @@ -2834,12 +2834,12 @@ JSC__JSValue JSC__JSValue__fromEntries(JSC__JSGlobalObject* globalObject, ZigStr for (size_t i = 0; i < initialCapacity; ++i) { object->putDirect( vm, JSC::PropertyName(JSC::Identifier::fromString(vm, Zig::toString(keys[i]))), - Zig::toJSStringValueGC(values[i], globalObject), 0); + Zig::toJSStringGC(values[i], globalObject), 0); } } else { for (size_t i = 0; i < initialCapacity; ++i) { object->putDirect(vm, JSC::PropertyName(Zig::toIdentifier(keys[i], globalObject)), - Zig::toJSStringValueGC(values[i], globalObject), 0); + Zig::toJSStringGC(values[i], globalObject), 0); } } } diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig index 51f1841af0..a44efc4450 100644 --- a/src/bun.js/bindings/bindings.zig +++ b/src/bun.js/bindings/bindings.zig @@ -62,64 +62,6 @@ pub const ScriptExecutionStatus = @import("./ScriptExecutionStatus.zig").ScriptE pub const DeferredError = @import("./DeferredError.zig").DeferredError; pub const Sizes = @import("./sizes.zig"); -// TODO(@paperdave): delete and inline these functions -pub fn NewGlobalObject(comptime Type: type) type { - return struct { - const importNotImpl = "Import not implemented"; - const resolveNotImpl = "resolve not implemented"; - const moduleNotImpl = "Module fetch not implemented"; - pub fn import(global: *JSGlobalObject, specifier: *String, source: *String) callconv(.C) ErrorableString { - if (comptime @hasDecl(Type, "import")) { - return @call(bun.callmod_inline, Type.import, .{ global, specifier.*, source.* }); - } - return ErrorableString.err(error.ImportFailed, String.init(importNotImpl).toErrorInstance(global).asVoid()); - } - pub fn resolve( - res: *ErrorableString, - global: *JSGlobalObject, - specifier: *String, - source: *String, - query_string: *ZigString, - ) callconv(.C) void { - if (comptime @hasDecl(Type, "resolve")) { - @call(bun.callmod_inline, Type.resolve, .{ res, global, specifier.*, source.*, query_string, true }); - return; - } - res.* = ErrorableString.err(error.ResolveFailed, String.init(resolveNotImpl).toErrorInstance(global).asVoid()); - } - pub fn fetch(ret: *ErrorableResolvedSource, global: *JSGlobalObject, specifier: *String, source: *String) callconv(.C) void { - if (comptime @hasDecl(Type, "fetch")) { - @call(bun.callmod_inline, Type.fetch, .{ ret, global, specifier.*, source.* }); - return; - } - ret.* = ErrorableResolvedSource.err(error.FetchFailed, String.init(moduleNotImpl).toErrorInstance(global).asVoid()); - } - pub fn promiseRejectionTracker(global: *JSGlobalObject, promise: *JSPromise, rejection: JSPromiseRejectionOperation) callconv(.C) JSValue { - if (comptime @hasDecl(Type, "promiseRejectionTracker")) { - return @call(bun.callmod_inline, Type.promiseRejectionTracker, .{ global, promise, rejection }); - } - return JSValue.jsUndefined(); - } - - pub fn reportUncaughtException(global: *JSGlobalObject, exception: *JSC.Exception) callconv(.C) JSValue { - if (comptime @hasDecl(Type, "reportUncaughtException")) { - return @call(bun.callmod_inline, Type.reportUncaughtException, .{ global, exception }); - } - return JSValue.jsUndefined(); - } - - pub fn onCrash() callconv(.C) void { - if (comptime @hasDecl(Type, "onCrash")) { - return @call(bun.callmod_inline, Type.onCrash, .{}); - } - - Output.flush(); - - @panic("A C++ exception occurred"); - } - }; -} - pub fn PromiseCallback(comptime Type: type, comptime CallbackFunction: fn (*Type, *JSGlobalObject, []const JSValue) anyerror!JSValue) type { return struct { pub fn callback( diff --git a/src/bun.js/bindings/exports.zig b/src/bun.js/bindings/exports.zig index 382570442f..f239c35f99 100644 --- a/src/bun.js/bindings/exports.zig +++ b/src/bun.js/bindings/exports.zig @@ -13,7 +13,6 @@ const JestPrettyFormat = @import("../test/pretty_format.zig").JestPrettyFormat; // Re-export all the split-out types pub const Exception = @import("Exception.zig").Exception; -pub const ZigGlobalObject = @import("ZigGlobalObject.zig").ZigGlobalObject; pub const ErrorCode = @import("ErrorCode.zig").ErrorCode; pub const ZigErrorType = @import("ZigErrorType.zig").ZigErrorType; pub const NodePath = JSC.Node.Path; diff --git a/src/bun.js/bindings/headers-handwritten.h b/src/bun.js/bindings/headers-handwritten.h index a81d3f193c..55710a0ebf 100644 --- a/src/bun.js/bindings/headers-handwritten.h +++ b/src/bun.js/bindings/headers-handwritten.h @@ -292,7 +292,7 @@ extern "C" JSC::EncodedJSValue BunString__toJS(JSC::JSGlobalObject*, const BunSt extern "C" void BunString__toWTFString(BunString*); namespace Bun { -JSC::JSValue toJS(JSC::JSGlobalObject*, BunString); +JSC::JSString* toJS(JSC::JSGlobalObject*, BunString); BunString toString(JSC::JSGlobalObject* globalObject, JSC::JSValue value); BunString toString(const char* bytes, size_t length); BunString toString(WTF::String& wtfString); @@ -355,6 +355,10 @@ extern "C" bool Bun__fetchBuiltinModule( const BunString* specifier, const BunString* referrer, ErrorableResolvedSource* result); +extern "C" bool Bun__resolveAndFetchBuiltinModule( + void* bunVM, + const BunString* specifier, + ErrorableResolvedSource* result); // Used in process.version extern "C" const char* Bun__version; diff --git a/src/bun.js/bindings/headers.h b/src/bun.js/bindings/headers.h index 726d18a47b..a2b20170aa 100644 --- a/src/bun.js/bindings/headers.h +++ b/src/bun.js/bindings/headers.h @@ -559,7 +559,6 @@ CPP_DECL bool Zig__GlobalObject__resetModuleRegistryMap(JSC__JSGlobalObject* arg #ifdef __cplusplus ZIG_DECL void Zig__GlobalObject__fetch(ErrorableResolvedSource* arg0, JSC__JSGlobalObject* arg1, BunString* arg2, BunString* arg3); -ZIG_DECL ErrorableString Zig__GlobalObject__import(JSC__JSGlobalObject* arg0, BunString* arg1, BunString* arg2); ZIG_DECL void Zig__GlobalObject__onCrash(); ZIG_DECL JSC__JSValue Zig__GlobalObject__promiseRejectionTracker(JSC__JSGlobalObject* arg0, JSC__JSPromise* arg1, uint32_t JSPromiseRejectionOperation2); ZIG_DECL JSC__JSValue Zig__GlobalObject__reportUncaughtException(JSC__JSGlobalObject* arg0, JSC__Exception* arg1); diff --git a/src/bun.js/bindings/helpers.h b/src/bun.js/bindings/helpers.h index 3abaa526b0..13962fd336 100644 --- a/src/bun.js/bindings/helpers.h +++ b/src/bun.js/bindings/helpers.h @@ -193,21 +193,11 @@ static const JSC::JSString* toJSString(ZigString str, JSC::JSGlobalObject* globa return JSC::jsOwnedString(global->vm(), toString(str)); } -static const JSC::JSValue toJSStringValue(ZigString str, JSC::JSGlobalObject* global) -{ - return JSC::JSValue(toJSString(str, global)); -} - -static const JSC::JSString* toJSStringGC(ZigString str, JSC::JSGlobalObject* global) +static JSC::JSString* toJSStringGC(ZigString str, JSC::JSGlobalObject* global) { return JSC::jsString(global->vm(), toStringCopy(str)); } -static const JSC::JSValue toJSStringValueGC(ZigString str, JSC::JSGlobalObject* global) -{ - return JSC::JSValue(toJSStringGC(str, global)); -} - static const ZigString ZigStringEmpty = ZigString { (unsigned char*)"", 0 }; static const unsigned char __dot_char = '.'; static const ZigString ZigStringCwd = ZigString { &__dot_char, 1 }; diff --git a/src/bun.js/bindings/isBuiltinModule.cpp b/src/bun.js/bindings/isBuiltinModule.cpp index 39ee50aca5..1bfd6ad23f 100644 --- a/src/bun.js/bindings/isBuiltinModule.cpp +++ b/src/bun.js/bindings/isBuiltinModule.cpp @@ -106,4 +106,154 @@ bool isBuiltinModule(const String& namePossiblyWithNodePrefix) return false; } +String isUnprefixedNodeBuiltin(const String& name) +{ + static constexpr ASCIILiteral unprefixedNodeBuiltinNamesSortedLength[] = { + "fs"_s, + "os"_s, + "v8"_s, + "vm"_s, + "dns"_s, + "net"_s, + "sys"_s, + "tls"_s, + "tty"_s, + "url"_s, + "http"_s, + "path"_s, + "repl"_s, + "util"_s, + "wasi"_s, + "zlib"_s, + "dgram"_s, + "http2"_s, + "https"_s, + "assert"_s, + "buffer"_s, + "crypto"_s, + "domain"_s, + "events"_s, + "module"_s, + "stream"_s, + "timers"_s, + "cluster"_s, + "console"_s, + "process"_s, + "punycode"_s, + "readline"_s, + "_tls_wrap"_s, + "constants"_s, + "inspector"_s, + "path/posix"_s, + "path/win32"_s, + "perf_hooks"_s, + "stream/web"_s, + "util/types"_s, + "_http_agent"_s, + "_tls_common"_s, + "async_hooks"_s, + "fs/promises"_s, + "querystring"_s, + "_http_client"_s, + "_http_common"_s, + "_http_server"_s, + "_stream_wrap"_s, + "dns/promises"_s, + "trace_events"_s, + "assert/strict"_s, + "child_process"_s, + "_http_incoming"_s, + "_http_outgoing"_s, + "_stream_duplex"_s, + "string_decoder"_s, + "worker_threads"_s, + "stream/promises"_s, + "timers/promises"_s, + "_stream_readable"_s, + "_stream_writable"_s, + "stream/consumers"_s, + "_stream_transform"_s, + "readline/promises"_s, + "inspector/promises"_s, + "_stream_passthrough"_s, + "diagnostics_channel"_s, + }; + static const NeverDestroyed mapTo[] = { + MAKE_STATIC_STRING_IMPL("node:fs"), + MAKE_STATIC_STRING_IMPL("node:os"), + MAKE_STATIC_STRING_IMPL("node:v8"), + MAKE_STATIC_STRING_IMPL("node:vm"), + MAKE_STATIC_STRING_IMPL("node:dns"), + MAKE_STATIC_STRING_IMPL("node:net"), + MAKE_STATIC_STRING_IMPL("node:sys"), + MAKE_STATIC_STRING_IMPL("node:tls"), + MAKE_STATIC_STRING_IMPL("node:tty"), + MAKE_STATIC_STRING_IMPL("node:url"), + MAKE_STATIC_STRING_IMPL("node:http"), + MAKE_STATIC_STRING_IMPL("node:path"), + MAKE_STATIC_STRING_IMPL("node:repl"), + MAKE_STATIC_STRING_IMPL("node:util"), + MAKE_STATIC_STRING_IMPL("node:wasi"), + MAKE_STATIC_STRING_IMPL("node:zlib"), + MAKE_STATIC_STRING_IMPL("node:dgram"), + MAKE_STATIC_STRING_IMPL("node:http2"), + MAKE_STATIC_STRING_IMPL("node:https"), + MAKE_STATIC_STRING_IMPL("node:assert"), + MAKE_STATIC_STRING_IMPL("node:buffer"), + MAKE_STATIC_STRING_IMPL("node:crypto"), + MAKE_STATIC_STRING_IMPL("node:domain"), + MAKE_STATIC_STRING_IMPL("node:events"), + MAKE_STATIC_STRING_IMPL("node:module"), + MAKE_STATIC_STRING_IMPL("node:stream"), + MAKE_STATIC_STRING_IMPL("node:timers"), + MAKE_STATIC_STRING_IMPL("node:cluster"), + MAKE_STATIC_STRING_IMPL("node:console"), + MAKE_STATIC_STRING_IMPL("node:process"), + MAKE_STATIC_STRING_IMPL("node:punycode"), + MAKE_STATIC_STRING_IMPL("node:readline"), + MAKE_STATIC_STRING_IMPL("node:_tls_wrap"), + MAKE_STATIC_STRING_IMPL("node:constants"), + MAKE_STATIC_STRING_IMPL("node:inspector"), + MAKE_STATIC_STRING_IMPL("node:path/posix"), + MAKE_STATIC_STRING_IMPL("node:path/win32"), + MAKE_STATIC_STRING_IMPL("node:perf_hooks"), + MAKE_STATIC_STRING_IMPL("node:stream/web"), + MAKE_STATIC_STRING_IMPL("node:util/types"), + MAKE_STATIC_STRING_IMPL("node:_http_agent"), + MAKE_STATIC_STRING_IMPL("node:_tls_common"), + MAKE_STATIC_STRING_IMPL("node:async_hooks"), + MAKE_STATIC_STRING_IMPL("node:fs/promises"), + MAKE_STATIC_STRING_IMPL("node:querystring"), + MAKE_STATIC_STRING_IMPL("node:_http_client"), + MAKE_STATIC_STRING_IMPL("node:_http_common"), + MAKE_STATIC_STRING_IMPL("node:_http_server"), + MAKE_STATIC_STRING_IMPL("node:_stream_wrap"), + MAKE_STATIC_STRING_IMPL("node:dns/promises"), + MAKE_STATIC_STRING_IMPL("node:trace_events"), + MAKE_STATIC_STRING_IMPL("node:assert/strict"), + MAKE_STATIC_STRING_IMPL("node:child_process"), + MAKE_STATIC_STRING_IMPL("node:_http_incoming"), + MAKE_STATIC_STRING_IMPL("node:_http_outgoing"), + MAKE_STATIC_STRING_IMPL("node:_stream_duplex"), + MAKE_STATIC_STRING_IMPL("node:string_decoder"), + MAKE_STATIC_STRING_IMPL("node:worker_threads"), + MAKE_STATIC_STRING_IMPL("node:stream/promises"), + MAKE_STATIC_STRING_IMPL("node:timers/promises"), + MAKE_STATIC_STRING_IMPL("node:_stream_readable"), + MAKE_STATIC_STRING_IMPL("node:_stream_writable"), + MAKE_STATIC_STRING_IMPL("node:stream/consumers"), + MAKE_STATIC_STRING_IMPL("node:_stream_transform"), + MAKE_STATIC_STRING_IMPL("node:readline/promises"), + MAKE_STATIC_STRING_IMPL("node:inspector/promises"), + MAKE_STATIC_STRING_IMPL("node:_stream_passthrough"), + MAKE_STATIC_STRING_IMPL("node:diagnostics_channel"), + }; + for (size_t i = 0; i < std::size(unprefixedNodeBuiltinNamesSortedLength); i++) { + if (name == unprefixedNodeBuiltinNamesSortedLength[i]) { + return mapTo[i]; + } + } + return String(); +} + } // namespace Bun diff --git a/src/bun.js/bindings/isBuiltinModule.h b/src/bun.js/bindings/isBuiltinModule.h index 296dbf402f..2038c8188a 100644 --- a/src/bun.js/bindings/isBuiltinModule.h +++ b/src/bun.js/bindings/isBuiltinModule.h @@ -2,4 +2,5 @@ namespace Bun { bool isBuiltinModule(const String& namePossiblyWithNodePrefix); +String isUnprefixedNodeBuiltin(const String& name); } // namespace Bun diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig index 9c3925912b..8913273c7d 100644 --- a/src/bun.js/javascript.zig +++ b/src/bun.js/javascript.zig @@ -62,7 +62,6 @@ const JSInternalPromise = bun.JSC.JSInternalPromise; const JSModuleLoader = bun.JSC.JSModuleLoader; const JSPromiseRejectionOperation = bun.JSC.JSPromiseRejectionOperation; const ErrorableZigString = bun.JSC.ErrorableZigString; -const ZigGlobalObject = bun.JSC.ZigGlobalObject; const VM = JSC.VM; const JSFunction = bun.JSC.JSFunction; const Config = @import("./config.zig"); @@ -418,8 +417,8 @@ pub export fn Bun__GlobalObject__hasIPC(global: *JSGlobalObject) bool { return global.bunVM().ipc != null; } -pub extern fn Bun__Process__queueNextTick1(*ZigGlobalObject, func: JSValue, JSValue) void; -pub extern fn Bun__Process__queueNextTick2(*ZigGlobalObject, func: JSValue, JSValue, JSValue) void; +pub extern fn Bun__Process__queueNextTick1(*JSGlobalObject, func: JSValue, JSValue) void; +pub extern fn Bun__Process__queueNextTick2(*JSGlobalObject, func: JSValue, JSValue, JSValue) void; comptime { const Bun__Process__send = JSC.toJSHostFunction(Bun__Process__send_); @@ -450,14 +449,13 @@ pub fn Bun__Process__send_(globalObject: *JSGlobalObject, callFrame: *JSC.CallFr }; const vm = globalObject.bunVM(); - const zigGlobal: *ZigGlobalObject = @ptrCast(globalObject); const ipc_instance = vm.getIPCInstance() orelse { const ex = globalObject.ERR_IPC_CHANNEL_CLOSED("Channel closed.", .{}).toJS(); if (callback.isFunction()) { - Bun__Process__queueNextTick1(zigGlobal, callback, ex); + Bun__Process__queueNextTick1(globalObject, callback, ex); } else { const fnvalue = JSFunction.create(globalObject, "", S.impl, 1, .{}); - Bun__Process__queueNextTick1(zigGlobal, fnvalue, ex); + Bun__Process__queueNextTick1(globalObject, fnvalue, ex); } return .false; }; @@ -473,16 +471,16 @@ pub fn Bun__Process__send_(globalObject: *JSGlobalObject, callFrame: *JSC.CallFr if (good) { if (callback.isFunction()) { - Bun__Process__queueNextTick1(zigGlobal, callback, .null); + Bun__Process__queueNextTick1(globalObject, callback, .null); } } else { const ex = globalObject.createTypeErrorInstance("process.send() failed", .{}); ex.put(globalObject, ZigString.static("syscall"), bun.String.static("write").toJS(globalObject)); if (callback.isFunction()) { - Bun__Process__queueNextTick1(zigGlobal, callback, ex); + Bun__Process__queueNextTick1(globalObject, callback, ex); } else { const fnvalue = JSFunction.create(globalObject, "", S.impl, 1, .{}); - Bun__Process__queueNextTick1(zigGlobal, fnvalue, ex); + Bun__Process__queueNextTick1(globalObject, fnvalue, ex); } } @@ -1972,10 +1970,10 @@ pub const VirtualMachine = struct { if (opts.is_main_thread) { VMHolder.main_thread_vm = vm; } - vm.global = ZigGlobalObject.create( + vm.global = JSGlobalObject.create( vm, vm.console, - if (opts.is_main_thread) -1 else std.math.maxInt(i32), + if (opts.is_main_thread) 1 else std.math.maxInt(i32), false, false, null, @@ -2089,10 +2087,10 @@ pub const VirtualMachine = struct { vm.transpiler.macro_context = js_ast.Macro.MacroContext.init(&vm.transpiler); - vm.global = ZigGlobalObject.create( + vm.global = JSGlobalObject.create( vm, vm.console, - if (opts.is_main_thread) -1 else std.math.maxInt(i32), + if (opts.is_main_thread) 1 else std.math.maxInt(i32), opts.smol, opts.eval, null, @@ -2255,7 +2253,7 @@ pub const VirtualMachine = struct { vm.smol = opts.smol; vm.transpiler.macro_context = js_ast.Macro.MacroContext.init(&vm.transpiler); - vm.global = ZigGlobalObject.create( + vm.global = JSGlobalObject.create( vm, vm.console, @as(i32, @intCast(worker.execution_context_id)), @@ -2519,7 +2517,7 @@ pub const VirtualMachine = struct { ret.result = null; ret.path = specifier; return; - } else if (JSC.HardcodedModule.Aliases.get(specifier, .bun)) |result| { + } else if (JSC.HardcodedModule.Alias.get(specifier, .bun)) |result| { ret.result = null; ret.path = result.path; return; @@ -2616,30 +2614,6 @@ pub const VirtualMachine = struct { ret.path = result_path.text; } - pub fn resolveForAPI( - res: *ErrorableString, - global: *JSGlobalObject, - specifier: bun.String, - source: bun.String, - query_string: ?*ZigString, - is_esm: bool, - ) void { - resolveMaybeNeedsTrailingSlash(res, global, specifier, source, query_string, is_esm, false) catch {}; - // TODO: handle js exception - } - - pub fn resolveFilePathForAPI( - res: *ErrorableString, - global: *JSGlobalObject, - specifier: bun.String, - source: bun.String, - query_string: ?*ZigString, - is_esm: bool, - ) void { - resolveMaybeNeedsTrailingSlash(res, global, specifier, source, query_string, is_esm, true) catch {}; - // TODO: handle js exception - } - pub fn resolve( res: *ErrorableString, global: *JSGlobalObject, @@ -2647,9 +2621,8 @@ pub const VirtualMachine = struct { source: bun.String, query_string: ?*ZigString, is_esm: bool, - ) void { - resolveMaybeNeedsTrailingSlash(res, global, specifier, source, query_string, is_esm, true) catch {}; - // TODO: handle js exception + ) !void { + try resolveMaybeNeedsTrailingSlash(res, global, specifier, source, query_string, is_esm, true, false); } fn normalizeSource(source: []const u8) []const u8 { @@ -2660,7 +2633,16 @@ pub const VirtualMachine = struct { return source; } - fn resolveMaybeNeedsTrailingSlash(res: *ErrorableString, global: *JSGlobalObject, specifier: bun.String, source: bun.String, query_string: ?*ZigString, is_esm: bool, comptime is_a_file_path: bool) bun.JSError!void { + pub fn resolveMaybeNeedsTrailingSlash( + res: *ErrorableString, + global: *JSGlobalObject, + specifier: bun.String, + source: bun.String, + query_string: ?*ZigString, + is_esm: bool, + comptime is_a_file_path: bool, + is_user_require_resolve: bool, + ) bun.JSError!void { if (is_a_file_path and specifier.length() > comptime @as(u32, @intFromFloat(@trunc(@as(f64, @floatFromInt(bun.MAX_PATH_BYTES)) * 1.5)))) { const specifier_utf8 = specifier.toUTF8(bun.default_allocator); defer specifier_utf8.deinit(); @@ -2671,6 +2653,7 @@ pub const VirtualMachine = struct { specifier_utf8.slice(), source_utf8.slice(), error.NameTooLong, + if (is_esm) .stmt else if (is_user_require_resolve) .require_resolve else .require, ) catch bun.outOfMemory(); const msg = logger.Msg{ .data = logger.rangeData( @@ -2705,21 +2688,13 @@ pub const VirtualMachine = struct { } } - if (JSC.HardcodedModule.Aliases.getWithEql(specifier, bun.String.eqlComptime, jsc_vm.transpiler.options.target)) |hardcoded| { - // if (hardcoded.tag == .none) { - // resolveMaybeNeedsTrailingSlash( - // res, - // global, - // bun.String.init(hardcoded.path), - // source, - // query_string, - // is_esm, - // is_a_file_path, - // ); - // return; - // } - - res.* = ErrorableString.ok(bun.String.init(hardcoded.path)); + if (JSC.HardcodedModule.Alias.get(specifier_utf8.slice(), .bun)) |hardcoded| { + res.* = ErrorableString.ok( + if (is_user_require_resolve and hardcoded.node_builtin) + specifier + else + bun.String.init(hardcoded.path), + ); return; } @@ -2747,12 +2722,20 @@ pub const VirtualMachine = struct { } } - const printed = JSC.ResolveMessage.fmt( + const import_kind: bun.ImportKind = if (is_esm) + .stmt + else if (is_user_require_resolve) + .require_resolve + else + .require; + + const printed = try JSC.ResolveMessage.fmt( jsc_vm.allocator, specifier_utf8.slice(), source_utf8.slice(), err, - ) catch unreachable; + import_kind, + ); break :brk logger.Msg{ .data = logger.rangeData( null, @@ -2760,8 +2743,10 @@ pub const VirtualMachine = struct { printed, ), .metadata = .{ - // import_kind is wrong probably - .resolve = .{ .specifier = logger.BabyString.in(printed, specifier_utf8.slice()), .import_kind = if (is_esm) .stmt else .require }, + .resolve = .{ + .specifier = logger.BabyString.in(printed, specifier_utf8.slice()), + .import_kind = import_kind, + }, }, }; }; diff --git a/src/bun.js/module_loader.zig b/src/bun.js/module_loader.zig index f67f007001..406977066d 100644 --- a/src/bun.js/module_loader.zig +++ b/src/bun.js/module_loader.zig @@ -59,7 +59,6 @@ const JSPromise = bun.JSC.JSPromise; const JSModuleLoader = bun.JSC.JSModuleLoader; const JSPromiseRejectionOperation = bun.JSC.JSPromiseRejectionOperation; const ErrorableZigString = bun.JSC.ErrorableZigString; -const ZigGlobalObject = bun.JSC.ZigGlobalObject; const VM = bun.JSC.VM; const JSFunction = bun.JSC.JSFunction; const Config = @import("./config.zig"); @@ -78,7 +77,7 @@ const String = bun.String; const debug = Output.scoped(.ModuleLoader, true); const panic = std.debug.panic; -inline fn jsSyntheticModule(comptime name: ResolvedSource.Tag, specifier: String) ResolvedSource { +inline fn jsSyntheticModule(name: ResolvedSource.Tag, specifier: String) ResolvedSource { return ResolvedSource{ .allocator = null, .source_code = bun.String.empty, @@ -593,7 +592,7 @@ pub const RuntimeTranspilerStore = struct { for (parse_result.ast.import_records.slice()) |*import_record_| { var import_record: *bun.ImportRecord = import_record_; - if (JSC.HardcodedModule.Aliases.get(import_record.path.text, transpiler.options.target)) |replacement| { + if (JSC.HardcodedModule.Alias.get(import_record.path.text, transpiler.options.target)) |replacement| { import_record.path.text = replacement.path; import_record.tag = replacement.tag; import_record.is_external_without_side_effects = true; @@ -2207,6 +2206,28 @@ pub const ModuleLoader = struct { } } + pub export fn Bun__resolveAndFetchBuiltinModule( + jsc_vm: *VirtualMachine, + specifier: *bun.String, + ret: *JSC.ErrorableResolvedSource, + ) bool { + JSC.markBinding(@src()); + var log = logger.Log.init(jsc_vm.transpiler.allocator); + defer log.deinit(); + + const alias = HardcodedModule.Alias.bun_aliases.getWithEql(specifier.*, bun.String.eqlComptime) orelse + return false; + const hardcoded = HardcodedModule.map.get(alias.path) orelse { + bun.debugAssert(false); + return false; + }; + ret.* = .ok( + getHardcodedModule(jsc_vm, specifier.*, hardcoded) orelse + return false, + ); + return true; + } + pub export fn Bun__fetchBuiltinModule( jsc_vm: *VirtualMachine, globalObject: *JSGlobalObject, @@ -2368,122 +2389,46 @@ pub const ModuleLoader = struct { return JSValue.zero; } - pub fn fetchBuiltinModule(jsc_vm: *VirtualMachine, specifier: bun.String) !?ResolvedSource { - if (specifier.eqlComptime(Runtime.Runtime.Imports.Name)) { - return ResolvedSource{ + fn getHardcodedModule(jsc_vm: *VirtualMachine, specifier: bun.String, hardcoded: HardcodedModule) ?ResolvedSource { + Analytics.Features.builtin_modules.insert(hardcoded); + return switch (hardcoded) { + .@"bun:main" => .{ + .allocator = null, + .source_code = bun.String.createUTF8(jsc_vm.entry_point.source.contents), + .specifier = specifier, + .source_url = specifier, + .hash = 0, + .tag = .esm, + .source_code_needs_deref = true, + }, + .@"bun:internal-for-testing" => { + if (!Environment.isDebug) { + if (!is_allowed_to_use_internal_testing_apis) + return null; + } + return jsSyntheticModule(.InternalForTesting, specifier); + }, + .@"bun:wrap" => .{ .allocator = null, .source_code = String.init(Runtime.Runtime.sourceCode()), .specifier = specifier, .source_url = specifier, .hash = Runtime.Runtime.versionHash(), - }; - } else if (HardcodedModule.Map.getWithEql(specifier, bun.String.eqlComptime)) |hardcoded| { - Analytics.Features.builtin_modules.insert(hardcoded); + }, + inline else => |tag| jsSyntheticModule(@field(ResolvedSource.Tag, @tagName(tag)), specifier), + }; + } - switch (hardcoded) { - .@"bun:main" => { - return ResolvedSource{ - .allocator = null, - .source_code = bun.String.createUTF8(jsc_vm.entry_point.source.contents), - .specifier = specifier, - .source_url = specifier, - .hash = 0, - .tag = .esm, - .source_code_needs_deref = true, - }; - }, + pub fn fetchBuiltinModule(jsc_vm: *VirtualMachine, specifier: bun.String) !?ResolvedSource { + if (HardcodedModule.map.getWithEql(specifier, bun.String.eqlComptime)) |hardcoded| { + return getHardcodedModule(jsc_vm, specifier, hardcoded); + } - // Native modules - .bun => return jsSyntheticModule(.bun, specifier), - .@"node:buffer" => return jsSyntheticModule(.@"node:buffer", specifier), - .@"node:string_decoder" => return jsSyntheticModule(.@"node:string_decoder", specifier), - .@"node:module" => return jsSyntheticModule(.@"node:module", specifier), - .@"node:process" => return jsSyntheticModule(.@"node:process", specifier), - .@"node:tty" => return jsSyntheticModule(.@"node:tty", specifier), - .@"node:util/types" => return jsSyntheticModule(.@"node:util/types", specifier), - .@"node:constants" => return jsSyntheticModule(.@"node:constants", specifier), - .@"bun:jsc" => return jsSyntheticModule(.@"bun:jsc", specifier), - .@"bun:test" => return jsSyntheticModule(.@"bun:test", specifier), - - .@"bun:internal-for-testing" => { - if (!Environment.isDebug) { - if (!is_allowed_to_use_internal_testing_apis) - return null; - } - - return jsSyntheticModule(.InternalForTesting, specifier); - }, - - // These are defined in src/js/* - .@"bun:ffi" => return jsSyntheticModule(.@"bun:ffi", specifier), - - .@"bun:sqlite" => return jsSyntheticModule(.@"bun:sqlite", specifier), - .@"node:assert" => return jsSyntheticModule(.@"node:assert", specifier), - .@"node:assert/strict" => return jsSyntheticModule(.@"node:assert/strict", specifier), - .@"node:async_hooks" => return jsSyntheticModule(.@"node:async_hooks", specifier), - .@"node:child_process" => return jsSyntheticModule(.@"node:child_process", specifier), - .@"node:cluster" => return jsSyntheticModule(.@"node:cluster", specifier), - .@"node:console" => return jsSyntheticModule(.@"node:console", specifier), - .@"node:crypto" => return jsSyntheticModule(.@"node:crypto", specifier), - .@"node:dgram" => return jsSyntheticModule(.@"node:dgram", specifier), - .@"node:diagnostics_channel" => return jsSyntheticModule(.@"node:diagnostics_channel", specifier), - .@"node:dns" => return jsSyntheticModule(.@"node:dns", specifier), - .@"node:dns/promises" => return jsSyntheticModule(.@"node:dns/promises", specifier), - .@"node:domain" => return jsSyntheticModule(.@"node:domain", specifier), - .@"node:events" => return jsSyntheticModule(.@"node:events", specifier), - .@"node:fs" => return jsSyntheticModule(.@"node:fs", specifier), - .@"node:fs/promises" => return jsSyntheticModule(.@"node:fs/promises", specifier), - .@"node:http" => return jsSyntheticModule(.@"node:http", specifier), - .@"node:http2" => return jsSyntheticModule(.@"node:http2", specifier), - .@"node:https" => return jsSyntheticModule(.@"node:https", specifier), - .@"node:inspector" => return jsSyntheticModule(.@"node:inspector", specifier), - .@"node:net" => return jsSyntheticModule(.@"node:net", specifier), - .@"node:os" => return jsSyntheticModule(.@"node:os", specifier), - .@"node:path" => return jsSyntheticModule(.@"node:path", specifier), - .@"node:path/posix" => return jsSyntheticModule(.@"node:path/posix", specifier), - .@"node:path/win32" => return jsSyntheticModule(.@"node:path/win32", specifier), - .@"node:punycode" => return jsSyntheticModule(.@"node:punycode", specifier), - .@"node:perf_hooks" => return jsSyntheticModule(.@"node:perf_hooks", specifier), - .@"node:querystring" => return jsSyntheticModule(.@"node:querystring", specifier), - .@"node:readline" => return jsSyntheticModule(.@"node:readline", specifier), - .@"node:readline/promises" => return jsSyntheticModule(.@"node:readline/promises", specifier), - .@"node:repl" => return jsSyntheticModule(.@"node:repl", specifier), - .@"node:stream" => return jsSyntheticModule(.@"node:stream", specifier), - .@"node:stream/consumers" => return jsSyntheticModule(.@"node:stream/consumers", specifier), - .@"node:stream/promises" => return jsSyntheticModule(.@"node:stream/promises", specifier), - .@"node:stream/web" => return jsSyntheticModule(.@"node:stream/web", specifier), - .@"node:test" => return jsSyntheticModule(.@"node:test", specifier), - .@"node:timers" => return jsSyntheticModule(.@"node:timers", specifier), - .@"node:timers/promises" => return jsSyntheticModule(.@"node:timers/promises", specifier), - .@"node:tls" => return jsSyntheticModule(.@"node:tls", specifier), - .@"node:trace_events" => return jsSyntheticModule(.@"node:trace_events", specifier), - .@"node:url" => return jsSyntheticModule(.@"node:url", specifier), - .@"node:util" => return jsSyntheticModule(.@"node:util", specifier), - .@"node:v8" => return jsSyntheticModule(.@"node:v8", specifier), - .@"node:vm" => return jsSyntheticModule(.@"node:vm", specifier), - .@"node:wasi" => return jsSyntheticModule(.@"node:wasi", specifier), - .@"node:worker_threads" => return jsSyntheticModule(.@"node:worker_threads", specifier), - .@"node:zlib" => return jsSyntheticModule(.@"node:zlib", specifier), - .@"isomorphic-fetch" => return jsSyntheticModule(.@"isomorphic-fetch", specifier), - .@"node-fetch" => return jsSyntheticModule(.@"node-fetch", specifier), - .@"@vercel/fetch" => return jsSyntheticModule(.vercel_fetch, specifier), - .@"utf-8-validate" => return jsSyntheticModule(.@"utf-8-validate", specifier), - .@"abort-controller" => return jsSyntheticModule(.@"abort-controller", specifier), - .undici => return jsSyntheticModule(.undici, specifier), - .ws => return jsSyntheticModule(.ws, specifier), - .@"node:_stream_duplex" => return jsSyntheticModule(.@"node:_stream_duplex", specifier), - .@"node:_stream_passthrough" => return jsSyntheticModule(.@"node:_stream_passthrough", specifier), - .@"node:_stream_readable" => return jsSyntheticModule(.@"node:_stream_readable", specifier), - .@"node:_stream_transform" => return jsSyntheticModule(.@"node:_stream_transform", specifier), - .@"node:_stream_wrap" => return jsSyntheticModule(.@"node:_stream_wrap", specifier), - .@"node:_stream_writable" => return jsSyntheticModule(.@"node:_stream_writable", specifier), - .@"node:_tls_common" => return jsSyntheticModule(.@"node:_tls_common", specifier), - } - } else if (specifier.hasPrefixComptime(js_ast.Macro.namespaceWithColon)) { + if (specifier.hasPrefixComptime(js_ast.Macro.namespaceWithColon)) { const spec = specifier.toUTF8(bun.default_allocator); defer spec.deinit(); if (jsc_vm.macro_entry_points.get(MacroEntryPoint.generateIDFromSpecifier(spec.slice()))) |entry| { - return ResolvedSource{ + return .{ .allocator = null, .source_code = bun.String.createUTF8(entry.source.contents), .specifier = specifier, @@ -2505,7 +2450,7 @@ pub const ModuleLoader = struct { \\export const __esModule = true; \\export default db; ; - return ResolvedSource{ + return .{ .allocator = null, .source_code = bun.String.static(code), .specifier = specifier, @@ -2515,7 +2460,7 @@ pub const ModuleLoader = struct { }; } - return ResolvedSource{ + return .{ .allocator = null, .source_code = file.toWTFString(), .specifier = specifier, @@ -2624,6 +2569,7 @@ pub const HardcodedModule = enum { @"bun:jsc", @"bun:main", @"bun:test", // usually replaced by the transpiler but `await import("bun:" + "test")` has to work + @"bun:wrap", @"bun:sqlite", @"node:assert", @"node:assert/strict", @@ -2674,9 +2620,8 @@ pub const HardcodedModule = enum { ws, @"isomorphic-fetch", @"node-fetch", - @"@vercel/fetch", + vercel_fetch, @"utf-8-validate", - // These are all not implemented yet, but are stubbed @"node:v8", @"node:trace_events", @"node:repl", @@ -2685,9 +2630,6 @@ pub const HardcodedModule = enum { @"node:diagnostics_channel", @"node:dgram", @"node:cluster", - // these are gated behind '--expose-internals' - @"bun:internal-for-testing", - // @"node:_stream_duplex", @"node:_stream_passthrough", @"node:_stream_readable", @@ -2695,253 +2637,258 @@ pub const HardcodedModule = enum { @"node:_stream_wrap", @"node:_stream_writable", @"node:_tls_common", + /// This is gated behind '--expose-internals' + @"bun:internal-for-testing", - /// Already resolved modules go in here. - /// This does not remap the module name, it is just a hash table. - /// Do not put modules that have aliases in here - /// Put those in Aliases - pub const Map = bun.ComptimeStringMap( - HardcodedModule, - .{ - .{ "bun", HardcodedModule.bun }, - .{ "bun:ffi", HardcodedModule.@"bun:ffi" }, - .{ "bun:jsc", HardcodedModule.@"bun:jsc" }, - .{ "bun:main", HardcodedModule.@"bun:main" }, - .{ "bun:test", HardcodedModule.@"bun:test" }, - .{ "bun:sqlite", HardcodedModule.@"bun:sqlite" }, - .{ "bun:internal-for-testing", HardcodedModule.@"bun:internal-for-testing" }, - .{ "node-fetch", HardcodedModule.@"node-fetch" }, - .{ "isomorphic-fetch", HardcodedModule.@"isomorphic-fetch" }, + /// The module loader first uses `Aliases` to get a single string during + /// resolution, then maps that single string to the actual module. + /// Do not include aliases here; Those go in `Aliases`. + pub const map = bun.ComptimeStringMap(HardcodedModule, [_]struct { []const u8, HardcodedModule }{ + // Bun + .{ "bun", .bun }, + .{ "bun:ffi", .@"bun:ffi" }, + .{ "bun:jsc", .@"bun:jsc" }, + .{ "bun:main", .@"bun:main" }, + .{ "bun:test", .@"bun:test" }, + .{ "bun:sqlite", .@"bun:sqlite" }, + .{ "bun:wrap", .@"bun:wrap" }, + .{ "bun:internal-for-testing", .@"bun:internal-for-testing" }, + // Node.js + .{ "node:assert", .@"node:assert" }, + .{ "node:assert/strict", .@"node:assert/strict" }, + .{ "node:async_hooks", .@"node:async_hooks" }, + .{ "node:buffer", .@"node:buffer" }, + .{ "node:child_process", .@"node:child_process" }, + .{ "node:cluster", .@"node:cluster" }, + .{ "node:console", .@"node:console" }, + .{ "node:constants", .@"node:constants" }, + .{ "node:crypto", .@"node:crypto" }, + .{ "node:dgram", .@"node:dgram" }, + .{ "node:diagnostics_channel", .@"node:diagnostics_channel" }, + .{ "node:dns", .@"node:dns" }, + .{ "node:dns/promises", .@"node:dns/promises" }, + .{ "node:domain", .@"node:domain" }, + .{ "node:events", .@"node:events" }, + .{ "node:fs", .@"node:fs" }, + .{ "node:fs/promises", .@"node:fs/promises" }, + .{ "node:http", .@"node:http" }, + .{ "node:http2", .@"node:http2" }, + .{ "node:https", .@"node:https" }, + .{ "node:inspector", .@"node:inspector" }, + .{ "node:module", .@"node:module" }, + .{ "node:net", .@"node:net" }, + .{ "node:readline", .@"node:readline" }, + .{ "node:test", .@"node:test" }, + .{ "node:os", .@"node:os" }, + .{ "node:path", .@"node:path" }, + .{ "node:path/posix", .@"node:path/posix" }, + .{ "node:path/win32", .@"node:path/win32" }, + .{ "node:perf_hooks", .@"node:perf_hooks" }, + .{ "node:process", .@"node:process" }, + .{ "node:punycode", .@"node:punycode" }, + .{ "node:querystring", .@"node:querystring" }, + .{ "node:readline", .@"node:readline" }, + .{ "node:readline/promises", .@"node:readline/promises" }, + .{ "node:repl", .@"node:repl" }, + .{ "node:stream", .@"node:stream" }, + .{ "node:stream/consumers", .@"node:stream/consumers" }, + .{ "node:stream/promises", .@"node:stream/promises" }, + .{ "node:stream/web", .@"node:stream/web" }, + .{ "node:string_decoder", .@"node:string_decoder" }, + .{ "node:timers", .@"node:timers" }, + .{ "node:timers/promises", .@"node:timers/promises" }, + .{ "node:tls", .@"node:tls" }, + .{ "node:trace_events", .@"node:trace_events" }, + .{ "node:tty", .@"node:tty" }, + .{ "node:url", .@"node:url" }, + .{ "node:util", .@"node:util" }, + .{ "node:util/types", .@"node:util/types" }, + .{ "node:v8", .@"node:v8" }, + .{ "node:vm", .@"node:vm" }, + .{ "node:wasi", .@"node:wasi" }, + .{ "node:worker_threads", .@"node:worker_threads" }, + .{ "node:zlib", .@"node:zlib" }, + .{ "node:_stream_duplex", .@"node:_stream_duplex" }, + .{ "node:_stream_passthrough", .@"node:_stream_passthrough" }, + .{ "node:_stream_readable", .@"node:_stream_readable" }, + .{ "node:_stream_transform", .@"node:_stream_transform" }, + .{ "node:_stream_wrap", .@"node:_stream_wrap" }, + .{ "node:_stream_writable", .@"node:_stream_writable" }, + .{ "node:_tls_common", .@"node:_tls_common" }, - .{ "node:test", HardcodedModule.@"node:test" }, - - .{ "assert", HardcodedModule.@"node:assert" }, - .{ "assert/strict", HardcodedModule.@"node:assert/strict" }, - .{ "async_hooks", HardcodedModule.@"node:async_hooks" }, - .{ "buffer", HardcodedModule.@"node:buffer" }, - .{ "child_process", HardcodedModule.@"node:child_process" }, - .{ "cluster", HardcodedModule.@"node:cluster" }, - .{ "console", HardcodedModule.@"node:console" }, - .{ "constants", HardcodedModule.@"node:constants" }, - .{ "crypto", HardcodedModule.@"node:crypto" }, - .{ "dgram", HardcodedModule.@"node:dgram" }, - .{ "diagnostics_channel", HardcodedModule.@"node:diagnostics_channel" }, - .{ "dns", HardcodedModule.@"node:dns" }, - .{ "dns/promises", HardcodedModule.@"node:dns/promises" }, - .{ "domain", HardcodedModule.@"node:domain" }, - .{ "events", HardcodedModule.@"node:events" }, - .{ "fs", HardcodedModule.@"node:fs" }, - .{ "fs/promises", HardcodedModule.@"node:fs/promises" }, - .{ "http", HardcodedModule.@"node:http" }, - .{ "http2", HardcodedModule.@"node:http2" }, - .{ "https", HardcodedModule.@"node:https" }, - .{ "inspector", HardcodedModule.@"node:inspector" }, - .{ "module", HardcodedModule.@"node:module" }, - .{ "net", HardcodedModule.@"node:net" }, - .{ "os", HardcodedModule.@"node:os" }, - .{ "path", HardcodedModule.@"node:path" }, - .{ "path/posix", HardcodedModule.@"node:path/posix" }, - .{ "path/win32", HardcodedModule.@"node:path/win32" }, - .{ "punycode", HardcodedModule.@"node:punycode" }, - .{ "perf_hooks", HardcodedModule.@"node:perf_hooks" }, - .{ "process", HardcodedModule.@"node:process" }, - .{ "querystring", HardcodedModule.@"node:querystring" }, - .{ "node:readline", HardcodedModule.@"node:readline" }, - .{ "readline", HardcodedModule.@"node:readline" }, - .{ "readline/promises", HardcodedModule.@"node:readline/promises" }, - .{ "repl", HardcodedModule.@"node:repl" }, - .{ "stream", HardcodedModule.@"node:stream" }, - .{ "stream/consumers", HardcodedModule.@"node:stream/consumers" }, - .{ "stream/promises", HardcodedModule.@"node:stream/promises" }, - .{ "stream/web", HardcodedModule.@"node:stream/web" }, - .{ "string_decoder", HardcodedModule.@"node:string_decoder" }, - .{ "timers", HardcodedModule.@"node:timers" }, - .{ "timers/promises", HardcodedModule.@"node:timers/promises" }, - .{ "tls", HardcodedModule.@"node:tls" }, - .{ "trace_events", HardcodedModule.@"node:trace_events" }, - .{ "tty", HardcodedModule.@"node:tty" }, - .{ "url", HardcodedModule.@"node:url" }, - .{ "util", HardcodedModule.@"node:util" }, - .{ "util/types", HardcodedModule.@"node:util/types" }, - .{ "v8", HardcodedModule.@"node:v8" }, - .{ "vm", HardcodedModule.@"node:vm" }, - .{ "wasi", HardcodedModule.@"node:wasi" }, - .{ "worker_threads", HardcodedModule.@"node:worker_threads" }, - .{ "zlib", HardcodedModule.@"node:zlib" }, - - .{ "_stream_duplex", .@"node:_stream_duplex" }, - .{ "_stream_passthrough", .@"node:_stream_passthrough" }, - .{ "_stream_readable", .@"node:_stream_readable" }, - .{ "_stream_transform", .@"node:_stream_transform" }, - .{ "_stream_wrap", .@"node:_stream_wrap" }, - .{ "_stream_writable", .@"node:_stream_writable" }, - .{ "_tls_common", .@"node:_tls_common" }, - - .{ "undici", HardcodedModule.undici }, - .{ "ws", HardcodedModule.ws }, - .{ "@vercel/fetch", HardcodedModule.@"@vercel/fetch" }, - .{ "utf-8-validate", HardcodedModule.@"utf-8-validate" }, - .{ "abort-controller", HardcodedModule.@"abort-controller" }, - }, - ); + .{ "node-fetch", HardcodedModule.@"node-fetch" }, + .{ "isomorphic-fetch", HardcodedModule.@"isomorphic-fetch" }, + .{ "undici", HardcodedModule.undici }, + .{ "ws", HardcodedModule.ws }, + .{ "@vercel/fetch", HardcodedModule.vercel_fetch }, + .{ "utf-8-validate", HardcodedModule.@"utf-8-validate" }, + .{ "abort-controller", HardcodedModule.@"abort-controller" }, + }); + /// Contains the list of built-in modules from the perspective of the module + /// loader. This logic is duplicated for `isBuiltinModule` and the like. pub const Alias = struct { path: [:0]const u8, tag: ImportRecord.Tag = .builtin, - }; + node_builtin: bool = false, - pub const Aliases = struct { - // Used by both Bun and Node. + fn nodeEntry(path: [:0]const u8) struct { string, Alias } { + return .{ + path, + .{ + .path = if (path.len > 5 and std.mem.eql(u8, path[0..5], "node:")) path else "node:" ++ path, + .node_builtin = true, + }, + }; + } + fn entry(path: [:0]const u8) struct { string, Alias } { + return .{ path, .{ .path = path } }; + } + + // Applied to both --target=bun and --target=node const common_alias_kvs = [_]struct { string, Alias }{ - .{ "node:assert", .{ .path = "assert" } }, - .{ "node:assert/strict", .{ .path = "assert/strict" } }, - .{ "node:async_hooks", .{ .path = "async_hooks" } }, - .{ "node:buffer", .{ .path = "buffer" } }, - .{ "node:child_process", .{ .path = "child_process" } }, - .{ "node:cluster", .{ .path = "cluster" } }, - .{ "node:console", .{ .path = "console" } }, - .{ "node:constants", .{ .path = "constants" } }, - .{ "node:crypto", .{ .path = "crypto" } }, - .{ "node:dgram", .{ .path = "dgram" } }, - .{ "node:diagnostics_channel", .{ .path = "diagnostics_channel" } }, - .{ "node:dns", .{ .path = "dns" } }, - .{ "node:dns/promises", .{ .path = "dns/promises" } }, - .{ "node:domain", .{ .path = "domain" } }, - .{ "node:events", .{ .path = "events" } }, - .{ "node:fs", .{ .path = "fs" } }, - .{ "node:fs/promises", .{ .path = "fs/promises" } }, - .{ "node:http", .{ .path = "http" } }, - .{ "node:http2", .{ .path = "http2" } }, - .{ "node:https", .{ .path = "https" } }, - .{ "node:inspector", .{ .path = "inspector" } }, - .{ "node:module", .{ .path = "module" } }, - .{ "node:net", .{ .path = "net" } }, - .{ "node:os", .{ .path = "os" } }, - .{ "node:path", .{ .path = "path" } }, - .{ "node:path/posix", .{ .path = "path/posix" } }, - .{ "node:path/win32", .{ .path = "path/win32" } }, - .{ "node:perf_hooks", .{ .path = "perf_hooks" } }, - .{ "node:process", .{ .path = "process" } }, - .{ "node:punycode", .{ .path = "punycode" } }, - .{ "node:querystring", .{ .path = "querystring" } }, - .{ "node:readline", .{ .path = "readline" } }, - .{ "node:readline/promises", .{ .path = "readline/promises" } }, - .{ "node:repl", .{ .path = "repl" } }, - .{ "node:stream", .{ .path = "stream" } }, - .{ "node:stream/consumers", .{ .path = "stream/consumers" } }, - .{ "node:stream/promises", .{ .path = "stream/promises" } }, - .{ "node:stream/web", .{ .path = "stream/web" } }, - .{ "node:string_decoder", .{ .path = "string_decoder" } }, - .{ "node:test", .{ .path = "node:test" } }, - .{ "node:timers", .{ .path = "timers" } }, - .{ "node:timers/promises", .{ .path = "timers/promises" } }, - .{ "node:tls", .{ .path = "tls" } }, - .{ "node:trace_events", .{ .path = "trace_events" } }, - .{ "node:tty", .{ .path = "tty" } }, - .{ "node:url", .{ .path = "url" } }, - .{ "node:util", .{ .path = "util" } }, - .{ "node:util/types", .{ .path = "util/types" } }, - .{ "node:v8", .{ .path = "v8" } }, - .{ "node:vm", .{ .path = "vm" } }, - .{ "node:wasi", .{ .path = "wasi" } }, - .{ "node:worker_threads", .{ .path = "worker_threads" } }, - .{ "node:zlib", .{ .path = "zlib" } }, + nodeEntry("node:assert"), + nodeEntry("node:assert/strict"), + nodeEntry("node:async_hooks"), + nodeEntry("node:buffer"), + nodeEntry("node:child_process"), + nodeEntry("node:cluster"), + nodeEntry("node:console"), + nodeEntry("node:constants"), + nodeEntry("node:crypto"), + nodeEntry("node:dgram"), + nodeEntry("node:diagnostics_channel"), + nodeEntry("node:dns"), + nodeEntry("node:dns/promises"), + nodeEntry("node:domain"), + nodeEntry("node:events"), + nodeEntry("node:fs"), + nodeEntry("node:fs/promises"), + nodeEntry("node:http"), + nodeEntry("node:http2"), + nodeEntry("node:https"), + nodeEntry("node:inspector"), + nodeEntry("node:module"), + nodeEntry("node:net"), + nodeEntry("node:os"), + nodeEntry("node:path"), + nodeEntry("node:path/posix"), + nodeEntry("node:path/win32"), + nodeEntry("node:perf_hooks"), + nodeEntry("node:process"), + nodeEntry("node:punycode"), + nodeEntry("node:querystring"), + nodeEntry("node:readline"), + nodeEntry("node:readline/promises"), + nodeEntry("node:repl"), + nodeEntry("node:stream"), + nodeEntry("node:stream/consumers"), + nodeEntry("node:stream/promises"), + nodeEntry("node:stream/web"), + nodeEntry("node:string_decoder"), + nodeEntry("node:timers"), + nodeEntry("node:timers/promises"), + nodeEntry("node:tls"), + nodeEntry("node:trace_events"), + nodeEntry("node:tty"), + nodeEntry("node:url"), + nodeEntry("node:util"), + nodeEntry("node:util/types"), + nodeEntry("node:v8"), + nodeEntry("node:vm"), + nodeEntry("node:wasi"), + nodeEntry("node:worker_threads"), + nodeEntry("node:zlib"), + // New Node.js builtins only resolve from the prefixed one. + nodeEntry("node:test"), - // These are returned in builtinModules, but probably not many packages use them so we will just alias them. - .{ "node:_http_agent", .{ .path = "http" } }, - .{ "node:_http_client", .{ .path = "http" } }, - .{ "node:_http_common", .{ .path = "http" } }, - .{ "node:_http_incoming", .{ .path = "http" } }, - .{ "node:_http_outgoing", .{ .path = "http" } }, - .{ "node:_http_server", .{ .path = "http" } }, - .{ "node:_stream_duplex", .{ .path = "_stream_duplex" } }, - .{ "node:_stream_passthrough", .{ .path = "_stream_passthrough" } }, - .{ "node:_stream_readable", .{ .path = "_stream_readable" } }, - .{ "node:_stream_transform", .{ .path = "_stream_transform" } }, - .{ "node:_stream_wrap", .{ .path = "_stream_wrap" } }, - .{ "node:_stream_writable", .{ .path = "_stream_writable" } }, - .{ "node:_tls_wrap", .{ .path = "tls" } }, - .{ "node:_tls_common", .{ .path = "_tls_common" } }, + nodeEntry("assert"), + nodeEntry("assert/strict"), + nodeEntry("async_hooks"), + nodeEntry("buffer"), + nodeEntry("child_process"), + nodeEntry("cluster"), + nodeEntry("console"), + nodeEntry("constants"), + nodeEntry("crypto"), + nodeEntry("dgram"), + nodeEntry("diagnostics_channel"), + nodeEntry("dns"), + nodeEntry("dns/promises"), + nodeEntry("domain"), + nodeEntry("events"), + nodeEntry("fs"), + nodeEntry("fs/promises"), + nodeEntry("http"), + nodeEntry("http2"), + nodeEntry("https"), + nodeEntry("inspector"), + nodeEntry("module"), + nodeEntry("net"), + nodeEntry("os"), + nodeEntry("path"), + nodeEntry("path/posix"), + nodeEntry("path/win32"), + nodeEntry("perf_hooks"), + nodeEntry("process"), + nodeEntry("punycode"), + nodeEntry("querystring"), + nodeEntry("readline"), + nodeEntry("readline/promises"), + nodeEntry("repl"), + nodeEntry("stream"), + nodeEntry("stream/consumers"), + nodeEntry("stream/promises"), + nodeEntry("stream/web"), + nodeEntry("string_decoder"), + nodeEntry("timers"), + nodeEntry("timers/promises"), + nodeEntry("tls"), + nodeEntry("trace_events"), + nodeEntry("tty"), + nodeEntry("url"), + nodeEntry("util"), + nodeEntry("util/types"), + nodeEntry("v8"), + nodeEntry("vm"), + nodeEntry("wasi"), + nodeEntry("worker_threads"), + nodeEntry("zlib"), - .{ "assert", .{ .path = "assert" } }, - .{ "assert/strict", .{ .path = "assert/strict" } }, - .{ "async_hooks", .{ .path = "async_hooks" } }, - .{ "buffer", .{ .path = "buffer" } }, - .{ "child_process", .{ .path = "child_process" } }, - .{ "cluster", .{ .path = "cluster" } }, - .{ "console", .{ .path = "console" } }, - .{ "constants", .{ .path = "constants" } }, - .{ "crypto", .{ .path = "crypto" } }, - .{ "dgram", .{ .path = "dgram" } }, - .{ "diagnostics_channel", .{ .path = "diagnostics_channel" } }, - .{ "dns", .{ .path = "dns" } }, - .{ "dns/promises", .{ .path = "dns/promises" } }, - .{ "domain", .{ .path = "domain" } }, - .{ "events", .{ .path = "events" } }, - .{ "fs", .{ .path = "fs" } }, - .{ "fs/promises", .{ .path = "fs/promises" } }, - .{ "http", .{ .path = "http" } }, - .{ "http2", .{ .path = "http2" } }, - .{ "https", .{ .path = "https" } }, - .{ "inspector", .{ .path = "inspector" } }, - .{ "module", .{ .path = "module" } }, - .{ "net", .{ .path = "net" } }, - .{ "os", .{ .path = "os" } }, - .{ "path", .{ .path = "path" } }, - .{ "path/posix", .{ .path = "path/posix" } }, - .{ "path/win32", .{ .path = "path/win32" } }, - .{ "perf_hooks", .{ .path = "perf_hooks" } }, - .{ "process", .{ .path = "process" } }, - .{ "punycode", .{ .path = "punycode" } }, - .{ "querystring", .{ .path = "querystring" } }, - .{ "readline", .{ .path = "readline" } }, - .{ "readline/promises", .{ .path = "readline/promises" } }, - .{ "repl", .{ .path = "repl" } }, - .{ "stream", .{ .path = "stream" } }, - .{ "stream/consumers", .{ .path = "stream/consumers" } }, - .{ "stream/promises", .{ .path = "stream/promises" } }, - .{ "stream/web", .{ .path = "stream/web" } }, - .{ "string_decoder", .{ .path = "string_decoder" } }, - // Node.js does not support "test", only "node:test" - // .{ "test", .{ .path = "node:test" } }, - .{ "timers", .{ .path = "timers" } }, - .{ "timers/promises", .{ .path = "timers/promises" } }, - .{ "tls", .{ .path = "tls" } }, - .{ "trace_events", .{ .path = "trace_events" } }, - .{ "tty", .{ .path = "tty" } }, - .{ "url", .{ .path = "url" } }, - .{ "util", .{ .path = "util" } }, - .{ "util/types", .{ .path = "util/types" } }, - .{ "v8", .{ .path = "v8" } }, - .{ "vm", .{ .path = "vm" } }, - .{ "wasi", .{ .path = "wasi" } }, - .{ "worker_threads", .{ .path = "worker_threads" } }, - .{ "zlib", .{ .path = "zlib" } }, + // sys is a deprecated alias for util + .{ "sys", .{ .path = "node:util", .node_builtin = true } }, + .{ "node:sys", .{ .path = "node:util", .node_builtin = true } }, - // It implements the same interface - .{ "sys", .{ .path = "util" } }, - .{ "node:sys", .{ .path = "util" } }, - - // These are returned in builtinModules, but probably not many packages use them - // so we will just alias them. - .{ "_http_agent", .{ .path = "http" } }, - .{ "_http_client", .{ .path = "http" } }, - .{ "_http_common", .{ .path = "http" } }, - .{ "_http_incoming", .{ .path = "http" } }, - .{ "_http_outgoing", .{ .path = "http" } }, - .{ "_http_server", .{ .path = "http" } }, - .{ "_stream_duplex", .{ .path = "_stream_duplex" } }, - .{ "_stream_passthrough", .{ .path = "_stream_passthrough" } }, - .{ "_stream_readable", .{ .path = "_stream_readable" } }, - .{ "_stream_transform", .{ .path = "_stream_transform" } }, - .{ "_stream_wrap", .{ .path = "_stream_wrap" } }, - .{ "_stream_writable", .{ .path = "_stream_writable" } }, - .{ "_tls_wrap", .{ .path = "tls" } }, - .{ "_tls_common", .{ .path = "_tls_common" } }, - - .{ "next/dist/compiled/ws", .{ .path = "ws" } }, - .{ "next/dist/compiled/node-fetch", .{ .path = "node-fetch" } }, - .{ "next/dist/compiled/undici", .{ .path = "undici" } }, + // These are returned in builtinModules, but probably not many + // packages use them so we will just alias them. + .{ "node:_http_agent", .{ .path = "node:http", .node_builtin = true } }, + .{ "node:_http_client", .{ .path = "node:http", .node_builtin = true } }, + .{ "node:_http_common", .{ .path = "node:http", .node_builtin = true } }, + .{ "node:_http_incoming", .{ .path = "node:http", .node_builtin = true } }, + .{ "node:_http_outgoing", .{ .path = "node:http", .node_builtin = true } }, + .{ "node:_http_server", .{ .path = "node:http", .node_builtin = true } }, + .{ "node:_stream_duplex", .{ .path = "node:_stream_duplex", .node_builtin = true } }, + .{ "node:_stream_passthrough", .{ .path = "node:_stream_passthrough", .node_builtin = true } }, + .{ "node:_stream_readable", .{ .path = "node:_stream_readable", .node_builtin = true } }, + .{ "node:_stream_transform", .{ .path = "node:_stream_transform", .node_builtin = true } }, + .{ "node:_stream_wrap", .{ .path = "node:_stream_wrap", .node_builtin = true } }, + .{ "node:_stream_writable", .{ .path = "node:_stream_writable", .node_builtin = true } }, + .{ "node:_tls_wrap", .{ .path = "node:tls", .node_builtin = true } }, + .{ "node:_tls_common", .{ .path = "node:_tls_common", .node_builtin = true } }, + .{ "_http_agent", .{ .path = "node:http", .node_builtin = true } }, + .{ "_http_client", .{ .path = "node:http", .node_builtin = true } }, + .{ "_http_common", .{ .path = "node:http", .node_builtin = true } }, + .{ "_http_incoming", .{ .path = "node:http", .node_builtin = true } }, + .{ "_http_outgoing", .{ .path = "node:http", .node_builtin = true } }, + .{ "_http_server", .{ .path = "node:http", .node_builtin = true } }, + .{ "_stream_duplex", .{ .path = "node:_stream_duplex", .node_builtin = true } }, + .{ "_stream_passthrough", .{ .path = "node:_stream_passthrough", .node_builtin = true } }, + .{ "_stream_readable", .{ .path = "node:_stream_readable", .node_builtin = true } }, + .{ "_stream_transform", .{ .path = "node:_stream_transform", .node_builtin = true } }, + .{ "_stream_wrap", .{ .path = "node:_stream_wrap", .node_builtin = true } }, + .{ "_stream_writable", .{ .path = "node:_stream_writable", .node_builtin = true } }, + .{ "_tls_wrap", .{ .path = "node:tls", .node_builtin = true } }, + .{ "_tls_common", .{ .path = "node:_tls_common", .node_builtin = true } }, }; const bun_extra_alias_kvs = [_]struct { string, Alias }{ @@ -2954,6 +2901,10 @@ pub const HardcodedModule = enum { .{ "bun:internal-for-testing", .{ .path = "bun:internal-for-testing" } }, .{ "ffi", .{ .path = "bun:ffi" } }, + // inspector/promises is not implemented, it is an alias of inspector + .{ "node:inspector/promises", .{ .path = "node:inspector", .node_builtin = true } }, + .{ "inspector/promises", .{ .path = "node:inspector", .node_builtin = true } }, + // Thirdparty packages we override .{ "@vercel/fetch", .{ .path = "@vercel/fetch" } }, .{ "isomorphic-fetch", .{ .path = "isomorphic-fetch" } }, @@ -2963,45 +2914,33 @@ pub const HardcodedModule = enum { .{ "ws", .{ .path = "ws" } }, .{ "ws/lib/websocket", .{ .path = "ws" } }, - .{ "inspector/promises", .{ .path = "inspector" } }, - .{ "node:inspector/promises", .{ .path = "inspector" } }, - // Polyfills we force to native .{ "abort-controller", .{ .path = "abort-controller" } }, .{ "abort-controller/polyfill", .{ .path = "abort-controller" } }, + + // To force Next.js to not use bundled dependencies. + .{ "next/dist/compiled/ws", .{ .path = "ws" } }, + .{ "next/dist/compiled/node-fetch", .{ .path = "node-fetch" } }, + .{ "next/dist/compiled/undici", .{ .path = "undici" } }, }; - const node_alias_kvs = [_]struct { string, Alias }{ - .{ "inspector/promises", .{ .path = "inspector/promises" } }, - .{ "node:inspector/promises", .{ .path = "inspector/promises" } }, + const node_extra_alias_kvs = [_]struct { string, Alias }{ + nodeEntry("node:inspector/promises"), + nodeEntry("inspector/promises"), }; - const NodeAliases = bun.ComptimeStringMap(Alias, common_alias_kvs ++ node_alias_kvs); - const BunAliases = bun.ComptimeStringMap(Alias, common_alias_kvs ++ bun_extra_alias_kvs); + const node_aliases = bun.ComptimeStringMap(Alias, common_alias_kvs ++ node_extra_alias_kvs); + const bun_aliases = bun.ComptimeStringMap(Alias, common_alias_kvs ++ bun_extra_alias_kvs); pub fn has(name: []const u8, target: options.Target) bool { - if (target.isBun()) { - return BunAliases.has(name); - } else if (target.isNode()) { - return NodeAliases.has(name); - } - return false; + return get(name, target) != null; } pub fn get(name: []const u8, target: options.Target) ?Alias { if (target.isBun()) { - return BunAliases.get(name); + return bun_aliases.get(name); } else if (target.isNode()) { - return NodeAliases.get(name); - } - return null; - } - - pub fn getWithEql(name: anytype, comptime eql: anytype, target: options.Target) ?Alias { - if (target.isBun()) { - return BunAliases.getWithEql(name, eql); - } else if (target.isNode()) { - return NodeAliases.getWithEql(name, eql); + return node_aliases.get(name); } return null; } @@ -3021,5 +2960,5 @@ export fn Bun__resolveEmbeddedNodeFile(vm: *VirtualMachine, in_out_str: *bun.Str export fn ModuleLoader__isBuiltin(data: [*]const u8, len: usize) bool { const str = data[0..len]; - return HardcodedModule.Map.get(str) != null; + return HardcodedModule.map.get(str) != null; } diff --git a/src/bun.js/modules/NodeModuleModule.cpp b/src/bun.js/modules/NodeModuleModule.cpp index b6ad3037e1..2f8cf33b4a 100644 --- a/src/bun.js/modules/NodeModuleModule.cpp +++ b/src/bun.js/modules/NodeModuleModule.cpp @@ -334,7 +334,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionResolveFileName, if ( // fast path: it's a real CommonJS module object. auto* cjs = jsDynamicCast(fromValue)) { - fromValue = cjs->id(); + fromValue = cjs->filename(); } else if // slow path: userland code did something weird. lets let them do that // weird thing. @@ -349,7 +349,11 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionResolveFileName, } auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); - auto result = Bun__resolveSync(globalObject, JSC::JSValue::encode(moduleName), JSValue::encode(fromValue), false); + auto result = Bun__resolveSync( + globalObject, + JSC::JSValue::encode(moduleName), JSValue::encode(fromValue), + false, + true); RETURN_IF_EXCEPTION(scope, {}); if (!JSC::JSValue::decode(result).isString()) { @@ -393,7 +397,7 @@ JSC_DEFINE_CUSTOM_SETTER(setNodeModuleResolveFilename, } } } - globalObject->hasOverridenModuleResolveFilenameFunction = !isOriginal; + globalObject->hasOverriddenModuleResolveFilenameFunction = !isOriginal; globalObject->m_moduleResolveFilenameFunction.set( lexicalGlobalObject->vm(), globalObject, value.asCell()); } @@ -628,6 +632,74 @@ static JSValue getGlobalPathsObject(VM& vm, JSObject* moduleObject) static_cast(nullptr), 0); } +JSC_DEFINE_HOST_FUNCTION(jsFunctionSetCJSWrapperItem, (JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ + auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); + JSValue a = callFrame->argument(0); + JSValue b = callFrame->argument(1); + Zig::GlobalObject* global = defaultGlobalObject(globalObject); + String aString = a.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + String bString = b.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + global->m_moduleWrapperStart = aString; + global->m_moduleWrapperEnd = bString; + global->hasOverriddenModuleWrapper = true; + return JSC::JSValue::encode(JSC::jsUndefined()); +} + +JSC_DEFINE_CUSTOM_GETTER(nodeModuleWrapper, + (JSGlobalObject * global, + EncodedJSValue thisValue, + PropertyName propertyName)) +{ + // This does not cache anything because it is assumed nobody reads it more than once. + VM& vm = global->vm(); + JSC::JSFunction* cb = JSC::JSFunction::create(vm, global, WebCore::moduleGetWrapperArrayProxyCodeGenerator(vm), global); + JSC::CallData callData = JSC::getCallData(cb); + + JSC::MarkedArgumentBuffer args; + args.append(JSFunction::create( + vm, global, 1, "onMutate"_s, + jsFunctionSetCJSWrapperItem, JSC::ImplementationVisibility::Public, + JSC::NoIntrinsic)); + + NakedPtr returnedException = nullptr; + auto result = JSC::profiledCall(global, JSC::ProfilingReason::API, cb, callData, JSC::jsUndefined(), args, returnedException); + ASSERT(!returnedException); + ASSERT(result.isCell()); + return JSC::JSValue::encode(result); +} + +JSC_DEFINE_CUSTOM_SETTER(setNodeModuleWrapper, + (JSGlobalObject * lexicalGlobalObject, + EncodedJSValue thisValue, EncodedJSValue encodedValue, + PropertyName propertyName)) +{ + auto v = JSValue::decode(encodedValue); + if (!v.isObject()) return false; + auto o = v.getObject(); + if (!o) return false; + + auto* globalObject = defaultGlobalObject(lexicalGlobalObject); + + auto scope = DECLARE_THROW_SCOPE(lexicalGlobalObject->vm()); + auto a = o->getIndex(globalObject, 0); + RETURN_IF_EXCEPTION(scope, false); + auto b = o->getIndex(globalObject, 1); + RETURN_IF_EXCEPTION(scope, false); + auto astring = a.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, false); + auto bstring = b.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, false); + + globalObject->m_moduleWrapperStart = astring; + globalObject->m_moduleWrapperEnd = bstring; + globalObject->hasOverriddenModuleWrapper = true; + + return true; +} + JSC_DEFINE_HOST_FUNCTION(jsFunctionInitPaths, (JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { return JSC::JSValue::encode(JSC::jsUndefined()); @@ -723,6 +795,7 @@ runMain jsFunctionRunMain Function 0 SourceMap getSourceMapFunction PropertyCallback syncBuiltinESMExports jsFunctionSyncBuiltinESMExports Function 0 wrap jsFunctionWrap Function 1 +wrapper nodeModuleWrapper CustomAccessor Module getModuleObject PropertyCallback @end */ @@ -809,7 +882,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionIsModuleResolveFilenameSlowPathEnabled, { return JSValue::encode( jsBoolean(defaultGlobalObject(globalObject) - ->hasOverridenModuleResolveFilenameFunction)); + ->hasOverriddenModuleResolveFilenameFunction)); } } // namespace Bun @@ -835,6 +908,9 @@ void generateNativeModule_NodeModule(JSC::JSGlobalObject* lexicalGlobalObject, exportNames.reserveCapacity(Bun::countof(Bun::nodeModuleObjectTableValues) + 1); exportValues.ensureCapacity(Bun::countof(Bun::nodeModuleObjectTableValues) + 1); + exportNames.append(vm.propertyNames->defaultKeyword); + exportValues.append(constructor); + for (unsigned i = 0; i < Bun::countof(Bun::nodeModuleObjectTableValues); ++i) { const auto& entry = Bun::nodeModuleObjectTableValues[i]; @@ -852,9 +928,6 @@ void generateNativeModule_NodeModule(JSC::JSGlobalObject* lexicalGlobalObject, exportNames.append(property); exportValues.append(value); } - - exportNames.append(vm.propertyNames->defaultKeyword); - exportValues.append(constructor); } } // namespace Zig diff --git a/src/bun.js/modules/ObjectModule.cpp b/src/bun.js/modules/ObjectModule.cpp index f4c363d43e..fa37494a80 100644 --- a/src/bun.js/modules/ObjectModule.cpp +++ b/src/bun.js/modules/ObjectModule.cpp @@ -54,6 +54,9 @@ generateObjectModuleSourceCodeForJSON(JSC::JSGlobalObject* globalObject, DontEnumPropertiesMode::Exclude); gcUnprotectNullTolerant(object); + exportNames.append(vm.propertyNames->defaultKeyword); + exportValues.append(object); + for (auto& entry : properties) { if (entry == vm.propertyNames->defaultKeyword) { continue; @@ -69,9 +72,6 @@ generateObjectModuleSourceCodeForJSON(JSC::JSGlobalObject* globalObject, } exportValues.append(value); } - - exportNames.append(vm.propertyNames->defaultKeyword); - exportValues.append(object); }; } diff --git a/src/bun.js/modules/_NativeModule.h b/src/bun.js/modules/_NativeModule.h index 7b9e89cb3e..8894318ede 100644 --- a/src/bun.js/modules/_NativeModule.h +++ b/src/bun.js/modules/_NativeModule.h @@ -106,3 +106,11 @@ while (0) { \ } +namespace Zig { +#define FORWARD_DECL_GENERATOR(id, enumName) \ +void generateNativeModule_##enumName( \ + JSC::JSGlobalObject *lexicalGlobalObject, JSC::Identifier moduleKey, \ + Vector &exportNames, \ + JSC::MarkedArgumentBuffer &exportValues); +BUN_FOREACH_ESM_NATIVE_MODULE(FORWARD_DECL_GENERATOR) +} // namespace Zig \ No newline at end of file diff --git a/src/bundler/bundle_v2.zig b/src/bundler/bundle_v2.zig index 026d1df6fe..eb61fe62a7 100644 --- a/src/bundler/bundle_v2.zig +++ b/src/bundler/bundle_v2.zig @@ -1644,10 +1644,9 @@ pub const BundleV2 = struct { const path = record.path.text; // External dependency if (path.len > 0 and - // Check for either node or bun builtins // We don't use the list from .bun because that includes third-party packages in some cases. - !JSC.HardcodedModule.Aliases.has(path, .node) and + !JSC.HardcodedModule.Alias.has(path, .node) and !strings.hasPrefixComptime(path, "bun:") and !strings.eqlComptime(path, "bun")) { @@ -3006,7 +3005,7 @@ pub const BundleV2 = struct { } if (ast.target.isBun()) { - if (JSC.HardcodedModule.Aliases.get(import_record.path.text, options.Target.bun)) |replacement| { + if (JSC.HardcodedModule.Alias.get(import_record.path.text, .bun)) |replacement| { import_record.path.text = replacement.path; import_record.tag = replacement.tag; import_record.source_index = Index.invalid; @@ -16002,7 +16001,7 @@ pub const LinkerContext = struct { // "undefined" instead of emitting an error. symbol.import_item_status = .missing; - if (c.resolver.opts.target == .browser and JSC.HardcodedModule.Aliases.has(next_source.path.pretty, .bun)) { + if (c.resolver.opts.target == .browser and JSC.HardcodedModule.Alias.has(next_source.path.pretty, .bun)) { c.log.addRangeWarningFmtWithNote( source, r, diff --git a/src/codegen/bundle-modules.ts b/src/codegen/bundle-modules.ts index 73979226eb..577c93b23a 100644 --- a/src/codegen/bundle-modules.ts +++ b/src/codegen/bundle-modules.ts @@ -52,7 +52,7 @@ function markVerbose(log: string) { const mark = silent ? (log: string) => {} : markVerbose; -const { moduleList, nativeModuleIds, nativeModuleEnumToId, nativeModuleEnums, requireTransformer } = +const { moduleList, nativeModuleIds, nativeModuleEnumToId, nativeModuleEnums, requireTransformer, nativeStartIndex } = createInternalModuleRegistry(BASE); globalThis.requireTransformer = requireTransformer; @@ -78,7 +78,7 @@ async function retry(n, fn) { // Preprocess builtins const bundledEntryPoints: string[] = []; -for (let i = 0; i < moduleList.length; i++) { +for (let i = 0; i < nativeStartIndex; i++) { try { let input = fs.readFileSync(path.join(BASE, moduleList[i]), "utf8"); @@ -295,7 +295,9 @@ mark("Bundle Functions"); // This is a file with a single macro that is used in defining InternalModuleRegistry.h writeIfNotChanged( path.join(CODEGEN_DIR, "InternalModuleRegistry+numberOfModules.h"), - `#define BUN_INTERNAL_MODULE_COUNT ${moduleList.length}\n`, + `#define BUN_INTERNAL_MODULE_COUNT ${moduleList.length} +#define BUN_NATIVE_MODULE_START_INDEX ${nativeStartIndex} +`, ); // This code slice is used in InternalModuleRegistry.h for inlining the enum. I dont think we @@ -322,12 +324,15 @@ JSValue InternalModuleRegistry::createInternalModuleById(JSGlobalObject* globalO // JS internal modules ${moduleList .map((id, n) => { - return `case Field::${idToEnumName(id)}: { - INTERNAL_MODULE_REGISTRY_GENERATE(globalObject, vm, "${idToPublicSpecifierOrEnumName(id)}"_s, ${JSON.stringify( + const inner = n >= nativeStartIndex + ? `return generateNativeModule(globalObject, vm, generateNativeModule_${nativeModuleEnums[id]});` + : `INTERNAL_MODULE_REGISTRY_GENERATE(globalObject, vm, "${idToPublicSpecifierOrEnumName(id)}"_s, ${JSON.stringify( id.replace(/\.[mc]?[tj]s$/, ".js"), )}_s, InternalModuleRegistryConstants::${idToEnumName(id)}Code, "builtin://${id .replace(/\.[mc]?[tj]s$/, "") - .replace(/[^a-zA-Z0-9]+/g, "/")}"_s); + .replace(/[^a-zA-Z0-9]+/g, "/")}"_s);` + return `case Field::${idToEnumName(id)}: { + ${inner} }`; }) .join("\n ")} @@ -335,6 +340,7 @@ JSValue InternalModuleRegistry::createInternalModuleById(JSGlobalObject* globalO __builtin_unreachable(); } } + __builtin_unreachable(); } `, ); @@ -353,6 +359,7 @@ if (!debug) { namespace Bun { namespace InternalModuleRegistryConstants { ${moduleList + .slice(0, nativeStartIndex) .map((id, n) => { const out = outputs.get(id.slice(0, -3).replaceAll("/", path.sep)); if (!out) { @@ -373,7 +380,7 @@ namespace InternalModuleRegistryConstants { namespace Bun { namespace InternalModuleRegistryConstants { - ${moduleList.map((id, n) => `${declareASCIILiteral(`${idToEnumName(id)}Code`, "")}`).join("\n")} + ${moduleList.slice(0, nativeStartIndex).map((id, n) => `${declareASCIILiteral(`${idToEnumName(id)}Code`, "")}`).join("\n")} } }`, ); @@ -392,7 +399,7 @@ pub const ResolvedSourceTag = enum(u32) { file = 4, esm = 5, json_for_object_loader = 6, - /// Generate an object with "default" set to all the exports, including a "default" propert + /// Generate an object with "default" set to all the exports, including a "default" property exports_object = 7, /// Generate a module that only exports default the input JSValue @@ -400,10 +407,10 @@ pub const ResolvedSourceTag = enum(u32) { // Built in modules are loaded through InternalModuleRegistry by numerical ID. // In this enum are represented as \`(1 << 9) & id\` -${moduleList.map((id, n) => ` @"${idToPublicSpecifierOrEnumName(id)}" = ${(1 << 9) | n},`).join("\n")} - // Native modules run through a different system using ESM registry. -${Object.entries(nativeModuleIds) - .map(([id, n]) => ` @"${id}" = ${(1 << 10) | n},`) +${moduleList.slice(0, nativeStartIndex).map((id, n) => ` @"${idToPublicSpecifierOrEnumName(id)}" = ${(1 << 9) | n},`).join("\n")} + // Native modules come after the JS modules +${Object.entries(nativeModuleEnumToId) + .map(([id, n], i) => ` @"${moduleList[nativeStartIndex + i]}" = ${(1 << 9) | (n + nativeStartIndex)},`) .join("\n")} }; `, @@ -425,13 +432,10 @@ writeIfNotChanged( // Built in modules are loaded through InternalModuleRegistry by numerical ID. // In this enum are represented as \`(1 << 9) & id\` InternalModuleRegistryFlag = 1 << 9, -${moduleList.map((id, n) => ` ${idToEnumName(id)} = ${(1 << 9) | n},`).join("\n")} - - // Native modules run through the same system, but with different underlying initializers. - // They also have bit 10 set to differentiate them from JS builtins. - NativeModuleFlag = (1 << 10) | (1 << 9), +${moduleList.slice(0, nativeStartIndex).map((id, n) => ` ${idToEnumName(id)} = ${(1 << 9) | n},`).join("\n")} + // Native modules come after the JS modules ${Object.entries(nativeModuleEnumToId) - .map(([id, n]) => ` ${id} = ${(1 << 10) | n},`) + .map(([id, n], i) => ` ${id} = ${(1 << 9) | (i + nativeStartIndex)},`) .join("\n")} }; @@ -476,7 +480,7 @@ declare module "module" { `; - for (let i = 0; i < moduleList.length; i++) { + for (let i = 0; i < nativeStartIndex; i++) { const id = moduleList[i]; const out = outputs.get(id.slice(0, -3).replaceAll("/", path.sep)); if (!out) { @@ -512,12 +516,13 @@ if (!silent) { console.log( ` %s kb`, Math.floor( - (moduleList.reduce((a, b) => a + outputs.get(b.slice(0, -3).replaceAll("/", path.sep)).length, 0) + + (moduleList.slice(0, nativeStartIndex).reduce((a, b) => a + outputs.get(b.slice(0, -3).replaceAll("/", path.sep)).length, 0) + globalThis.internalFunctionJSSize) / 1000, ), ); - console.log(` %s internal modules`, moduleList.length); + console.log(` %s internal modules`, nativeStartIndex); + console.log(` %s native modules`, Object.keys(nativeModuleIds).length); console.log( ` %s internal functions across %s files`, globalThis.internalFunctionCount, diff --git a/src/codegen/generate-node-errors.ts b/src/codegen/generate-node-errors.ts index 0b5cc189a7..801d5754b6 100644 --- a/src/codegen/generate-node-errors.ts +++ b/src/codegen/generate-node-errors.ts @@ -56,7 +56,7 @@ const std = @import("std"); const bun = @import("root").bun; const JSC = bun.JSC; -fn ErrorBuilder(comptime code: Error, comptime fmt: [:0]const u8, Args: type) type { +pub fn ErrorBuilder(comptime code: Error, comptime fmt: [:0]const u8, Args: type) type { return struct { globalThis: *JSC.JSGlobalObject, args: Args, @@ -88,6 +88,7 @@ for (let [code, constructor, name, ...other_constructors] of NodeErrors) { if (name == null) name = constructor.name; enumHeader += ` ${code} = ${i},\n`; listHeader += ` { JSC::ErrorType::${constructor.name}, "${name}"_s, "${code}"_s },\n`; + zig += ` /// ${name}: ${code} (instanceof ${constructor.name})\n`; zig += ` ${code} = ${i},\n`; listForUsingNamespace += ` /// ${name}: ${code} (instanceof ${constructor.name})\n`; listForUsingNamespace += ` pub inline fn ${code}(globalThis: *JSC.JSGlobalObject, comptime fmt: [:0]const u8, args: anytype) ErrorBuilder(Error.${code}, fmt, @TypeOf(args)) {\n`; @@ -100,6 +101,7 @@ for (let [code, constructor, name, ...other_constructors] of NodeErrors) { if (name == null) name = con.name; enumHeader += ` ${code}_${con.name} = ${i},\n`; listHeader += ` { JSC::ErrorType::${con.name}, "${con.name}"_s, "${code}"_s },\n`; + zig += ` /// ${name}: ${code} (instanceof ${con.name})\n`; zig += ` ${code}_${con.name} = ${i},\n`; listForUsingNamespace += ` /// ${name}: ${code} (instanceof ${con.name})\n`; listForUsingNamespace += ` pub inline fn ${code}_${con.name}(globalThis: *JSC.JSGlobalObject, comptime fmt: [:0]const u8, args: anytype) ErrorBuilder(Error.${code}_${con.name}, fmt, @TypeOf(args)) {\n`; diff --git a/src/codegen/internal-module-registry-scanner.ts b/src/codegen/internal-module-registry-scanner.ts index 069b9d70bb..512170ac0e 100644 --- a/src/codegen/internal-module-registry-scanner.ts +++ b/src/codegen/internal-module-registry-scanner.ts @@ -45,6 +45,13 @@ export function createInternalModuleRegistry(basedir: string) { nativeModuleEnumToId[processedEnumValue] = processedNumericId; } + const nativeStartIndex = moduleList.length; + + for (const [id] of Object.entries(nativeModuleIds)) { + moduleList.push(id); + internalRegistry.set(id, moduleList.length - 1); + } + if (nextNativeModuleId === 0) { throw new Error( "Could not find BUN_FOREACH_ESM_AND_CJS_NATIVE_MODULE in _NativeModule.h. Knowing native module IDs is a part of the codegen process.", @@ -55,18 +62,10 @@ export function createInternalModuleRegistry(basedir: string) { return `(__intrinsic__getInternalField(__intrinsic__internalModuleRegistry, ${id}) || __intrinsic__createInternalModuleById(${id}))`; } - function codegenRequireNativeModule(id: string) { - return `(__intrinsic__requireNativeModule(${id.replace(/node:/, "")}))`; - } - const requireTransformer = (specifier: string, from: string) => { const directMatch = internalRegistry.get(specifier); if (directMatch) return codegenRequireId(`${directMatch}/*${specifier}*/`); - if (specifier in nativeModuleIds) { - return codegenRequireNativeModule(JSON.stringify(specifier)); - } - const relativeMatch = resolveSyncOrNull(specifier, path.join(basedir, path.dirname(from))) ?? resolveSyncOrNull(specifier, basedir); @@ -93,5 +92,6 @@ export function createInternalModuleRegistry(basedir: string) { nativeModuleEnumToId, internalRegistry, moduleList, + nativeStartIndex, } as const; } diff --git a/src/import_record.zig b/src/import_record.zig index 9404faaadf..89622aaa97 100644 --- a/src/import_record.zig +++ b/src/import_record.zig @@ -56,7 +56,7 @@ pub const ImportKind = enum(u8) { labels.set(ImportKind.stmt, "import"); labels.set(ImportKind.require, "require()"); labels.set(ImportKind.dynamic, "import()"); - labels.set(ImportKind.require_resolve, "require.resolve"); + labels.set(ImportKind.require_resolve, "require.resolve()"); labels.set(ImportKind.at, "@import"); labels.set(ImportKind.url, "url()"); labels.set(ImportKind.internal, ""); diff --git a/src/js/builtins.d.ts b/src/js/builtins.d.ts index 31a157cd61..b12420e278 100644 --- a/src/js/builtins.d.ts +++ b/src/js/builtins.d.ts @@ -54,7 +54,7 @@ declare function $extractHighWaterMarkFromQueuingStrategyInit(obj: any): any; // https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp /** returns `arguments[index]` */ -declare function $argument(index: number): any; +declare function $argument(index: number): any | undefined; /** returns number of arguments */ declare function $argumentCount(): number; /** array.push(item) */ @@ -92,7 +92,6 @@ declare function $getInternalField number: N, ): Fields[N]; declare function $fulfillPromise(...args: any[]): TODO; -declare function $evaluateCommonJSModule(...args: any[]): TODO; declare function $loadCJS2ESM(...args: any[]): TODO; declare function $getGeneratorInternalField(): TODO; declare function $getAsyncGeneratorInternalField(): TODO; @@ -422,7 +421,7 @@ declare function $requireESM(path: string): any; declare const $requireMap: Map; declare const $internalModuleRegistry: InternalFieldObject; declare function $resolve(name: string, from: string): Promise; -declare function $resolveSync(name: string, from: string, isESM?: boolean): string; +declare function $resolveSync(name: string, from: string, isESM?: boolean, isUserRequireResolve?: boolean): string; declare function $resume(): TODO; declare function $search(): TODO; declare function $searchParams(): TODO; @@ -487,6 +486,10 @@ declare function $createCommonJSModule( hasEvaluated: boolean, parent: CommonJSModuleRecord, ): CommonJSModuleRecord; +declare function $evaluateCommonJSModule( + moduleToEvaluate: CommonJSModuleRecord, + sourceModule: CommonJSModuleRecord +): void; declare function $overridableRequire(this: CommonJSModuleRecord, id: string): any; diff --git a/src/js/builtins/ImportMetaObject.ts b/src/js/builtins/ImportMetaObject.ts index a1c65ffbe8..7e06be69a5 100644 --- a/src/js/builtins/ImportMetaObject.ts +++ b/src/js/builtins/ImportMetaObject.ts @@ -51,7 +51,7 @@ export function loadCJS2ESM(this: ImportMetaObject, resolvedSpecifier: string) { } // this pulls it out of the promise without delaying by a tick - // the promise is already fullfilled by $fullfillModuleSync + // the promise is already fulfilled by $fulfillModuleSync const sourceCodeObject = $getPromiseInternalField(fetch, $promiseFieldReactionsOrResult); moduleRecordPromise = loader.parseModule(key, sourceCodeObject); } @@ -125,7 +125,7 @@ export function loadCJS2ESM(this: ImportMetaObject, resolvedSpecifier: string) { } $visibility = "Private"; -export function requireESM(this: ImportMetaObject, resolved) { +export function requireESM(this: ImportMetaObject, resolved: string) { var entry = Loader.registry.$get(resolved); if (!entry || !entry.evaluated) { diff --git a/src/js/builtins/Module.ts b/src/js/builtins/Module.ts index 648bea5d6c..e96b2c54ad 100644 --- a/src/js/builtins/Module.ts +++ b/src/js/builtins/Module.ts @@ -12,34 +12,53 @@ export function require(this: CommonJSModuleRecord, id: string) { // overridableRequire can be overridden by setting `Module.prototype.require` $overriddenName = "require"; $visibility = "Private"; -export function overridableRequire(this: CommonJSModuleRecord, id: string) { - const existing = $requireMap.$get(id) || $requireMap.$get((id = $resolveSync(id, this.id, false))); - if (existing) { - // Scenario where this is necessary: - // - // In an ES Module, we have: - // - // import "react-dom/server" - // import "react" - // - // Synchronously, the "react" import is created first, and then the - // "react-dom/server" import is created. Then, at ES Module link time, they - // are evaluated. The "react-dom/server" import is evaluated first, and - // require("react") was previously created as an ESM module, so we wait - // for the ESM module to load - // - // ...and then when this code is reached, unless - // we evaluate it "early", we'll get an empty object instead of the module - // exports. - // - $evaluateCommonJSModule(existing); - return existing.exports; +export function overridableRequire(this: CommonJSModuleRecord, originalId: string) { + const id = $resolveSync(originalId, this.filename, false); + if (id.startsWith('node:')) { + if (id !== originalId) { + // A terrible special case where Node.js allows non-prefixed built-ins to + // read the require cache. Though they never write to it, which is so silly. + const existing = $requireMap.$get(originalId); + if (existing) { + $evaluateCommonJSModule(existing, this); + return existing.exports; + } + } + + return this.$requireNativeModule(id); + } else { + const existing = $requireMap.$get(id); + if (existing) { + // Scenario where this is necessary: + // + // In an ES Module, we have: + // + // import "react-dom/server" + // import "react" + // + // Synchronously, the "react" import is created first, and then the + // "react-dom/server" import is created. Then, at ES Module link time, they + // are evaluated. The "react-dom/server" import is evaluated first, and + // require("react") was previously created as an ESM module, so we wait + // for the ESM module to load + // + // ...and then when this code is reached, unless + // we evaluate it "early", we'll get an empty object instead of the module + // exports. + // + $evaluateCommonJSModule(existing, this); + return existing.exports; + } } if (id.endsWith(".node")) { return $internalRequire(id); } + if (id === "bun:test") { + return Bun.jest(this.filename); + } + // To handle import/export cycles, we need to create a module object and put // it into the map before we import it. const mod = $createCommonJSModule(id, {}, false, this); @@ -48,18 +67,33 @@ export function overridableRequire(this: CommonJSModuleRecord, id: string) { // This is where we load the module. We will see if Module._load and // Module._compile are actually important for compatibility. // - // Note: we do not need to wrap this in a try/catch, if it throws the C++ code will - // clear the module from the map. + // Note: we do not need to wrap this in a try/catch for release, if it throws + // the C++ code will clear the module from the map. // - var out = this.$require( - id, - mod, - // did they pass a { type } object? - $argumentCount(), - // the object containing a "type" attribute, if they passed one - // maybe this will be "paths" in the future too. - arguments[1], - ); + if (IS_BUN_DEVELOPMENT) { + $assert(mod.id === id); + try { + var out = this.$require( + id, + mod, + // did they pass a { type } object? + $argumentCount(), + // the object containing a "type" attribute, if they passed one + // maybe this will be "paths" in the future too. + $argument(1), + ); + } catch (E) { + $assert($requireMap.$get(id) === undefined, "Module " + JSON.stringify(id) + " should no longer be in the map"); + throw E; + } + } else { + var out = this.$require( + id, + mod, + $argumentCount(), + $argument(1), + ); + } // -1 means we need to lookup the module from the ESM registry. if (out === -1) { @@ -91,25 +125,37 @@ export function overridableRequire(this: CommonJSModuleRecord, id: string) { } } - return (mod.exports = namespace); + return (mod.exports = namespace["module.exports"] ?? namespace); } } - $evaluateCommonJSModule(mod); + $evaluateCommonJSModule(mod, this); return mod.exports; } $visibility = "Private"; -export function requireResolve(this: string | { id: string }, id: string) { - return $resolveSync(id, typeof this === "string" ? this : this?.id, false); +export function requireResolve(this: string | { filename?: string; id?: string }, id: string) { + return $resolveSync(id, typeof this === "string" ? this : this?.filename ?? this?.id ?? "", false, true); } -$visibility = "Private"; -export function requireNativeModule(id: string) { - let esm = Loader.registry.$get(id); - if (esm?.evaluated && (esm.state ?? 0) >= $ModuleReady) { - const exports = Loader.getModuleNamespaceObject(esm.module); - return exports.default; - } - return $requireESM(id).default; +type WrapperMutate = (start: string, end: string) => void; +export function getWrapperArrayProxy(onMutate: WrapperMutate) { + const wrapper = ["(function(exports,require,module,__filename,__dirname){", "})"]; + return new Proxy(wrapper, { + set(target, prop, value, receiver) { + Reflect.set(target, prop, value, receiver); + onMutate(wrapper[0], wrapper[1]); + return true; + }, + defineProperty(target, prop, descriptor) { + Reflect.defineProperty(target, prop, descriptor); + onMutate(wrapper[0], wrapper[1]); + return true; + }, + deleteProperty(target, prop) { + Reflect.deleteProperty(target, prop); + onMutate(wrapper[0], wrapper[1]); + return true; + }, + }); } diff --git a/src/js/internal/util/inspect.js b/src/js/internal/util/inspect.js index 6908ff9ca5..106ff19a0b 100644 --- a/src/js/internal/util/inspect.js +++ b/src/js/internal/util/inspect.js @@ -30,6 +30,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. + const { pathToFileURL } = require("node:url"); let BufferModule; diff --git a/src/js/node/path.ts b/src/js/node/path.ts index 839075af42..e9a67e4337 100644 --- a/src/js/node/path.ts +++ b/src/js/node/path.ts @@ -45,11 +45,6 @@ posix.posix = posix; type Glob = import("bun").Glob; -let LazyGlob: Glob | undefined; -function loadGlob() { - LazyGlob = require("bun").Glob; -} - // the most-recently used glob is memoized in case `matchesGlob` is called in a // loop with the same pattern let prevGlob: Glob | undefined; @@ -65,24 +60,21 @@ function matchesGlob(isWindows, path, pattern) { if (prevPattern === pattern) { glob = prevGlob; } else { - if (LazyGlob === undefined) loadGlob(); validateString(pattern, "pattern"); if (isWindows) pattern = pattern.replaceAll("\\", "/"); - glob = prevGlob = new LazyGlob!(pattern); + glob = prevGlob = new Bun.Glob(pattern); prevPattern = pattern; } } else { - loadGlob(); // no prevGlob implies LazyGlob isn't loaded validateString(pattern, "pattern"); if (isWindows) pattern = pattern.replaceAll("\\", "/"); - glob = prevGlob = new LazyGlob!(pattern); + glob = prevGlob = new Bun.Glob(pattern); prevPattern = pattern; } return glob.match(path); } -// posix.matchesGlob = win32.matchesGlob = matchesGlob; posix.matchesGlob = matchesGlob.bind(null, false); win32.matchesGlob = matchesGlob.bind(null, true); diff --git a/src/js/private.d.ts b/src/js/private.d.ts index b058cc40c5..052e58bbe1 100644 --- a/src/js/private.d.ts +++ b/src/js/private.d.ts @@ -151,6 +151,7 @@ declare interface Error { interface CommonJSModuleRecord { $require(id: string, mod: any, args_count: number, args: Array): any; + $requireNativeModule(id: string): any; children: CommonJSModuleRecord[]; exports: any; id: string; @@ -159,6 +160,7 @@ interface CommonJSModuleRecord { path: string; paths: string[]; require: typeof require; + filename: string; } /** diff --git a/src/js_ast.zig b/src/js_ast.zig index 59aab796e1..acbb12001d 100644 --- a/src/js_ast.zig +++ b/src/js_ast.zig @@ -7975,7 +7975,7 @@ pub const Macro = struct { bun.assert(!isMacroPath(import_record_path_without_macro_prefix)); const input_specifier = brk: { - if (JSC.HardcodedModule.Aliases.get(import_record_path, .bun)) |replacement| { + if (JSC.HardcodedModule.Alias.get(import_record_path, .bun)) |replacement| { break :brk replacement.path; } diff --git a/src/linker.zig b/src/linker.zig index 4201cf20e1..6997bc3e8b 100644 --- a/src/linker.zig +++ b/src/linker.zig @@ -186,14 +186,13 @@ pub const Linker = struct { } if (comptime is_bun) { - if (JSC.HardcodedModule.Aliases.get(import_record.path.text, linker.options.target)) |replacement| { + if (JSC.HardcodedModule.Alias.get(import_record.path.text, linker.options.target)) |replacement| { + if (replacement.tag == .builtin and import_record.kind.isCommonJS()) + continue; import_record.path.text = replacement.path; import_record.tag = replacement.tag; import_record.is_external_without_side_effects = true; - if (replacement.tag != .none) { - externals.append(@intCast(record_index)) catch unreachable; - continue; - } + continue; } if (strings.startsWith(import_record.path.text, "node:")) { // if a module is not found here, it is not found at all diff --git a/src/options.zig b/src/options.zig index 07685a9ba1..510bf6a4a1 100644 --- a/src/options.zig +++ b/src/options.zig @@ -89,7 +89,7 @@ pub const ExternalModules = struct { }; pub fn isNodeBuiltin(str: string) bool { - return bun.JSC.HardcodedModule.Aliases.has(str, .node); + return bun.JSC.HardcodedModule.Alias.has(str, .node); } const default_wildcard_patterns = &[_]WildcardPattern{ diff --git a/src/resolver/resolver.zig b/src/resolver/resolver.zig index 1b0e9df7cf..636020d919 100644 --- a/src/resolver/resolver.zig +++ b/src/resolver/resolver.zig @@ -713,7 +713,7 @@ pub const Resolver = struct { if (r.opts.mark_builtins_as_external) { if (strings.hasPrefixComptime(import_path, "node:") or strings.hasPrefixComptime(import_path, "bun:") or - bun.JSC.HardcodedModule.Aliases.has(import_path, r.opts.target)) + bun.JSC.HardcodedModule.Alias.has(import_path, r.opts.target)) { return .{ .success = Result{ @@ -1306,7 +1306,7 @@ pub const Resolver = struct { if (had_node_prefix) { // Module resolution fails automatically for unknown node builtins - if (!bun.JSC.HardcodedModule.Aliases.has(import_path_without_node_prefix, .node)) { + if (!bun.JSC.HardcodedModule.Alias.has(import_path_without_node_prefix, .node)) { return .{ .not_found = {} }; } @@ -3130,10 +3130,10 @@ pub const Resolver = struct { // } // if (r.opts.mark_builtins_as_external or r.opts.target.isBun()) { - if (JSC.HardcodedModule.Aliases.has(esm_resolution.path, r.opts.target)) { + if (JSC.HardcodedModule.Alias.get(esm_resolution.path, r.opts.target)) |alias| { return .{ .success = .{ - .path_pair = .{ .primary = bun.fs.Path.init(esm_resolution.path) }, + .path_pair = .{ .primary = bun.fs.Path.init(alias.path) }, .is_external = true, }, }; diff --git a/test/internal/ban-words.test.ts b/test/internal/ban-words.test.ts index 3ec5f14faf..f3f173e781 100644 --- a/test/internal/ban-words.test.ts +++ b/test/internal/ban-words.test.ts @@ -1,5 +1,5 @@ import { readdir } from "fs/promises"; -import { join } from "path"; +import path from "path"; // prettier-ignore const words: Record = { @@ -28,16 +28,17 @@ const words: Record "== alloc.ptr": { reason: "The std.mem.Allocator context pointer can be undefined, which makes this comparison undefined behavior" }, "!= alloc.ptr": { reason: "The std.mem.Allocator context pointer can be undefined, which makes this comparison undefined behavior" }, [String.raw`: [a-zA-Z0-9_\.\*\?\[\]\(\)]+ = undefined,`]: { reason: "Do not default a struct field to undefined", limit: 249, regex: true }, + "usingnamespace": { reason: "This brings Bun away from incremental / faster compile times.", limit: 496 }, }; const words_keys = [...Object.keys(words)]; let counts: Record = {}; -const files = await readdir(join(__dirname, "../../src"), { recursive: true, withFileTypes: true }); +const files = await readdir("src", { recursive: true, withFileTypes: true }); for (const file of files) { if (file.isDirectory()) continue; if (!file.name.endsWith(".zig")) continue; - if (file.parentPath.startsWith("src/deps")) continue; - const content = await Bun.file(file.parentPath + "/" + file.name).text(); + if (file.parentPath.startsWith("src" + path.sep + "deps")) continue; + const content = await Bun.file(file.parentPath + path.sep + file.name).text(); for (const word of words_keys) { let regex = words[word].regex ? new RegExp(word, "g") : undefined; const did_match = regex ? regex.test(content) : content.includes(word); @@ -50,7 +51,7 @@ for (const file of files) { if (trim.startsWith("//") || trim.startsWith("\\\\")) continue; const count = regex ? [...lines[line_i].matchAll(regex)].length : lines[line_i].split(word).length - 1; for (let count_i = 0; count_i < count; count_i++) { - counts[word].push([line_i + 1, file.parentPath + "/" + file.name]); + counts[word].push([line_i + 1, file.parentPath + path.sep + file.name]); } } } diff --git a/test/js/bun/resolve/import-meta-resolve.test.mjs b/test/js/bun/resolve/import-meta-resolve.test.mjs index 0ed73acb10..6890a22243 100644 --- a/test/js/bun/resolve/import-meta-resolve.test.mjs +++ b/test/js/bun/resolve/import-meta-resolve.test.mjs @@ -88,7 +88,7 @@ if (process.platform !== "win32") { fileUrlRelTo(() => import.meta.resolve("lodash"), "../../../node_modules/lodash/lodash.js"); exact(() => import.meta.resolve("node:path"), "node:path"); -exact(() => import.meta.resolve("path"), process?.versions?.bun ? "path" : "node:path"); +exact(() => import.meta.resolve("path"), "node:path"); exact(() => import.meta.resolve("node:doesnotexist"), "node:doesnotexist"); if (process?.versions?.bun) { diff --git a/test/js/bun/resolve/import-meta.test.js b/test/js/bun/resolve/import-meta.test.js index 9ad8a7bc03..965bdb73ac 100644 --- a/test/js/bun/resolve/import-meta.test.js +++ b/test/js/bun/resolve/import-meta.test.js @@ -249,6 +249,15 @@ it("import non exist error code", async () => { try { await import("node:missing"); throw 1; + } catch (e) { + expect(e.code).toBe("ERR_UNKNOWN_BUILTIN_MODULE"); + } +}); + +it("import non exist error code", async () => { + try { + await import("./idontexist"); + throw 1; } catch (e) { expect(e.code).toBe("ERR_MODULE_NOT_FOUND"); } diff --git a/test/js/bun/resolve/resolve-error.test.ts b/test/js/bun/resolve/resolve-error.test.ts index 513269e67f..af0ae7fbfc 100644 --- a/test/js/bun/resolve/resolve-error.test.ts +++ b/test/js/bun/resolve/resolve-error.test.ts @@ -22,7 +22,7 @@ describe("ResolveMessage", () => { } }); - it("has code for esm", async () => { + it.only("has code for esm", async () => { try { await import("./file-importing-nonexistent-file.js"); } catch (e: any) { diff --git a/test/js/bun/resolve/resolve.test.ts b/test/js/bun/resolve/resolve.test.ts index 3d7acb571e..a6c964d120 100644 --- a/test/js/bun/resolve/resolve.test.ts +++ b/test/js/bun/resolve/resolve.test.ts @@ -297,7 +297,7 @@ it("import long string should not segfault", async () => { } catch {} }); -it("import override to node builtin", async () => { +it.only("import override to node builtin", async () => { // @ts-expect-error expect(await import("#async_hooks")).toBeDefined(); }); diff --git a/test/js/node/missing-module.test.js b/test/js/node/missing-module.test.js index b39446f1ab..4f23facf96 100644 --- a/test/js/node/missing-module.test.js +++ b/test/js/node/missing-module.test.js @@ -1,7 +1,25 @@ -import { expect, test } from "bun:test"; +import { test, expect } from "bun:test"; +import assert from "assert"; test("not implemented yet module throws an error", () => { - const missingModule = "node:missing" + ""; - expect(() => require(missingModule)).toThrow(/^Cannot find package 'node:missing' from '/); - expect(() => import(missingModule)).toThrow(/^Cannot find package 'node:missing' from '/); + var missingModule = "node:missing"; + var missingBun = "bun:missing"; + var missingFile = "./filethatdoesntexist"; + var missingPackage = "package-that-doesnt-exist"; + + assert.throws(() => require(missingModule), {message: 'No such built-in module: node:missing', code: "ERR_UNKNOWN_BUILTIN_MODULE" }); + assert.throws(() => require.resolve(missingModule), {message: /Cannot find package 'node:missing' from/, code: "MODULE_NOT_FOUND" }); + assert.rejects(() => import(missingModule), {message: 'No such built-in module: node:missing', code: "ERR_UNKNOWN_BUILTIN_MODULE" }); + + assert.throws(() => require(missingBun), {message: /^Cannot find package 'bun:missing' from/, code: "MODULE_NOT_FOUND" }); + assert.throws(() => require.resolve(missingBun), {message: /^Cannot find package 'bun:missing' from/, code: "MODULE_NOT_FOUND" }); + assert.rejects(() => import(missingBun), {message: /^Cannot find package 'bun:missing' from/, code: "ERR_MODULE_NOT_FOUND" }); + + assert.throws(() => require(missingFile), {message: /^Cannot find module '\.\/filethatdoesntexist'/, code: "MODULE_NOT_FOUND" }); + assert.throws(() => require.resolve(missingFile), {message: /^Cannot find module '\.\/filethatdoesntexist'/, code: "MODULE_NOT_FOUND" }); + assert.rejects(() => import(missingFile), {message: /^Cannot find module '\.\/filethatdoesntexist'/, code: "ERR_MODULE_NOT_FOUND" }); + + assert.throws(() => require(missingPackage), {message: /^Cannot find package 'package-that-doesnt-exist'/, code: "MODULE_NOT_FOUND" }); + assert.throws(() => require.resolve(missingPackage), {message: /^Cannot find package 'package-that-doesnt-exist'/, code: "MODULE_NOT_FOUND" }); + assert.rejects(() => import(missingPackage), {message: /^Cannot find package 'package-that-doesnt-exist'/, code: "ERR_MODULE_NOT_FOUND" }); }); diff --git a/test/js/node/module/esm_to_cjs_interop.mjs b/test/js/node/module/esm_to_cjs_interop.mjs new file mode 100644 index 0000000000..8a084a8984 --- /dev/null +++ b/test/js/node/module/esm_to_cjs_interop.mjs @@ -0,0 +1,2 @@ +const test = Symbol.for("meow"); +export { test as "module.exports" }; diff --git a/test/js/node/module/node-module-module.test.js b/test/js/node/module/node-module-module.test.js index 6907b7c177..cccc70e9cb 100644 --- a/test/js/node/module/node-module-module.test.js +++ b/test/js/node/module/node-module-module.test.js @@ -141,3 +141,40 @@ test("Module._resolveLookupPaths", () => { test("Module.findSourceMap doesn't throw", () => { expect(Module.findSourceMap("foo")).toEqual(undefined); }); + +test("require cache relative specifier", () => { + require.cache['./bar.cjs'] = { exports: { default: 'bar' } }; + expect(() => require('./bar.cjs')).toThrow("Cannot find module"); +}); +test("builtin resolution", () => { + expect(require.resolve("fs")).toBe("fs"); + expect(require.resolve("node:fs")).toBe("node:fs"); +}); +test("require cache node builtins specifier", () => { + // as js builtin + try { + const fake = { default: 'bar' }; + const real = require('fs'); + expect(require.cache['fs']).toBe(undefined); + require.cache['fs'] = { exports: fake }; + expect(require('fs')).toBe(fake); + expect(require("node:fs")).toBe(real); + } finally { + delete require.cache['fs']; + } + + // as native module + try { + const fake = { default: 'bar' }; + const real = require('util/types'); + expect(require.cache['util/types']).toBe(undefined); + require.cache['util/types'] = { exports: fake }; + expect(require('util/types')).toBe(fake); + expect(require("node:util/types")).toBe(real); + } finally { + delete require.cache['util/types']; + } +}); +test("require a cjs file uses the 'module.exports' export", () => { + expect(require("./esm_to_cjs_interop.mjs")).toEqual(Symbol.for("meow")); +}); diff --git a/test/js/node/test/fixtures/.gitignore b/test/js/node/test/fixtures/.gitignore new file mode 100644 index 0000000000..736e8ae58a --- /dev/null +++ b/test/js/node/test/fixtures/.gitignore @@ -0,0 +1 @@ +!node_modules \ No newline at end of file diff --git a/test/js/node/test/fixtures/GH-54265/dep1.js b/test/js/node/test/fixtures/GH-54265/dep1.js new file mode 100644 index 0000000000..42464d01ec --- /dev/null +++ b/test/js/node/test/fixtures/GH-54265/dep1.js @@ -0,0 +1,4 @@ +// dep1.js +module.exports = function requireDep2() { + require("./dep2.js"); +}; diff --git a/test/js/node/test/fixtures/GH-54265/dep2.js b/test/js/node/test/fixtures/GH-54265/dep2.js new file mode 100644 index 0000000000..59c017990f --- /dev/null +++ b/test/js/node/test/fixtures/GH-54265/dep2.js @@ -0,0 +1,3 @@ +// dep2.js + +// (empty) diff --git a/test/js/node/test/fixtures/GH-54265/index.js b/test/js/node/test/fixtures/GH-54265/index.js new file mode 100644 index 0000000000..9caef6b88c --- /dev/null +++ b/test/js/node/test/fixtures/GH-54265/index.js @@ -0,0 +1,10 @@ +// index.js +const Module = require("module"); +const requireDep2 = require("./dep1.js"); + +const globalCache = Module._cache; +Module._cache = Object.create(null); +require("./require-hook.js"); +Module._cache = globalCache; + +requireDep2(); diff --git a/test/js/node/test/fixtures/GH-54265/require-hook.js b/test/js/node/test/fixtures/GH-54265/require-hook.js new file mode 100644 index 0000000000..e94a2b6261 --- /dev/null +++ b/test/js/node/test/fixtures/GH-54265/require-hook.js @@ -0,0 +1,9 @@ +// require-hook.js +const Module = require("module"); +const requireDep2 = require("./dep1.js"); + +const originalJSLoader = Module._extensions[".js"]; +Module._extensions[".js"] = function customJSLoader(module, filename) { + requireDep2(); + return originalJSLoader(module, filename); +}; diff --git a/test/js/node/test/fixtures/compile-cache-flush.js b/test/js/node/test/fixtures/compile-cache-flush.js new file mode 100644 index 0000000000..8054f67b0d --- /dev/null +++ b/test/js/node/test/fixtures/compile-cache-flush.js @@ -0,0 +1,21 @@ +'use strict'; + +const { flushCompileCache, getCompileCacheDir } = require('module'); +const { spawnSync } = require('child_process'); +const assert = require('assert'); + +if (process.argv[2] !== 'child') { + // The test should be run with the compile cache already enabled and NODE_DEBUG_NATIVE=COMPILE_CACHE. + assert(getCompileCacheDir()); + assert(process.env.NODE_DEBUG_NATIVE.includes('COMPILE_CACHE')); + + flushCompileCache(); + + const child1 = spawnSync(process.execPath, [__filename, 'child']); + console.log(child1.stderr.toString().trim().split('\n').map(line => `[child1]${line}`).join('\n')); + + flushCompileCache(); + + const child2 = spawnSync(process.execPath, [__filename, 'child']); + console.log(child2.stderr.toString().trim().split('\n').map(line => `[child2]${line}`).join('\n')); +} diff --git a/test/js/node/test/fixtures/compile-cache-wrapper.js b/test/js/node/test/fixtures/compile-cache-wrapper.js new file mode 100644 index 0000000000..57ebbb71b3 --- /dev/null +++ b/test/js/node/test/fixtures/compile-cache-wrapper.js @@ -0,0 +1,21 @@ +'use strict'; + +const { enableCompileCache, getCompileCacheDir, constants } = require('module'); + +console.log('dir before enableCompileCache:', getCompileCacheDir()); +const result = enableCompileCache(process.env.NODE_TEST_COMPILE_CACHE_DIR); +switch (result.status) { + case constants.compileCacheStatus.FAILED: + console.log('Compile cache failed. ' + result.message); + break; + case constants.compileCacheStatus.ENABLED: + console.log('Compile cache enabled. ' + result.directory); + break; + case constants.compileCacheStatus.ALREADY_ENABLED: + console.log('Compile cache already enabled.'); + break; + case constants.compileCacheStatus.DISABLED: + console.log('Compile cache already disabled.'); + break; +} +console.log('dir after enableCompileCache:', getCompileCacheDir()); diff --git a/test/js/node/test/fixtures/console/console.snapshot b/test/js/node/test/fixtures/console/console.snapshot index 4f1cb25481..41e7d16fb9 100644 --- a/test/js/node/test/fixtures/console/console.snapshot +++ b/test/js/node/test/fixtures/console/console.snapshot @@ -7,3 +7,4 @@ Trace: foo at * at * at * + at * diff --git a/test/js/node/test/fixtures/copy/utf/新建文件夹/index.js b/test/js/node/test/fixtures/copy/utf/新建文件夹/index.js new file mode 100644 index 0000000000..12388b0457 --- /dev/null +++ b/test/js/node/test/fixtures/copy/utf/新建文件夹/index.js @@ -0,0 +1,3 @@ +module.exports = { + purpose: 'testing copy' +}; diff --git a/test/js/node/test/fixtures/deep-exit.js b/test/js/node/test/fixtures/deep-exit.js new file mode 100644 index 0000000000..357137a279 --- /dev/null +++ b/test/js/node/test/fixtures/deep-exit.js @@ -0,0 +1,15 @@ +'use strict'; + +// This is meant to be run with --trace-exit. + +const depth = parseInt(process.env.STACK_DEPTH) || 30; +let counter = 1; +function recurse() { + if (counter++ < depth) { + recurse(); + } else { + process.exit(0); + } +} + +recurse(); diff --git a/test/js/node/test/fixtures/disable-signal/sigusr1.js b/test/js/node/test/fixtures/disable-signal/sigusr1.js new file mode 100644 index 0000000000..6abf3ab2b5 --- /dev/null +++ b/test/js/node/test/fixtures/disable-signal/sigusr1.js @@ -0,0 +1,2 @@ +console.log('pid is', process.pid); +setInterval(() => {}, 1000); diff --git a/test/js/node/test/fixtures/dotenv/no-final-newline-single-quotes.env b/test/js/node/test/fixtures/dotenv/no-final-newline-single-quotes.env new file mode 100644 index 0000000000..4f1b37d774 --- /dev/null +++ b/test/js/node/test/fixtures/dotenv/no-final-newline-single-quotes.env @@ -0,0 +1 @@ +BASIC='basic' \ No newline at end of file diff --git a/test/js/node/test/fixtures/dotenv/no-final-newline.env b/test/js/node/test/fixtures/dotenv/no-final-newline.env new file mode 100644 index 0000000000..ef996552bd --- /dev/null +++ b/test/js/node/test/fixtures/dotenv/no-final-newline.env @@ -0,0 +1 @@ +BASIC="basic" \ No newline at end of file diff --git a/test/js/node/test/fixtures/dotenv/node-options.env b/test/js/node/test/fixtures/dotenv/node-options.env index f74ac01bc2..bd3be820f6 100644 --- a/test/js/node/test/fixtures/dotenv/node-options.env +++ b/test/js/node/test/fixtures/dotenv/node-options.env @@ -1,6 +1,6 @@ CUSTOM_VARIABLE=hello-world NODE_NO_WARNINGS=1 -NODE_OPTIONS="--experimental-permission --allow-fs-read=*" +NODE_OPTIONS="--permission --allow-fs-read=*" TZ=Pacific/Honolulu UV_THREADPOOL_SIZE=5 BASIC=overridden diff --git a/test/js/node/test/fixtures/errors/async_error_nexttick_main.snapshot b/test/js/node/test/fixtures/errors/async_error_nexttick_main.snapshot index eff2c0569c..c5ccba996a 100644 --- a/test/js/node/test/fixtures/errors/async_error_nexttick_main.snapshot +++ b/test/js/node/test/fixtures/errors/async_error_nexttick_main.snapshot @@ -1,7 +1,7 @@ Error: test at one (*fixtures*async-error.js:4:9) at two (*fixtures*async-error.js:17:9) - at process.processTicksAndRejections (node:internal*process*task_queues:95:5) + at process.processTicksAndRejections (node:internal*process*task_queues:105:5) at async three (*fixtures*async-error.js:20:3) at async four (*fixtures*async-error.js:24:3) at async main (*async_error_nexttick_main.js:7:5) diff --git a/test/js/node/test/fixtures/errors/force_colors.snapshot b/test/js/node/test/fixtures/errors/force_colors.snapshot index 21410d492d..e5a03ca609 100644 --- a/test/js/node/test/fixtures/errors/force_colors.snapshot +++ b/test/js/node/test/fixtures/errors/force_colors.snapshot @@ -11,5 +11,6 @@ Error: Should include grayed stack trace  at *  at *  at * + at * Node.js * diff --git a/test/js/node/test/fixtures/errors/promise_unhandled_warn_with_error.snapshot b/test/js/node/test/fixtures/errors/promise_unhandled_warn_with_error.snapshot index 48e5da7c9a..4b3ed8640d 100644 --- a/test/js/node/test/fixtures/errors/promise_unhandled_warn_with_error.snapshot +++ b/test/js/node/test/fixtures/errors/promise_unhandled_warn_with_error.snapshot @@ -7,5 +7,6 @@ at * at * at * -(Use `node --trace-warnings ...` to show where the warning was created) + at * +(Use `* --trace-warnings ...` to show where the warning was created) (node:*) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https:*nodejs.org*api*cli.html#cli_unhandled_rejections_mode). (rejection id: 1) diff --git a/test/js/node/test/fixtures/errors/throw_error_with_getter_throw.snapshot b/test/js/node/test/fixtures/errors/throw_error_with_getter_throw.snapshot index 30bbb336a2..1786f96f19 100644 --- a/test/js/node/test/fixtures/errors/throw_error_with_getter_throw.snapshot +++ b/test/js/node/test/fixtures/errors/throw_error_with_getter_throw.snapshot @@ -3,6 +3,6 @@ throw { * eslint-disable-line no-throw-literal ^ [object Object] -(Use `node --trace-uncaught ...` to show where the exception was thrown) +(Use `* --trace-uncaught ...` to show where the exception was thrown) Node.js * diff --git a/test/js/node/test/fixtures/errors/throw_in_eval_anonymous.js b/test/js/node/test/fixtures/errors/throw_in_eval_anonymous.js new file mode 100644 index 0000000000..aa9ab6a058 --- /dev/null +++ b/test/js/node/test/fixtures/errors/throw_in_eval_anonymous.js @@ -0,0 +1,9 @@ +'use strict'; +require('../../common'); + +Error.stackTraceLimit = 1; +eval(` + + throw new Error('error in anonymous script'); + +`) diff --git a/test/js/node/test/fixtures/errors/throw_in_eval_anonymous.snapshot b/test/js/node/test/fixtures/errors/throw_in_eval_anonymous.snapshot new file mode 100644 index 0000000000..e6f731f4d9 --- /dev/null +++ b/test/js/node/test/fixtures/errors/throw_in_eval_anonymous.snapshot @@ -0,0 +1,8 @@ +:* + throw new Error('error in anonymous script'); + ^ + +Error: error in anonymous script + at eval (eval at (*throw_in_eval_anonymous.js:*:*), :*:*) + +Node.js * diff --git a/test/js/node/test/fixtures/errors/throw_in_eval_named.js b/test/js/node/test/fixtures/errors/throw_in_eval_named.js new file mode 100644 index 0000000000..0d33fcf4d0 --- /dev/null +++ b/test/js/node/test/fixtures/errors/throw_in_eval_named.js @@ -0,0 +1,9 @@ +'use strict'; +require('../../common'); + +Error.stackTraceLimit = 1; +eval(` + + throw new Error('error in named script'); + +//# sourceURL=evalscript.js`) diff --git a/test/js/node/test/fixtures/errors/throw_in_eval_named.snapshot b/test/js/node/test/fixtures/errors/throw_in_eval_named.snapshot new file mode 100644 index 0000000000..3be4c35847 --- /dev/null +++ b/test/js/node/test/fixtures/errors/throw_in_eval_named.snapshot @@ -0,0 +1,8 @@ +evalscript.js:* + throw new Error('error in named script'); + ^ + +Error: error in named script + at eval (evalscript.js:*:*) + +Node.js * diff --git a/test/js/node/test/fixtures/errors/throw_null.snapshot b/test/js/node/test/fixtures/errors/throw_null.snapshot index 88494ec683..1a1191ca9c 100644 --- a/test/js/node/test/fixtures/errors/throw_null.snapshot +++ b/test/js/node/test/fixtures/errors/throw_null.snapshot @@ -3,6 +3,6 @@ throw null; ^ null -(Use `node --trace-uncaught ...` to show where the exception was thrown) +(Use `* --trace-uncaught ...` to show where the exception was thrown) Node.js * diff --git a/test/js/node/test/fixtures/errors/throw_undefined.snapshot b/test/js/node/test/fixtures/errors/throw_undefined.snapshot index baae738445..b6b6060b17 100644 --- a/test/js/node/test/fixtures/errors/throw_undefined.snapshot +++ b/test/js/node/test/fixtures/errors/throw_undefined.snapshot @@ -3,6 +3,6 @@ throw undefined; ^ undefined -(Use `node --trace-uncaught ...` to show where the exception was thrown) +(Use `* --trace-uncaught ...` to show where the exception was thrown) Node.js * diff --git a/test/js/node/test/fixtures/errors/unhandled_promise_trace_warnings.snapshot b/test/js/node/test/fixtures/errors/unhandled_promise_trace_warnings.snapshot index 94c709b177..246b82a8d5 100644 --- a/test/js/node/test/fixtures/errors/unhandled_promise_trace_warnings.snapshot +++ b/test/js/node/test/fixtures/errors/unhandled_promise_trace_warnings.snapshot @@ -11,6 +11,7 @@ at * at * at * + at * (node:*) Error: This was rejected at * at * @@ -20,6 +21,7 @@ at * at * at * + at * (node:*) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 1) at * at * diff --git a/test/js/node/test/fixtures/es-module-loaders/builtin-named-exports-loader.mjs b/test/js/node/test/fixtures/es-module-loaders/builtin-named-exports-loader.mjs index fca31c585a..f1b770d04f 100644 --- a/test/js/node/test/fixtures/es-module-loaders/builtin-named-exports-loader.mjs +++ b/test/js/node/test/fixtures/es-module-loaders/builtin-named-exports-loader.mjs @@ -28,7 +28,7 @@ export function load(url, context, next) { source: generateBuiltinModule(urlObj.pathname), format: 'commonjs', }; - } else if (context.format === 'commonjs') { + } else if (context.format === undefined || context.format === null || context.format === 'commonjs') { return { shortCircuit: true, source: readFileSync(new URL(url)), diff --git a/test/js/node/test/fixtures/es-module-loaders/hooks-custom.mjs b/test/js/node/test/fixtures/es-module-loaders/hooks-custom.mjs index 3c38649a88..5109d20f4d 100644 --- a/test/js/node/test/fixtures/es-module-loaders/hooks-custom.mjs +++ b/test/js/node/test/fixtures/es-module-loaders/hooks-custom.mjs @@ -105,5 +105,12 @@ export function load(url, context, next) { }; } + if (url.endsWith('esmHook/maximumCallStack.mjs')) { + function recurse() { + recurse(); + } + recurse(); + } + return next(url); } diff --git a/test/js/node/test/fixtures/es-module-loaders/hooks-input.mjs b/test/js/node/test/fixtures/es-module-loaders/hooks-input.mjs index 1d3759f458..854b8e6192 100644 --- a/test/js/node/test/fixtures/es-module-loaders/hooks-input.mjs +++ b/test/js/node/test/fixtures/es-module-loaders/hooks-input.mjs @@ -37,6 +37,7 @@ export async function resolve(specifier, context, next) { 'conditions', 'importAttributes', 'parentURL', + 'importAssertions', ]); assert.ok(Array.isArray(context.conditions)); assert.strictEqual(typeof next, 'function'); @@ -71,9 +72,10 @@ export async function load(url, context, next) { assert.ok(new URL(url)); // Ensure `context` has all and only the properties it's supposed to - assert.deepStrictEqual(Object.keys(context), [ + assert.deepStrictEqual(Reflect.ownKeys(context), [ 'format', 'importAttributes', + 'importAssertions', ]); assert.strictEqual(context.format, 'test'); assert.strictEqual(typeof next, 'function'); diff --git a/test/js/node/test/fixtures/es-module-loaders/loader-with-custom-condition.mjs b/test/js/node/test/fixtures/es-module-loaders/loader-with-custom-condition.mjs index 3aefed51d5..90c55fa576 100644 --- a/test/js/node/test/fixtures/es-module-loaders/loader-with-custom-condition.mjs +++ b/test/js/node/test/fixtures/es-module-loaders/loader-with-custom-condition.mjs @@ -5,6 +5,7 @@ export async function resolve(specifier, context, defaultResolve) { deepStrictEqual([...context.conditions].sort(), [ 'import', + 'module-sync', 'node', 'node-addons', ]); diff --git a/test/js/node/test/fixtures/es-module-loaders/node_modules/load/index.mjs b/test/js/node/test/fixtures/es-module-loaders/node_modules/load/index.mjs new file mode 100644 index 0000000000..db98e8d9f8 --- /dev/null +++ b/test/js/node/test/fixtures/es-module-loaders/node_modules/load/index.mjs @@ -0,0 +1 @@ +export * from '../../loader-load-passthru.mjs' \ No newline at end of file diff --git a/test/js/node/test/fixtures/es-module-loaders/node_modules/load/package.json b/test/js/node/test/fixtures/es-module-loaders/node_modules/load/package.json new file mode 100644 index 0000000000..b6629e2478 --- /dev/null +++ b/test/js/node/test/fixtures/es-module-loaders/node_modules/load/package.json @@ -0,0 +1,3 @@ +{ + "exports": "./index.mjs" +} diff --git a/test/js/node/test/fixtures/es-module-loaders/node_modules/resolve/index.mjs b/test/js/node/test/fixtures/es-module-loaders/node_modules/resolve/index.mjs new file mode 100644 index 0000000000..b3769d9613 --- /dev/null +++ b/test/js/node/test/fixtures/es-module-loaders/node_modules/resolve/index.mjs @@ -0,0 +1 @@ +export * from '../../loader-resolve-passthru.mjs' \ No newline at end of file diff --git a/test/js/node/test/fixtures/es-module-loaders/node_modules/resolve/package.json b/test/js/node/test/fixtures/es-module-loaders/node_modules/resolve/package.json new file mode 100644 index 0000000000..b6629e2478 --- /dev/null +++ b/test/js/node/test/fixtures/es-module-loaders/node_modules/resolve/package.json @@ -0,0 +1,3 @@ +{ + "exports": "./index.mjs" +} diff --git a/test/js/node/test/fixtures/es-module-specifiers/node_modules/explicit-main/entry.mjs b/test/js/node/test/fixtures/es-module-specifiers/node_modules/explicit-main/entry.mjs new file mode 100644 index 0000000000..914e3a97d5 --- /dev/null +++ b/test/js/node/test/fixtures/es-module-specifiers/node_modules/explicit-main/entry.mjs @@ -0,0 +1 @@ +export default 'esm'; diff --git a/test/js/node/test/fixtures/es-module-specifiers/node_modules/explicit-main/package.json b/test/js/node/test/fixtures/es-module-specifiers/node_modules/explicit-main/package.json new file mode 100644 index 0000000000..e9457582ac --- /dev/null +++ b/test/js/node/test/fixtures/es-module-specifiers/node_modules/explicit-main/package.json @@ -0,0 +1,3 @@ +{ + "main": "entry.mjs" +} \ No newline at end of file diff --git a/test/js/node/test/fixtures/es-module-specifiers/node_modules/implicit-main-type-commonjs/entry.mjs b/test/js/node/test/fixtures/es-module-specifiers/node_modules/implicit-main-type-commonjs/entry.mjs new file mode 100644 index 0000000000..914e3a97d5 --- /dev/null +++ b/test/js/node/test/fixtures/es-module-specifiers/node_modules/implicit-main-type-commonjs/entry.mjs @@ -0,0 +1 @@ +export default 'esm'; diff --git a/test/js/node/test/fixtures/es-module-specifiers/node_modules/implicit-main-type-commonjs/package.json b/test/js/node/test/fixtures/es-module-specifiers/node_modules/implicit-main-type-commonjs/package.json new file mode 100644 index 0000000000..9093a7cc14 --- /dev/null +++ b/test/js/node/test/fixtures/es-module-specifiers/node_modules/implicit-main-type-commonjs/package.json @@ -0,0 +1,4 @@ +{ + "main": "entry", + "type": "commonjs" +} diff --git a/test/js/node/test/fixtures/es-module-specifiers/node_modules/implicit-main-type-module/entry.js b/test/js/node/test/fixtures/es-module-specifiers/node_modules/implicit-main-type-module/entry.js new file mode 100644 index 0000000000..06db4db158 --- /dev/null +++ b/test/js/node/test/fixtures/es-module-specifiers/node_modules/implicit-main-type-module/entry.js @@ -0,0 +1 @@ +export default 'cjs'; diff --git a/test/js/node/test/fixtures/es-module-specifiers/node_modules/implicit-main-type-module/entry.mjs b/test/js/node/test/fixtures/es-module-specifiers/node_modules/implicit-main-type-module/entry.mjs new file mode 100644 index 0000000000..914e3a97d5 --- /dev/null +++ b/test/js/node/test/fixtures/es-module-specifiers/node_modules/implicit-main-type-module/entry.mjs @@ -0,0 +1 @@ +export default 'esm'; diff --git a/test/js/node/test/fixtures/es-module-specifiers/node_modules/implicit-main-type-module/package.json b/test/js/node/test/fixtures/es-module-specifiers/node_modules/implicit-main-type-module/package.json new file mode 100644 index 0000000000..5710280bad --- /dev/null +++ b/test/js/node/test/fixtures/es-module-specifiers/node_modules/implicit-main-type-module/package.json @@ -0,0 +1,4 @@ +{ + "main": "entry", + "type": "module" +} diff --git a/test/js/node/test/fixtures/es-module-specifiers/node_modules/implicit-main/entry.js b/test/js/node/test/fixtures/es-module-specifiers/node_modules/implicit-main/entry.js new file mode 100644 index 0000000000..b2825bd3c9 --- /dev/null +++ b/test/js/node/test/fixtures/es-module-specifiers/node_modules/implicit-main/entry.js @@ -0,0 +1 @@ +module.exports = 'cjs'; diff --git a/test/js/node/test/fixtures/es-module-specifiers/node_modules/implicit-main/entry.mjs b/test/js/node/test/fixtures/es-module-specifiers/node_modules/implicit-main/entry.mjs new file mode 100644 index 0000000000..914e3a97d5 --- /dev/null +++ b/test/js/node/test/fixtures/es-module-specifiers/node_modules/implicit-main/entry.mjs @@ -0,0 +1 @@ +export default 'esm'; diff --git a/test/js/node/test/fixtures/es-module-specifiers/node_modules/implicit-main/package.json b/test/js/node/test/fixtures/es-module-specifiers/node_modules/implicit-main/package.json new file mode 100644 index 0000000000..5c07cf41bb --- /dev/null +++ b/test/js/node/test/fixtures/es-module-specifiers/node_modules/implicit-main/package.json @@ -0,0 +1,3 @@ +{ + "main": "entry" +} diff --git a/test/js/node/test/fixtures/es-module-specifiers/node_modules/no-main-field/index.js b/test/js/node/test/fixtures/es-module-specifiers/node_modules/no-main-field/index.js new file mode 100644 index 0000000000..528a6ff2ac --- /dev/null +++ b/test/js/node/test/fixtures/es-module-specifiers/node_modules/no-main-field/index.js @@ -0,0 +1,2 @@ +'use strict'; +module.exports = 'no main field'; diff --git a/test/js/node/test/fixtures/es-module-specifiers/node_modules/no-main-field/package.json b/test/js/node/test/fixtures/es-module-specifiers/node_modules/no-main-field/package.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/test/js/node/test/fixtures/es-module-specifiers/node_modules/no-main-field/package.json @@ -0,0 +1 @@ +{} diff --git a/test/js/node/test/fixtures/es-modules/cjs-exports.mjs b/test/js/node/test/fixtures/es-modules/cjs-exports.mjs index 6001ce0636..b89420baa0 100644 --- a/test/js/node/test/fixtures/es-modules/cjs-exports.mjs +++ b/test/js/node/test/fixtures/es-modules/cjs-exports.mjs @@ -3,7 +3,8 @@ import { strictEqual, deepEqual } from 'assert'; import m, { π } from './exports-cases.js'; import * as ns from './exports-cases.js'; -deepEqual(Object.keys(ns), ['?invalid', 'default', 'invalid identifier', 'isObject', 'package', 'z', 'π', '\u{d83c}\u{df10}']); +deepEqual(Object.keys(ns), ['?invalid', 'default', 'invalid identifier', 'isObject', 'module.exports', 'package', 'z', 'π', '\u{d83c}\u{df10}']); +strictEqual(ns['module.exports'], ns.default); strictEqual(π, 'yes'); strictEqual(typeof m.isObject, 'undefined'); strictEqual(m.π, 'yes'); @@ -21,7 +22,8 @@ strictEqual(typeof m2, 'object'); strictEqual(m2.default, 'the default'); strictEqual(ns2.__esModule, true); strictEqual(ns2.name, 'name'); -deepEqual(Object.keys(ns2), ['__esModule', 'case2', 'default', 'name', 'pi']); +strictEqual(ns2['module.exports'], ns2.default); +deepEqual(Object.keys(ns2), ['__esModule', 'case2', 'default', 'module.exports', 'name', 'pi']); import m3, { __esModule as __esModule3, name as name3 } from './exports-cases3.js'; import * as ns3 from './exports-cases3.js'; @@ -32,5 +34,6 @@ deepEqual(Object.keys(m3), ['name', 'default', 'pi', 'case2']); strictEqual(ns3.__esModule, true); strictEqual(ns3.name, 'name'); strictEqual(ns3.case2, 'case2'); +strictEqual(ns3['module.exports'], ns3.default); console.log('ok'); diff --git a/test/js/node/test/fixtures/es-modules/deprecated-folders-ignore/node_modules/pkg/m.js b/test/js/node/test/fixtures/es-modules/deprecated-folders-ignore/node_modules/pkg/m.js new file mode 100644 index 0000000000..7646bbd17d --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/deprecated-folders-ignore/node_modules/pkg/m.js @@ -0,0 +1 @@ +export default null; diff --git a/test/js/node/test/fixtures/es-modules/deprecated-folders-ignore/node_modules/pkg/package.json b/test/js/node/test/fixtures/es-modules/deprecated-folders-ignore/node_modules/pkg/package.json new file mode 100644 index 0000000000..c3baf35ea9 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/deprecated-folders-ignore/node_modules/pkg/package.json @@ -0,0 +1,7 @@ +{ + "exports": { + "./folder/": "./" + }, + "type": "module" +} + diff --git a/test/js/node/test/fixtures/es-modules/dynamic-import/node_modules/deps/mod.js b/test/js/node/test/fixtures/es-modules/dynamic-import/node_modules/deps/mod.js new file mode 100644 index 0000000000..0554fa3d5c --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/dynamic-import/node_modules/deps/mod.js @@ -0,0 +1,2 @@ +export const hello = 'world'; + diff --git a/test/js/node/test/fixtures/es-modules/dynamic-import/node_modules/deps/package.json b/test/js/node/test/fixtures/es-modules/dynamic-import/node_modules/deps/package.json new file mode 100644 index 0000000000..8f7954154d --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/dynamic-import/node_modules/deps/package.json @@ -0,0 +1,4 @@ +{ + "type": "module", + "main": "mod.js" +} diff --git a/test/js/node/test/fixtures/es-modules/export-es-module-2.mjs b/test/js/node/test/fixtures/es-modules/export-es-module-2.mjs new file mode 100644 index 0000000000..81f61095ce --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/export-es-module-2.mjs @@ -0,0 +1,2 @@ +export const __esModule = false; +export default { hello: 'world' }; diff --git a/test/js/node/test/fixtures/es-modules/export-es-module.mjs b/test/js/node/test/fixtures/es-modules/export-es-module.mjs new file mode 100644 index 0000000000..a85dea6c5e --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/export-es-module.mjs @@ -0,0 +1,2 @@ +export const __esModule = 'test'; +export default { hello: 'world' }; diff --git a/test/js/node/test/fixtures/es-modules/exports-both/node_modules/dep/mod.cjs b/test/js/node/test/fixtures/es-modules/exports-both/node_modules/dep/mod.cjs new file mode 100644 index 0000000000..267c18747d --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/exports-both/node_modules/dep/mod.cjs @@ -0,0 +1 @@ +module.exports = { type: "cjs" }; diff --git a/test/js/node/test/fixtures/es-modules/exports-both/node_modules/dep/mod.mjs b/test/js/node/test/fixtures/es-modules/exports-both/node_modules/dep/mod.mjs new file mode 100644 index 0000000000..ba57355b40 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/exports-both/node_modules/dep/mod.mjs @@ -0,0 +1,2 @@ +export const type = "mjs"; + diff --git a/test/js/node/test/fixtures/es-modules/exports-both/node_modules/dep/package.json b/test/js/node/test/fixtures/es-modules/exports-both/node_modules/dep/package.json new file mode 100644 index 0000000000..d4be8cb35e --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/exports-both/node_modules/dep/package.json @@ -0,0 +1,8 @@ +{ + "exports": { + ".": { + "import": "./mod.mjs", + "require": "./mod.cjs" + } + } +} diff --git a/test/js/node/test/fixtures/es-modules/exports-import-default/node_modules/dep/mod.js b/test/js/node/test/fixtures/es-modules/exports-import-default/node_modules/dep/mod.js new file mode 100644 index 0000000000..267c18747d --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/exports-import-default/node_modules/dep/mod.js @@ -0,0 +1 @@ +module.exports = { type: "cjs" }; diff --git a/test/js/node/test/fixtures/es-modules/exports-import-default/node_modules/dep/mod.mjs b/test/js/node/test/fixtures/es-modules/exports-import-default/node_modules/dep/mod.mjs new file mode 100644 index 0000000000..ba57355b40 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/exports-import-default/node_modules/dep/mod.mjs @@ -0,0 +1,2 @@ +export const type = "mjs"; + diff --git a/test/js/node/test/fixtures/es-modules/exports-import-default/node_modules/dep/package.json b/test/js/node/test/fixtures/es-modules/exports-import-default/node_modules/dep/package.json new file mode 100644 index 0000000000..de60e166d6 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/exports-import-default/node_modules/dep/package.json @@ -0,0 +1,8 @@ +{ + "exports": { + ".": { + "import": "./mod.mjs", + "default": "./mod.js" + } + } +} diff --git a/test/js/node/test/fixtures/es-modules/exports-import-only/node_modules/dep/mod.js b/test/js/node/test/fixtures/es-modules/exports-import-only/node_modules/dep/mod.js new file mode 100644 index 0000000000..e25304b3a9 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/exports-import-only/node_modules/dep/mod.js @@ -0,0 +1,2 @@ +export const type = 'mjs'; + diff --git a/test/js/node/test/fixtures/es-modules/exports-import-only/node_modules/dep/package.json b/test/js/node/test/fixtures/es-modules/exports-import-only/node_modules/dep/package.json new file mode 100644 index 0000000000..7b208f585f --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/exports-import-only/node_modules/dep/package.json @@ -0,0 +1,8 @@ +{ + "type": "module", + "exports": { + ".": { + "import": "./mod.js" + } + } +} diff --git a/test/js/node/test/fixtures/es-modules/exports-require-only/node_modules/dep/mod.js b/test/js/node/test/fixtures/es-modules/exports-require-only/node_modules/dep/mod.js new file mode 100644 index 0000000000..267c18747d --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/exports-require-only/node_modules/dep/mod.js @@ -0,0 +1 @@ +module.exports = { type: "cjs" }; diff --git a/test/js/node/test/fixtures/es-modules/exports-require-only/node_modules/dep/package.json b/test/js/node/test/fixtures/es-modules/exports-require-only/node_modules/dep/package.json new file mode 100644 index 0000000000..134ee945df --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/exports-require-only/node_modules/dep/package.json @@ -0,0 +1,7 @@ +{ + "exports": { + ".": { + "require": "./mod.js" + } + } +} diff --git a/test/js/node/test/fixtures/es-modules/import-data-url.mjs b/test/js/node/test/fixtures/es-modules/import-data-url.mjs new file mode 100644 index 0000000000..18a2ca4486 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/import-data-url.mjs @@ -0,0 +1 @@ +import "data:text/javascript;export * from \"node:os\""; diff --git a/test/js/node/test/fixtures/es-modules/loose.js b/test/js/node/test/fixtures/es-modules/loose.js index 69147a3b8c..251d6e538a 100644 --- a/test/js/node/test/fixtures/es-modules/loose.js +++ b/test/js/node/test/fixtures/es-modules/loose.js @@ -1,3 +1,2 @@ -// This file can be run or imported only if `--experimental-default-type=module` is set. export default 'module'; console.log('executed'); diff --git a/test/js/node/test/fixtures/es-modules/module-condition/dynamic_import.js b/test/js/node/test/fixtures/es-modules/module-condition/dynamic_import.js new file mode 100644 index 0000000000..7c4cd42d70 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/module-condition/dynamic_import.js @@ -0,0 +1,5 @@ +function load(id) { + return import(id); +} + +export { load as import }; diff --git a/test/js/node/test/fixtures/es-modules/module-condition/import.mjs b/test/js/node/test/fixtures/es-modules/module-condition/import.mjs new file mode 100644 index 0000000000..ae12fbf142 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/module-condition/import.mjs @@ -0,0 +1,7 @@ +export { resolved as import_module_require } from 'import-module-require'; +export { resolved as module_and_import } from 'module-and-import'; +export { resolved as module_and_require } from 'module-and-require'; +export { resolved as module_import_require } from 'module-import-require'; +export { resolved as module_only } from 'module-only'; +export { resolved as module_require_import } from 'module-require-import'; +export { resolved as require_module_import } from 'require-module-import'; diff --git a/test/js/node/test/fixtures/es-modules/module-condition/node_modules/import-module-require/import.js b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/import-module-require/import.js new file mode 100644 index 0000000000..58f10e20bf --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/import-module-require/import.js @@ -0,0 +1 @@ +export const resolved = 'import'; \ No newline at end of file diff --git a/test/js/node/test/fixtures/es-modules/module-condition/node_modules/import-module-require/module.js b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/import-module-require/module.js new file mode 100644 index 0000000000..136ec680a7 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/import-module-require/module.js @@ -0,0 +1 @@ +export const resolved = 'module'; \ No newline at end of file diff --git a/test/js/node/test/fixtures/es-modules/module-condition/node_modules/import-module-require/package.json b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/import-module-require/package.json new file mode 100644 index 0000000000..46a096c2e7 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/import-module-require/package.json @@ -0,0 +1,11 @@ +{ + "type": "module", + "exports": { + "node": { + "import": "./import.js", + "module-sync": "./module.js", + "require": "./require.cjs" + }, + "default": "./module.js" + } +} \ No newline at end of file diff --git a/test/js/node/test/fixtures/es-modules/module-condition/node_modules/import-module-require/require.cjs b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/import-module-require/require.cjs new file mode 100644 index 0000000000..6dd2c2ec97 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/import-module-require/require.cjs @@ -0,0 +1 @@ +exports.resolved = 'require'; diff --git a/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-and-import/import.js b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-and-import/import.js new file mode 100644 index 0000000000..58f10e20bf --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-and-import/import.js @@ -0,0 +1 @@ +export const resolved = 'import'; \ No newline at end of file diff --git a/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-and-import/module.js b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-and-import/module.js new file mode 100644 index 0000000000..136ec680a7 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-and-import/module.js @@ -0,0 +1 @@ +export const resolved = 'module'; \ No newline at end of file diff --git a/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-and-import/package.json b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-and-import/package.json new file mode 100644 index 0000000000..4425147f7d --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-and-import/package.json @@ -0,0 +1,10 @@ +{ + "type": "module", + "exports": { + "node": { + "module-sync": "./module.js", + "import": "./import.js" + }, + "default": "./module.js" + } +} diff --git a/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-and-require/module.js b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-and-require/module.js new file mode 100644 index 0000000000..136ec680a7 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-and-require/module.js @@ -0,0 +1 @@ +export const resolved = 'module'; \ No newline at end of file diff --git a/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-and-require/package.json b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-and-require/package.json new file mode 100644 index 0000000000..57598fb501 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-and-require/package.json @@ -0,0 +1,10 @@ +{ + "type": "module", + "exports": { + "node": { + "module-sync": "./module.js", + "require": "./require.cjs" + }, + "default": "./module.js" + } +} \ No newline at end of file diff --git a/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-and-require/require.cjs b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-and-require/require.cjs new file mode 100644 index 0000000000..6dd2c2ec97 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-and-require/require.cjs @@ -0,0 +1 @@ +exports.resolved = 'require'; diff --git a/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-import-require/import.js b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-import-require/import.js new file mode 100644 index 0000000000..58f10e20bf --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-import-require/import.js @@ -0,0 +1 @@ +export const resolved = 'import'; \ No newline at end of file diff --git a/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-import-require/module.js b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-import-require/module.js new file mode 100644 index 0000000000..136ec680a7 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-import-require/module.js @@ -0,0 +1 @@ +export const resolved = 'module'; \ No newline at end of file diff --git a/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-import-require/package.json b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-import-require/package.json new file mode 100644 index 0000000000..bbc8c0d286 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-import-require/package.json @@ -0,0 +1,11 @@ +{ + "type": "module", + "exports": { + "node": { + "module-sync": "./module.js", + "import": "./import.js", + "require": "./require.cjs" + }, + "default": "./module.js" + } +} \ No newline at end of file diff --git a/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-import-require/require.cjs b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-import-require/require.cjs new file mode 100644 index 0000000000..6dd2c2ec97 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-import-require/require.cjs @@ -0,0 +1 @@ +exports.resolved = 'require'; diff --git a/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-only/module.js b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-only/module.js new file mode 100644 index 0000000000..136ec680a7 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-only/module.js @@ -0,0 +1 @@ +export const resolved = 'module'; \ No newline at end of file diff --git a/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-only/package.json b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-only/package.json new file mode 100644 index 0000000000..2d29bbdf32 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-only/package.json @@ -0,0 +1,6 @@ +{ + "type": "module", + "exports": { + "module-sync": "./module.js" + } +} diff --git a/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-require-import/import.js b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-require-import/import.js new file mode 100644 index 0000000000..58f10e20bf --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-require-import/import.js @@ -0,0 +1 @@ +export const resolved = 'import'; \ No newline at end of file diff --git a/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-require-import/module.js b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-require-import/module.js new file mode 100644 index 0000000000..136ec680a7 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-require-import/module.js @@ -0,0 +1 @@ +export const resolved = 'module'; \ No newline at end of file diff --git a/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-require-import/package.json b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-require-import/package.json new file mode 100644 index 0000000000..1490f04b27 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-require-import/package.json @@ -0,0 +1,11 @@ +{ + "type": "module", + "exports": { + "node": { + "module-sync": "./module.js", + "require": "./require.cjs", + "import": "./import.js" + }, + "default": "./module.js" + } +} diff --git a/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-require-import/require.cjs b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-require-import/require.cjs new file mode 100644 index 0000000000..f5bf7ed329 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/module-require-import/require.cjs @@ -0,0 +1 @@ +export const resolved = 'require'; diff --git a/test/js/node/test/fixtures/es-modules/module-condition/node_modules/require-module-import/import.js b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/require-module-import/import.js new file mode 100644 index 0000000000..58f10e20bf --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/require-module-import/import.js @@ -0,0 +1 @@ +export const resolved = 'import'; \ No newline at end of file diff --git a/test/js/node/test/fixtures/es-modules/module-condition/node_modules/require-module-import/module.js b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/require-module-import/module.js new file mode 100644 index 0000000000..136ec680a7 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/require-module-import/module.js @@ -0,0 +1 @@ +export const resolved = 'module'; \ No newline at end of file diff --git a/test/js/node/test/fixtures/es-modules/module-condition/node_modules/require-module-import/package.json b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/require-module-import/package.json new file mode 100644 index 0000000000..b62f96c997 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/require-module-import/package.json @@ -0,0 +1,11 @@ +{ + "type": "module", + "exports": { + "node": { + "require": "./require.cjs", + "module-sync": "./module.js", + "import": "./module.js" + }, + "default": "./module.js" + } +} diff --git a/test/js/node/test/fixtures/es-modules/module-condition/node_modules/require-module-import/require.cjs b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/require-module-import/require.cjs new file mode 100644 index 0000000000..6dd2c2ec97 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/module-condition/node_modules/require-module-import/require.cjs @@ -0,0 +1 @@ +exports.resolved = 'require'; diff --git a/test/js/node/test/fixtures/es-modules/module-condition/require.cjs b/test/js/node/test/fixtures/es-modules/module-condition/require.cjs new file mode 100644 index 0000000000..2457758a98 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/module-condition/require.cjs @@ -0,0 +1 @@ +exports.require = require; diff --git a/test/js/node/test/fixtures/es-modules/package-cjs-named-error/node_modules/deep-fail/index.js b/test/js/node/test/fixtures/es-modules/package-cjs-named-error/node_modules/deep-fail/index.js new file mode 100644 index 0000000000..40c512ab0e --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/package-cjs-named-error/node_modules/deep-fail/index.js @@ -0,0 +1,3 @@ +module.exports = { + comeOn: 'fhqwhgads' +}; diff --git a/test/js/node/test/fixtures/es-modules/package-cjs-named-error/node_modules/deep-fail/package.json b/test/js/node/test/fixtures/es-modules/package-cjs-named-error/node_modules/deep-fail/package.json new file mode 100644 index 0000000000..a52e9923b0 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/package-cjs-named-error/node_modules/deep-fail/package.json @@ -0,0 +1,4 @@ +{ + "name": "deep-fail", + "main": "index.mjs" +} diff --git a/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-type-module/noext-esm b/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-type-module/noext-esm new file mode 100644 index 0000000000..251d6e538a --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-type-module/noext-esm @@ -0,0 +1,2 @@ +export default 'module'; +console.log('executed'); diff --git a/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-type-module/noext-wasm b/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-type-module/noext-wasm new file mode 100644 index 0000000000..9e035904b2 Binary files /dev/null and b/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-type-module/noext-wasm differ diff --git a/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-type-module/package.json b/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-type-module/package.json new file mode 100644 index 0000000000..8d155c74ef --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-type-module/package.json @@ -0,0 +1,8 @@ +{ + "name": "dep-with-package-json-type-module", + "type": "module", + "version": "1.0.0", + "exports": { + "./*": "./*" + } +} diff --git a/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-type-module/wasm-dep.mjs b/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-type-module/wasm-dep.mjs new file mode 100644 index 0000000000..a0e28aa17b --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-type-module/wasm-dep.mjs @@ -0,0 +1,15 @@ +import { strictEqual } from 'assert'; + +export function jsFn () { + state = 'WASM JS Function Executed'; + return 42; +} + +export let state = 'JS Function Executed'; + +export function jsInitFn () { + strictEqual(state, 'JS Function Executed'); + state = 'WASM Start Executed'; +} + +console.log('executed'); diff --git a/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-without-type/dep.js b/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-without-type/dep.js new file mode 100644 index 0000000000..0d702867cd --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-without-type/dep.js @@ -0,0 +1,2 @@ +// Controlling package.json has no "type" field -> should still be CommonJS as it is in node_modules +module.exports = 42; diff --git a/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-without-type/noext-cjs b/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-without-type/noext-cjs new file mode 100644 index 0000000000..7712b3bad5 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-without-type/noext-cjs @@ -0,0 +1,3 @@ +// No package.json -> should still be CommonJS as it is in node_modules +module.exports = 42; +console.log('executed'); diff --git a/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-without-type/package.json b/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-without-type/package.json new file mode 100644 index 0000000000..1b83367ebe --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-without-type/package.json @@ -0,0 +1,7 @@ +{ + "name": "dep-with-package-json-without-type", + "version": "1.0.0", + "exports": { + "./*": "./*" + } +} diff --git a/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-without-type/run.js b/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-without-type/run.js new file mode 100644 index 0000000000..7712b3bad5 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-without-type/run.js @@ -0,0 +1,3 @@ +// No package.json -> should still be CommonJS as it is in node_modules +module.exports = 42; +console.log('executed'); diff --git a/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-without-package-json/dep.js b/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-without-package-json/dep.js new file mode 100644 index 0000000000..7b04e8b380 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-without-package-json/dep.js @@ -0,0 +1,2 @@ +// No package.json -> should still be CommonJS as it is in node_modules +module.exports = 42; diff --git a/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-without-package-json/noext-cjs b/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-without-package-json/noext-cjs new file mode 100644 index 0000000000..7712b3bad5 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-without-package-json/noext-cjs @@ -0,0 +1,3 @@ +// No package.json -> should still be CommonJS as it is in node_modules +module.exports = 42; +console.log('executed'); diff --git a/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-without-package-json/run.js b/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-without-package-json/run.js new file mode 100644 index 0000000000..7712b3bad5 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/package-type-module/node_modules/dep-without-package-json/run.js @@ -0,0 +1,3 @@ +// No package.json -> should still be CommonJS as it is in node_modules +module.exports = 42; +console.log('executed'); diff --git a/test/js/node/test/fixtures/es-modules/package-without-type/noext-esm b/test/js/node/test/fixtures/es-modules/package-without-type/noext-esm index 69147a3b8c..251d6e538a 100644 --- a/test/js/node/test/fixtures/es-modules/package-without-type/noext-esm +++ b/test/js/node/test/fixtures/es-modules/package-without-type/noext-esm @@ -1,3 +1,2 @@ -// This file can be run or imported only if `--experimental-default-type=module` is set. export default 'module'; console.log('executed'); diff --git a/test/js/node/test/fixtures/es-modules/print-entrypoint.mjs b/test/js/node/test/fixtures/es-modules/print-entrypoint.mjs new file mode 100644 index 0000000000..d9536a69b3 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/print-entrypoint.mjs @@ -0,0 +1 @@ +console.log(import.meta.url); diff --git a/test/js/node/test/fixtures/es-modules/reference-error-esm.js b/test/js/node/test/fixtures/es-modules/reference-error-esm.js new file mode 100644 index 0000000000..baf773c789 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/reference-error-esm.js @@ -0,0 +1,5 @@ +// This module is invalid in both ESM and CJS, because +// 'exports' are not defined in ESM, while require cannot be +// redeclared in CJS. +Object.defineProperty(exports, "__esModule", { value: true }); +const require = () => {}; diff --git a/test/js/node/test/fixtures/es-modules/require-and-import/node_modules/dep/mod.js b/test/js/node/test/fixtures/es-modules/require-and-import/node_modules/dep/mod.js new file mode 100644 index 0000000000..0554fa3d5c --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/require-and-import/node_modules/dep/mod.js @@ -0,0 +1,2 @@ +export const hello = 'world'; + diff --git a/test/js/node/test/fixtures/es-modules/require-and-import/node_modules/dep/package.json b/test/js/node/test/fixtures/es-modules/require-and-import/node_modules/dep/package.json new file mode 100644 index 0000000000..7aeabf8c45 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/require-and-import/node_modules/dep/package.json @@ -0,0 +1,5 @@ +{ + "type": "module", + "main": "mod.js" +} + diff --git a/test/js/node/test/fixtures/es-modules/require-esm-throws-with-loaders.js b/test/js/node/test/fixtures/es-modules/require-esm-throws-with-loaders.js new file mode 100644 index 0000000000..79c5cf96c1 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/require-esm-throws-with-loaders.js @@ -0,0 +1,8 @@ +'use strict'; +const { readFile, __fromLoader } = require('fs'); +const assert = require('assert'); + +assert.throws(() => require('./test-esm-ok.mjs'), { code: 'ERR_REQUIRE_ESM' }); + +assert(readFile); +assert(__fromLoader); diff --git a/test/js/node/test/fixtures/es-modules/require-module.js b/test/js/node/test/fixtures/es-modules/require-module.js new file mode 100644 index 0000000000..5a36590fc6 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/require-module.js @@ -0,0 +1 @@ +require('./message.mjs'); diff --git a/test/js/node/test/fixtures/es-modules/runtime-error-esm.js b/test/js/node/test/fixtures/es-modules/runtime-error-esm.js new file mode 100644 index 0000000000..1df3cc469a --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/runtime-error-esm.js @@ -0,0 +1,2 @@ +import 'node:fs'; // Forces it to be recognized as ESM. +throw new Error('hello'); diff --git a/test/js/node/test/fixtures/es-modules/synchronous-rejection-esm.js b/test/js/node/test/fixtures/es-modules/synchronous-rejection-esm.js new file mode 100644 index 0000000000..34d066037e --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/synchronous-rejection-esm.js @@ -0,0 +1,2 @@ +import 'node:fs'; // Forces it to be recognized as ESM. +Promise.reject('reject!'); diff --git a/test/js/node/test/fixtures/es-modules/test_node_modules/import-import-require-esm.mjs b/test/js/node/test/fixtures/es-modules/test_node_modules/import-import-require-esm.mjs new file mode 100644 index 0000000000..d470088c38 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/test_node_modules/import-import-require-esm.mjs @@ -0,0 +1,2 @@ +import mod from 'import-require-esm'; +console.log(mod.hello); diff --git a/test/js/node/test/fixtures/es-modules/test_node_modules/import-require-esm.mjs b/test/js/node/test/fixtures/es-modules/test_node_modules/import-require-esm.mjs new file mode 100644 index 0000000000..2ad346de9e --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/test_node_modules/import-require-esm.mjs @@ -0,0 +1,2 @@ +import mod from 'require-esm'; +console.log(mod.hello); diff --git a/test/js/node/test/fixtures/es-modules/test_node_modules/node_modules/esm/index.js b/test/js/node/test/fixtures/es-modules/test_node_modules/node_modules/esm/index.js new file mode 100644 index 0000000000..35f468bf48 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/test_node_modules/node_modules/esm/index.js @@ -0,0 +1 @@ +export const hello = 'world'; diff --git a/test/js/node/test/fixtures/es-modules/test_node_modules/node_modules/esm/package.json b/test/js/node/test/fixtures/es-modules/test_node_modules/node_modules/esm/package.json new file mode 100644 index 0000000000..07aec65d5a --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/test_node_modules/node_modules/esm/package.json @@ -0,0 +1,4 @@ +{ + "type": "module", + "main": "index.js" +} diff --git a/test/js/node/test/fixtures/es-modules/test_node_modules/node_modules/import-require-esm/index.js b/test/js/node/test/fixtures/es-modules/test_node_modules/node_modules/import-require-esm/index.js new file mode 100644 index 0000000000..918bb5d559 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/test_node_modules/node_modules/import-require-esm/index.js @@ -0,0 +1,2 @@ +import mod from 'require-esm'; +export default mod; diff --git a/test/js/node/test/fixtures/es-modules/test_node_modules/node_modules/import-require-esm/package.json b/test/js/node/test/fixtures/es-modules/test_node_modules/node_modules/import-require-esm/package.json new file mode 100644 index 0000000000..07aec65d5a --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/test_node_modules/node_modules/import-require-esm/package.json @@ -0,0 +1,4 @@ +{ + "type": "module", + "main": "index.js" +} diff --git a/test/js/node/test/fixtures/es-modules/test_node_modules/node_modules/require-esm/index.js b/test/js/node/test/fixtures/es-modules/test_node_modules/node_modules/require-esm/index.js new file mode 100644 index 0000000000..ca6f0c264a --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/test_node_modules/node_modules/require-esm/index.js @@ -0,0 +1,2 @@ +module.exports = require('esm'); + diff --git a/test/js/node/test/fixtures/es-modules/test_node_modules/require-esm.js b/test/js/node/test/fixtures/es-modules/test_node_modules/require-esm.js new file mode 100644 index 0000000000..60ad3f7fff --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/test_node_modules/require-esm.js @@ -0,0 +1,2 @@ +const { hello } = require('esm'); +console.log(hello); diff --git a/test/js/node/test/fixtures/es-modules/test_node_modules/require-require-esm.js b/test/js/node/test/fixtures/es-modules/test_node_modules/require-require-esm.js new file mode 100644 index 0000000000..9fe255dce2 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/test_node_modules/require-require-esm.js @@ -0,0 +1,2 @@ +const { hello } = require('require-esm'); +console.log(hello); diff --git a/test/js/node/test/fixtures/es-modules/tla/await-export-promise.mjs b/test/js/node/test/fixtures/es-modules/tla/await-export-promise.mjs new file mode 100644 index 0000000000..0129793e42 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/tla/await-export-promise.mjs @@ -0,0 +1,4 @@ +import promise from './export-promise.mjs'; +let result; +result = await promise; +export default result; diff --git a/test/js/node/test/fixtures/es-modules/tla/export-async.mjs b/test/js/node/test/fixtures/es-modules/tla/export-async.mjs new file mode 100644 index 0000000000..b6de9a5a5f --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/tla/export-async.mjs @@ -0,0 +1,2 @@ +let hello = await Promise.resolve('world'); +export { hello }; diff --git a/test/js/node/test/fixtures/es-modules/tla/export-promise.mjs b/test/js/node/test/fixtures/es-modules/tla/export-promise.mjs new file mode 100644 index 0000000000..74864d232e --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/tla/export-promise.mjs @@ -0,0 +1,8 @@ +let exportedResolve; +let exportedReject; +const promise = new Promise((resolve, reject) => { + exportedResolve = resolve; + exportedReject = reject; +}); +export default promise; +export { exportedResolve, exportedReject }; diff --git a/test/js/node/test/fixtures/es-modules/tla/unresolved.js b/test/js/node/test/fixtures/es-modules/tla/unresolved.js new file mode 100644 index 0000000000..231a8cd634 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/tla/unresolved.js @@ -0,0 +1 @@ +await new Promise(() => {}); diff --git a/test/js/node/test/fixtures/es-modules/transpiled-cjs-require-module/node_modules/logger/logger.mjs b/test/js/node/test/fixtures/es-modules/transpiled-cjs-require-module/node_modules/logger/logger.mjs new file mode 100644 index 0000000000..abcac43fff --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/transpiled-cjs-require-module/node_modules/logger/logger.mjs @@ -0,0 +1,2 @@ +export default class Logger { log(val) { console.log(val); } } +export function log(logger, val) { logger.log(val) }; diff --git a/test/js/node/test/fixtures/es-modules/transpiled-cjs-require-module/node_modules/logger/package.json b/test/js/node/test/fixtures/es-modules/transpiled-cjs-require-module/node_modules/logger/package.json new file mode 100644 index 0000000000..56c237df95 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/transpiled-cjs-require-module/node_modules/logger/package.json @@ -0,0 +1,4 @@ +{ + "name": "logger", + "main": "logger.mjs" +} \ No newline at end of file diff --git a/test/js/node/test/fixtures/es-modules/transpiled-cjs-require-module/src/import-both.mjs b/test/js/node/test/fixtures/es-modules/transpiled-cjs-require-module/src/import-both.mjs new file mode 100644 index 0000000000..7773ccb2bc --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/transpiled-cjs-require-module/src/import-both.mjs @@ -0,0 +1,2 @@ +import Logger, { log } from 'logger'; +log(new Logger(), 'import both'); diff --git a/test/js/node/test/fixtures/es-modules/transpiled-cjs-require-module/src/import-default.mjs b/test/js/node/test/fixtures/es-modules/transpiled-cjs-require-module/src/import-default.mjs new file mode 100644 index 0000000000..16c123bbcc --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/transpiled-cjs-require-module/src/import-default.mjs @@ -0,0 +1,2 @@ +import Logger from 'logger'; +new Logger().log('import default'); diff --git a/test/js/node/test/fixtures/es-modules/transpiled-cjs-require-module/src/import-named.mjs b/test/js/node/test/fixtures/es-modules/transpiled-cjs-require-module/src/import-named.mjs new file mode 100644 index 0000000000..489d0886e5 --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/transpiled-cjs-require-module/src/import-named.mjs @@ -0,0 +1,2 @@ +import { log } from 'logger'; +log(console, 'import named'); diff --git a/test/js/node/test/fixtures/es-modules/transpiled-cjs-require-module/transpile.cjs b/test/js/node/test/fixtures/es-modules/transpiled-cjs-require-module/transpile.cjs new file mode 100644 index 0000000000..da9978164b --- /dev/null +++ b/test/js/node/test/fixtures/es-modules/transpiled-cjs-require-module/transpile.cjs @@ -0,0 +1,23 @@ +'use strict'; + +// This script is used to transpile ESM fixtures from the src/ directory +// to CJS modules in dist/. The transpiled CJS files are used to test +// integration of transpiled CJS modules loading real ESM. + +const { readFileSync, writeFileSync, readdirSync } = require('node:fs'); + +// We use typescript.js because it's already in the code base as a fixture. +// Most ecosystem tools follow a similar pattern, and this produces a bare +// minimum integration test for existing patterns. +const ts = require('../../snapshot/typescript'); +const { join } = require('node:path'); +const sourceDir = join(__dirname, 'src'); +const files = readdirSync(sourceDir); +for (const filename of files) { + const filePath = join(sourceDir, filename); + const source = readFileSync(filePath, 'utf8'); + const { outputText } = ts.transpileModule(source, { + compilerOptions: { module: ts.ModuleKind.NodeNext } + }); + writeFileSync(join(__dirname, 'dist', filename.replace('.mjs', '.cjs')), outputText, 'utf8'); +} diff --git a/test/js/node/test/fixtures/eval/eval_messages.js b/test/js/node/test/fixtures/eval/eval_messages.js new file mode 100644 index 0000000000..171bff06b8 --- /dev/null +++ b/test/js/node/test/fixtures/eval/eval_messages.js @@ -0,0 +1,53 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +require('../../common'); + +const spawn = require('child_process').spawn; + +function run(cmd, strict, cb) { + const args = []; + if (strict) args.push('--use_strict'); + args.push('-pe', cmd); + const child = spawn(process.execPath, args); + child.stdout.pipe(process.stdout); + child.stderr.pipe(process.stdout); + child.on('close', cb); +} + +const queue = + [ 'with(this){__filename}', + '42', + 'throw new Error("hello")', + 'var x = 100; y = x;', + 'var ______________________________________________; throw 10' ]; + +function go() { + const c = queue.shift(); + if (!c) return console.log('done'); + run(c, false, function() { + run(c, true, go); + }); +} + +go(); diff --git a/test/js/node/test/fixtures/eval/eval_messages.snapshot b/test/js/node/test/fixtures/eval/eval_messages.snapshot new file mode 100644 index 0000000000..bed1674244 --- /dev/null +++ b/test/js/node/test/fixtures/eval/eval_messages.snapshot @@ -0,0 +1,54 @@ +[eval] +[eval]:1 +with(this){__filename} +^^^^ + x The 'with' statement is not supported. All symbols in a 'with' block will have type 'any'. + ,---- + 1 | with(this){__filename} + : ^^^^ + `---- + +SyntaxError: Strict mode code may not include a with statement + +Node.js * +42 +42 +[eval]:1 +throw new Error("hello") +^ + +Error: hello + +Node.js * +[eval]:1 +throw new Error("hello") +^ + +Error: hello + +Node.js * +100 +[eval]:1 +var x = 100; y = x; + ^ + +ReferenceError: y is not defined + +Node.js * + +[eval]:1 +var ______________________________________________; throw 10 + ^ +10 +(Use `node --trace-uncaught ...` to show where the exception was thrown) + +Node.js * + +[eval]:1 +var ______________________________________________; throw 10 + ^ +10 +(Use `node --trace-uncaught ...` to show where the exception was thrown) + +Node.js * +done diff --git a/test/js/node/test/fixtures/eval/eval_typescript.js b/test/js/node/test/fixtures/eval/eval_typescript.js new file mode 100644 index 0000000000..2c96b66f70 --- /dev/null +++ b/test/js/node/test/fixtures/eval/eval_typescript.js @@ -0,0 +1,25 @@ +'use strict'; + +require('../../common'); + +const spawnSync = require('child_process').spawnSync; + +const queue = [ + 'enum Foo{};', + 'throw new SyntaxError("hello")', + 'const foo;', + 'let x: number = 100;x;', + 'const foo: string = 10;', + 'function foo(){};foo(1);', + 'interface Foo{};const foo;', + 'function foo(){ await Promise.resolve(1)};', +]; + +for (const cmd of queue) { + const args = ['--disable-warning=ExperimentalWarning', '-p', cmd]; + const result = spawnSync(process.execPath, args, { + stdio: 'pipe' + }); + process.stdout.write(result.stdout); + process.stdout.write(result.stderr); +} diff --git a/test/js/node/test/fixtures/eval/eval_typescript.snapshot b/test/js/node/test/fixtures/eval/eval_typescript.snapshot new file mode 100644 index 0000000000..074e966e51 --- /dev/null +++ b/test/js/node/test/fixtures/eval/eval_typescript.snapshot @@ -0,0 +1,48 @@ +[eval]:1 +enum Foo{}; +^^^^ + x TypeScript enum is not supported in strip-only mode + ,---- + 1 | enum Foo{}; + : ^^^^^^^^^^ + `---- + +SyntaxError: Unexpected reserved word + +Node.js * +[eval]:1 +throw new SyntaxError("hello") +^ + +SyntaxError: hello + +Node.js * +[eval]:1 +const foo; + ^^^ + +SyntaxError: Missing initializer in const declaration + +Node.js * +100 +undefined +false +[eval]:1 + ;const foo; + ^^^ + +SyntaxError: Missing initializer in const declaration + +Node.js * +[eval]:1 +function foo(){ await Promise.resolve(1)}; + ^^^^^ + x await isn't allowed in non-async function + ,---- + 1 | function foo(){ await Promise.resolve(1)}; + : ^^^^^^^ + `---- + +SyntaxError: await is only valid in async functions and the top level bodies of modules + +Node.js * diff --git a/test/js/node/test/fixtures/eval/stdin_messages.js b/test/js/node/test/fixtures/eval/stdin_messages.js new file mode 100644 index 0000000000..874b473be3 --- /dev/null +++ b/test/js/node/test/fixtures/eval/stdin_messages.js @@ -0,0 +1,54 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +require('../../common'); + +const spawn = require('child_process').spawn; + +function run(cmd, strict, cb) { + const args = []; + if (strict) args.push('--use_strict'); + args.push('-p'); + const child = spawn(process.execPath, args); + child.stdout.pipe(process.stdout); + child.stderr.pipe(process.stdout); + child.stdin.end(cmd); + child.on('close', cb); +} + +const queue = + [ 'with(this){__filename}', + '42', + 'throw new Error("hello")', + 'let x = 100; y = x;', + 'let ______________________________________________; throw 10' ]; + +function go() { + const c = queue.shift(); + if (!c) return console.log('done'); + run(c, false, function() { + run(c, true, go); + }); +} + +go(); diff --git a/test/js/node/test/fixtures/eval/stdin_messages.snapshot b/test/js/node/test/fixtures/eval/stdin_messages.snapshot new file mode 100644 index 0000000000..66bd506f75 --- /dev/null +++ b/test/js/node/test/fixtures/eval/stdin_messages.snapshot @@ -0,0 +1,54 @@ +[stdin] +[stdin]:1 +with(this){__filename} +^^^^ + x The 'with' statement is not supported. All symbols in a 'with' block will have type 'any'. + ,---- + 1 | with(this){__filename} + : ^^^^ + `---- + +SyntaxError: Strict mode code may not include a with statement + +Node.js * +42 +42 +[stdin]:1 +throw new Error("hello") +^ + +Error: hello + +Node.js * +[stdin]:1 +throw new Error("hello") +^ + +Error: hello + +Node.js * +100 +[stdin]:1 +let x = 100; y = x; + ^ + +ReferenceError: y is not defined + +Node.js * + +[stdin]:1 +let ______________________________________________; throw 10 + ^ +10 +(Use `node --trace-uncaught ...` to show where the exception was thrown) + +Node.js * + +[stdin]:1 +let ______________________________________________; throw 10 + ^ +10 +(Use `node --trace-uncaught ...` to show where the exception was thrown) + +Node.js * +done diff --git a/test/js/node/test/fixtures/eval/stdin_typescript.js b/test/js/node/test/fixtures/eval/stdin_typescript.js new file mode 100644 index 0000000000..d47c495f86 --- /dev/null +++ b/test/js/node/test/fixtures/eval/stdin_typescript.js @@ -0,0 +1,38 @@ +'use strict'; + +require('../../common'); + +const spawn = require('child_process').spawn; + +function run(cmd, strict, cb) { + const args = ['--disable-warning=ExperimentalWarning']; + if (strict) args.push('--use_strict'); + args.push('-p'); + const child = spawn(process.execPath, args); + child.stdout.pipe(process.stdout); + child.stderr.pipe(process.stdout); + child.stdin.end(cmd); + child.on('close', cb); +} + +const queue = + [ + 'enum Foo{};', + 'throw new SyntaxError("hello")', + 'const foo;', + 'let x: number = 100;x;', + 'const foo: string = 10;', + 'function foo(){};foo(1);', + 'interface Foo{};const foo;', + 'function foo(){ await Promise.resolve(1)};', + ]; + +function go() { + const c = queue.shift(); + if (!c) return console.log('done'); + run(c, false, function () { + run(c, true, go); + }); +} + +go(); diff --git a/test/js/node/test/fixtures/eval/stdin_typescript.snapshot b/test/js/node/test/fixtures/eval/stdin_typescript.snapshot new file mode 100644 index 0000000000..3e209e6db2 --- /dev/null +++ b/test/js/node/test/fixtures/eval/stdin_typescript.snapshot @@ -0,0 +1,97 @@ +[stdin]:1 +enum Foo{}; +^^^^ + x TypeScript enum is not supported in strip-only mode + ,---- + 1 | enum Foo{}; + : ^^^^^^^^^^ + `---- + +SyntaxError: Unexpected reserved word + +Node.js * +[stdin]:1 +enum Foo{}; +^^^^ + x TypeScript enum is not supported in strip-only mode + ,---- + 1 | enum Foo{}; + : ^^^^^^^^^^ + `---- + +SyntaxError: Unexpected reserved word + +Node.js * +[stdin]:1 +throw new SyntaxError("hello") +^ + +SyntaxError: hello + +Node.js * +[stdin]:1 +throw new SyntaxError("hello") +^ + +SyntaxError: hello + +Node.js * +[stdin]:1 +const foo; + ^^^ + +SyntaxError: Missing initializer in const declaration + +Node.js * +[stdin]:1 +const foo; + ^^^ + +SyntaxError: Missing initializer in const declaration + +Node.js * +100 +100 +undefined +undefined +false +false +[stdin]:1 + ;const foo; + ^^^ + +SyntaxError: Missing initializer in const declaration + +Node.js * +[stdin]:1 + ;const foo; + ^^^ + +SyntaxError: Missing initializer in const declaration + +Node.js * +[stdin]:1 +function foo(){ await Promise.resolve(1)}; + ^^^^^ + x await isn't allowed in non-async function + ,---- + 1 | function foo(){ await Promise.resolve(1)}; + : ^^^^^^^ + `---- + +SyntaxError: await is only valid in async functions and the top level bodies of modules + +Node.js * +[stdin]:1 +function foo(){ await Promise.resolve(1)}; + ^^^^^ + x await isn't allowed in non-async function + ,---- + 1 | function foo(){ await Promise.resolve(1)}; + : ^^^^^^^ + `---- + +SyntaxError: await is only valid in async functions and the top level bodies of modules + +Node.js * +done diff --git a/test/js/node/test/fixtures/get-call-sites.js b/test/js/node/test/fixtures/get-call-sites.js new file mode 100644 index 0000000000..dc52c25fab --- /dev/null +++ b/test/js/node/test/fixtures/get-call-sites.js @@ -0,0 +1,4 @@ +const util = require('node:util'); +const assert = require('node:assert'); +assert.ok(util.getCallSites().length > 1); +process.stdout.write(util.getCallSites()[0].scriptName); diff --git a/test/js/node/test/fixtures/icu/localizationData-v74.2.json b/test/js/node/test/fixtures/icu/localizationData-v74.2.json new file mode 100644 index 0000000000..65671ba5ac --- /dev/null +++ b/test/js/node/test/fixtures/icu/localizationData-v74.2.json @@ -0,0 +1,128 @@ +{ + "dateStrings": { + "en": "Fri Jul 25 1980 01:35:33 GMT+0100 (Central European Standard Time)", + "zh": "Fri Jul 25 1980 01:35:33 GMT+0100 (中欧标准时间)", + "hi": "Fri Jul 25 1980 01:35:33 GMT+0100 (मध्य यूरोपीय मानक समय)", + "es": "Fri Jul 25 1980 01:35:33 GMT+0100 (hora estándar de Europa central)", + "fr": "Fri Jul 25 1980 01:35:33 GMT+0100 (heure normale d’Europe centrale)", + "ar": "Fri Jul 25 1980 01:35:33 GMT+0100 (توقيت وسط أوروبا الرسمي)", + "bn": "Fri Jul 25 1980 01:35:33 GMT+0100 (মধ্য ইউরোপীয় মানক সময়)", + "ru": "Fri Jul 25 1980 01:35:33 GMT+0100 (Центральная Европа, стандартное время)", + "pt": "Fri Jul 25 1980 01:35:33 GMT+0100 (Horário Padrão da Europa Central)", + "ur": "Fri Jul 25 1980 01:35:33 GMT+0100 (وسطی یورپ کا معیاری وقت)", + "id": "Fri Jul 25 1980 01:35:33 GMT+0100 (Waktu Standar Eropa Tengah)", + "de": "Fri Jul 25 1980 01:35:33 GMT+0100 (Mitteleuropäische Normalzeit)", + "ja": "Fri Jul 25 1980 01:35:33 GMT+0100 (中央ヨーロッパ標準時)", + "pcm": "Fri Jul 25 1980 01:35:33 GMT+0100 (Mídúl Yúrop Fíksd Taim)", + "mr": "Fri Jul 25 1980 01:35:33 GMT+0100 (मध्‍य युरोपियन प्रमाण वेळ)", + "te": "Fri Jul 25 1980 01:35:33 GMT+0100 (సెంట్రల్ యూరోపియన్ ప్రామాణిక సమయం)" + }, + "dateTimeFormats": { + "en": "7/25/1980, 1:35:33 AM", + "zh": "1980/7/25 01:35:33", + "hi": "25/7/1980, 1:35:33 am", + "es": "25/7/1980, 1:35:33", + "fr": "25/07/1980 01:35:33", + "ar": "٢٥‏/٧‏/١٩٨٠، ١:٣٥:٣٣ ص", + "bn": "২৫/৭/১৯৮০, ১:৩৫:৩৩ AM", + "ru": "25.07.1980, 01:35:33", + "pt": "25/07/1980, 01:35:33", + "ur": "25/7/1980، 1:35:33 AM", + "id": "25/7/1980, 01.35.33", + "de": "25.7.1980, 01:35:33", + "ja": "1980/7/25 1:35:33", + "pcm": "25/7/1980 01:35:33", + "mr": "२५/७/१९८०, १:३५:३३ AM", + "te": "25/7/1980 1:35:33 AM" + }, + "dateFormats": { + "en": "7/25/1980", + "zh": "1980/7/25", + "hi": "25/7/1980", + "es": "25/7/1980", + "fr": "25/07/1980", + "ar": "٢٥‏/٧‏/١٩٨٠", + "bn": "২৫/৭/১৯৮০", + "ru": "25.07.1980", + "pt": "25/07/1980", + "ur": "25/7/1980", + "id": "25/7/1980", + "de": "25.7.1980", + "ja": "1980/7/25", + "pcm": "25/7/1980", + "mr": "२५/७/१९८०", + "te": "25/7/1980" + }, + "displayNames": { + "en": "Switzerland", + "zh": "瑞士", + "hi": "स्विट्ज़रलैंड", + "es": "Suiza", + "fr": "Suisse", + "ar": "سويسرا", + "bn": "সুইজারল্যান্ড", + "ru": "Швейцария", + "pt": "Suíça", + "ur": "سوئٹزر لینڈ", + "id": "Swiss", + "de": "Schweiz", + "ja": "スイス", + "pcm": "Swítsaland", + "mr": "स्वित्झर्लंड", + "te": "స్విట్జర్లాండ్" + }, + "numberFormats": { + "en": "275,760.913", + "zh": "275,760.913", + "hi": "2,75,760.913", + "es": "275.760,913", + "fr": "275 760,913", + "ar": "٢٧٥٬٧٦٠٫٩١٣", + "bn": "২,৭৫,৭৬০.৯১৩", + "ru": "275 760,913", + "pt": "275.760,913", + "ur": "275,760.913", + "id": "275.760,913", + "de": "275.760,913", + "ja": "275,760.913", + "pcm": "275,760.913", + "mr": "२,७५,७६०.९१३", + "te": "2,75,760.913" + }, + "pluralRules": { + "en": "other", + "zh": "other", + "hi": "one", + "es": "other", + "fr": "one", + "ar": "zero", + "bn": "one", + "ru": "many", + "pt": "one", + "ur": "other", + "id": "other", + "de": "other", + "ja": "other", + "pcm": "one", + "mr": "other", + "te": "other" + }, + "relativeTime": { + "en": "586,920.617 hours ago", + "zh": "586,920.617小时前", + "hi": "5,86,920.617 घंटे पहले", + "es": "hace 586.920,617 horas", + "fr": "il y a 586 920,617 heures", + "ar": "قبل ٥٨٦٬٩٢٠٫٦١٧ ساعة", + "bn": "৫,৮৬,৯২০.৬১৭ ঘন্টা আগে", + "ru": "586 920,617 часа назад", + "pt": "há 586.920,617 horas", + "ur": "586,920.617 گھنٹے پہلے", + "id": "586.920,617 jam yang lalu", + "de": "vor 586.920,617 Stunden", + "ja": "586,920.617 時間前", + "pcm": "586,920.617 áwa wé dọ́n pas", + "mr": "५,८६,९२०.६१७ तासांपूर्वी", + "te": "5,86,920.617 గంటల క్రితం" + } +} diff --git a/test/js/node/test/fixtures/icu/localizationData-v75.1.json b/test/js/node/test/fixtures/icu/localizationData-v75.1.json new file mode 100644 index 0000000000..65671ba5ac --- /dev/null +++ b/test/js/node/test/fixtures/icu/localizationData-v75.1.json @@ -0,0 +1,128 @@ +{ + "dateStrings": { + "en": "Fri Jul 25 1980 01:35:33 GMT+0100 (Central European Standard Time)", + "zh": "Fri Jul 25 1980 01:35:33 GMT+0100 (中欧标准时间)", + "hi": "Fri Jul 25 1980 01:35:33 GMT+0100 (मध्य यूरोपीय मानक समय)", + "es": "Fri Jul 25 1980 01:35:33 GMT+0100 (hora estándar de Europa central)", + "fr": "Fri Jul 25 1980 01:35:33 GMT+0100 (heure normale d’Europe centrale)", + "ar": "Fri Jul 25 1980 01:35:33 GMT+0100 (توقيت وسط أوروبا الرسمي)", + "bn": "Fri Jul 25 1980 01:35:33 GMT+0100 (মধ্য ইউরোপীয় মানক সময়)", + "ru": "Fri Jul 25 1980 01:35:33 GMT+0100 (Центральная Европа, стандартное время)", + "pt": "Fri Jul 25 1980 01:35:33 GMT+0100 (Horário Padrão da Europa Central)", + "ur": "Fri Jul 25 1980 01:35:33 GMT+0100 (وسطی یورپ کا معیاری وقت)", + "id": "Fri Jul 25 1980 01:35:33 GMT+0100 (Waktu Standar Eropa Tengah)", + "de": "Fri Jul 25 1980 01:35:33 GMT+0100 (Mitteleuropäische Normalzeit)", + "ja": "Fri Jul 25 1980 01:35:33 GMT+0100 (中央ヨーロッパ標準時)", + "pcm": "Fri Jul 25 1980 01:35:33 GMT+0100 (Mídúl Yúrop Fíksd Taim)", + "mr": "Fri Jul 25 1980 01:35:33 GMT+0100 (मध्‍य युरोपियन प्रमाण वेळ)", + "te": "Fri Jul 25 1980 01:35:33 GMT+0100 (సెంట్రల్ యూరోపియన్ ప్రామాణిక సమయం)" + }, + "dateTimeFormats": { + "en": "7/25/1980, 1:35:33 AM", + "zh": "1980/7/25 01:35:33", + "hi": "25/7/1980, 1:35:33 am", + "es": "25/7/1980, 1:35:33", + "fr": "25/07/1980 01:35:33", + "ar": "٢٥‏/٧‏/١٩٨٠، ١:٣٥:٣٣ ص", + "bn": "২৫/৭/১৯৮০, ১:৩৫:৩৩ AM", + "ru": "25.07.1980, 01:35:33", + "pt": "25/07/1980, 01:35:33", + "ur": "25/7/1980، 1:35:33 AM", + "id": "25/7/1980, 01.35.33", + "de": "25.7.1980, 01:35:33", + "ja": "1980/7/25 1:35:33", + "pcm": "25/7/1980 01:35:33", + "mr": "२५/७/१९८०, १:३५:३३ AM", + "te": "25/7/1980 1:35:33 AM" + }, + "dateFormats": { + "en": "7/25/1980", + "zh": "1980/7/25", + "hi": "25/7/1980", + "es": "25/7/1980", + "fr": "25/07/1980", + "ar": "٢٥‏/٧‏/١٩٨٠", + "bn": "২৫/৭/১৯৮০", + "ru": "25.07.1980", + "pt": "25/07/1980", + "ur": "25/7/1980", + "id": "25/7/1980", + "de": "25.7.1980", + "ja": "1980/7/25", + "pcm": "25/7/1980", + "mr": "२५/७/१९८०", + "te": "25/7/1980" + }, + "displayNames": { + "en": "Switzerland", + "zh": "瑞士", + "hi": "स्विट्ज़रलैंड", + "es": "Suiza", + "fr": "Suisse", + "ar": "سويسرا", + "bn": "সুইজারল্যান্ড", + "ru": "Швейцария", + "pt": "Suíça", + "ur": "سوئٹزر لینڈ", + "id": "Swiss", + "de": "Schweiz", + "ja": "スイス", + "pcm": "Swítsaland", + "mr": "स्वित्झर्लंड", + "te": "స్విట్జర్లాండ్" + }, + "numberFormats": { + "en": "275,760.913", + "zh": "275,760.913", + "hi": "2,75,760.913", + "es": "275.760,913", + "fr": "275 760,913", + "ar": "٢٧٥٬٧٦٠٫٩١٣", + "bn": "২,৭৫,৭৬০.৯১৩", + "ru": "275 760,913", + "pt": "275.760,913", + "ur": "275,760.913", + "id": "275.760,913", + "de": "275.760,913", + "ja": "275,760.913", + "pcm": "275,760.913", + "mr": "२,७५,७६०.९१३", + "te": "2,75,760.913" + }, + "pluralRules": { + "en": "other", + "zh": "other", + "hi": "one", + "es": "other", + "fr": "one", + "ar": "zero", + "bn": "one", + "ru": "many", + "pt": "one", + "ur": "other", + "id": "other", + "de": "other", + "ja": "other", + "pcm": "one", + "mr": "other", + "te": "other" + }, + "relativeTime": { + "en": "586,920.617 hours ago", + "zh": "586,920.617小时前", + "hi": "5,86,920.617 घंटे पहले", + "es": "hace 586.920,617 horas", + "fr": "il y a 586 920,617 heures", + "ar": "قبل ٥٨٦٬٩٢٠٫٦١٧ ساعة", + "bn": "৫,৮৬,৯২০.৬১৭ ঘন্টা আগে", + "ru": "586 920,617 часа назад", + "pt": "há 586.920,617 horas", + "ur": "586,920.617 گھنٹے پہلے", + "id": "586.920,617 jam yang lalu", + "de": "vor 586.920,617 Stunden", + "ja": "586,920.617 時間前", + "pcm": "586,920.617 áwa wé dọ́n pas", + "mr": "५,८६,९२०.६१७ तासांपूर्वी", + "te": "5,86,920.617 గంటల క్రితం" + } +} diff --git a/test/js/node/test/fixtures/icu/localizationData-v76.1.json b/test/js/node/test/fixtures/icu/localizationData-v76.1.json new file mode 100644 index 0000000000..cb519d2bea --- /dev/null +++ b/test/js/node/test/fixtures/icu/localizationData-v76.1.json @@ -0,0 +1,128 @@ +{ + "dateStrings": { + "en": "Fri Jul 25 1980 01:35:33 GMT+0100 (Central European Standard Time)", + "zh": "Fri Jul 25 1980 01:35:33 GMT+0100 (中欧标准时间)", + "hi": "Fri Jul 25 1980 01:35:33 GMT+0100 (मध्य यूरोपीय मानक समय)", + "es": "Fri Jul 25 1980 01:35:33 GMT+0100 (hora estándar de Europa central)", + "fr": "Fri Jul 25 1980 01:35:33 GMT+0100 (heure normale d’Europe centrale)", + "ar": "Fri Jul 25 1980 01:35:33 GMT+0100 (توقيت وسط أوروبا الرسمي)", + "bn": "Fri Jul 25 1980 01:35:33 GMT+0100 (মধ্য ইউরোপীয় মানক সময়)", + "ru": "Fri Jul 25 1980 01:35:33 GMT+0100 (Центральная Европа, стандартное время)", + "pt": "Fri Jul 25 1980 01:35:33 GMT+0100 (Horário Padrão da Europa Central)", + "ur": "Fri Jul 25 1980 01:35:33 GMT+0100 (وسطی یورپ کا معیاری وقت)", + "id": "Fri Jul 25 1980 01:35:33 GMT+0100 (Waktu Standar Eropa Tengah)", + "de": "Fri Jul 25 1980 01:35:33 GMT+0100 (Mitteleuropäische Normalzeit)", + "ja": "Fri Jul 25 1980 01:35:33 GMT+0100 (中央ヨーロッパ標準時)", + "pcm": "Fri Jul 25 1980 01:35:33 GMT+0100 (Mídúl Yúrop Fíksd Taim)", + "mr": "Fri Jul 25 1980 01:35:33 GMT+0100 (मध्‍य युरोपियन प्रमाण वेळ)", + "te": "Fri Jul 25 1980 01:35:33 GMT+0100 (సెంట్రల్ యూరోపియన్ ప్రామాణిక సమయం)" + }, + "dateTimeFormats": { + "en": "7/25/1980, 1:35:33 AM", + "zh": "1980/7/25 01:35:33", + "hi": "25/7/1980, 1:35:33 am", + "es": "25/7/1980, 1:35:33", + "fr": "25/07/1980 01:35:33", + "ar": "25‏/7‏/1980، 1:35:33 ص", + "bn": "২৫/৭/১৯৮০, ১:৩৫:৩৩ AM", + "ru": "25.07.1980, 01:35:33", + "pt": "25/07/1980, 01:35:33", + "ur": "25/7/1980، 1:35:33 AM", + "id": "25/7/1980, 01.35.33", + "de": "25.7.1980, 01:35:33", + "ja": "1980/7/25 1:35:33", + "pcm": "25/7/1980 01:35:33", + "mr": "२५/७/१९८०, १:३५:३३ AM", + "te": "25/7/1980 1:35:33 AM" + }, + "dateFormats": { + "en": "7/25/1980", + "zh": "1980/7/25", + "hi": "25/7/1980", + "es": "25/7/1980", + "fr": "25/07/1980", + "ar": "25‏/7‏/1980", + "bn": "২৫/৭/১৯৮০", + "ru": "25.07.1980", + "pt": "25/07/1980", + "ur": "25/7/1980", + "id": "25/7/1980", + "de": "25.7.1980", + "ja": "1980/7/25", + "pcm": "25/7/1980", + "mr": "२५/७/१९८०", + "te": "25/7/1980" + }, + "displayNames": { + "en": "Switzerland", + "zh": "瑞士", + "hi": "स्विट्ज़रलैंड", + "es": "Suiza", + "fr": "Suisse", + "ar": "سويسرا", + "bn": "সুইজারল্যান্ড", + "ru": "Швейцария", + "pt": "Suíça", + "ur": "سوئٹزر لینڈ", + "id": "Swiss", + "de": "Schweiz", + "ja": "スイス", + "pcm": "Swítsaland", + "mr": "स्वित्झर्लंड", + "te": "స్విట్జర్లాండ్" + }, + "numberFormats": { + "en": "275,760.913", + "zh": "275,760.913", + "hi": "2,75,760.913", + "es": "275.760,913", + "fr": "275 760,913", + "ar": "275,760.913", + "bn": "২,৭৫,৭৬০.৯১৩", + "ru": "275 760,913", + "pt": "275.760,913", + "ur": "275,760.913", + "id": "275.760,913", + "de": "275.760,913", + "ja": "275,760.913", + "pcm": "275,760.913", + "mr": "२,७५,७६०.९१३", + "te": "2,75,760.913" + }, + "pluralRules": { + "en": "other", + "zh": "other", + "hi": "one", + "es": "other", + "fr": "one", + "ar": "zero", + "bn": "one", + "ru": "many", + "pt": "one", + "ur": "other", + "id": "other", + "de": "other", + "ja": "other", + "pcm": "one", + "mr": "other", + "te": "other" + }, + "relativeTime": { + "en": "586,920.617 hours ago", + "zh": "586,920.617小时前", + "hi": "5,86,920.617 घंटे पहले", + "es": "hace 586.920,617 horas", + "fr": "il y a 586 920,617 heures", + "ar": "قبل 586,920.617 ساعة", + "bn": "৫,৮৬,৯২০.৬১৭ ঘন্টা আগে", + "ru": "586 920,617 часа назад", + "pt": "há 586.920,617 horas", + "ur": "586,920.617 گھنٹے پہلے", + "id": "586.920,617 jam yang lalu", + "de": "vor 586.920,617 Stunden", + "ja": "586,920.617 時間前", + "pcm": "586,920.617 áwa wé dọ́n pas", + "mr": "५,८६,९२०.६१७ तासांपूर्वी", + "te": "5,86,920.617 గంటల క్రితం" + } +} diff --git a/test/js/node/test/fixtures/internal-modules/node_modules/internal/freelist.js b/test/js/node/test/fixtures/internal-modules/node_modules/internal/freelist.js new file mode 100644 index 0000000000..888cae37af --- /dev/null +++ b/test/js/node/test/fixtures/internal-modules/node_modules/internal/freelist.js @@ -0,0 +1 @@ +module.exports = 42; diff --git a/test/js/node/test/fixtures/keys/Makefile b/test/js/node/test/fixtures/keys/Makefile index 313183f6d6..3339f4b912 100644 --- a/test/js/node/test/fixtures/keys/Makefile +++ b/test/js/node/test/fixtures/keys/Makefile @@ -24,7 +24,10 @@ all: \ dh512.pem \ dh1024.pem \ dh2048.pem \ + dh3072.pem \ dherror.pem \ + dh_private.pem \ + dh_public.pem \ dsa_params.pem \ dsa_private.pem \ dsa_private_encrypted.pem \ @@ -594,9 +597,18 @@ dh1024.pem: dh2048.pem: openssl dhparam -out dh2048.pem 2048 +dh3072.pem: + openssl dhparam -out dh3072.pem 3072 + dherror.pem: dh1024.pem sed 's/^[^-].*/AAAAAAAAAA/g' dh1024.pem > dherror.pem +dh_private.pem: + openssl genpkey -algorithm dh -out dh_private.pem -pkeyopt dh_param:ffdhe2048 + +dh_public.pem: dh_private.pem + openssl pkey -in dh_private.pem -pubout -out dh_public.pem + dsa_params.pem: openssl dsaparam -out dsa_params.pem 2048 diff --git a/test/js/node/test/fixtures/keys/agent10-cert.pem b/test/js/node/test/fixtures/keys/agent10-cert.pem index ce0e515e82..59bb070575 100644 --- a/test/js/node/test/fixtures/keys/agent10-cert.pem +++ b/test/js/node/test/fixtures/keys/agent10-cert.pem @@ -1,41 +1,47 @@ -----BEGIN CERTIFICATE----- -MIIDjjCCAnagAwIBAgITMVaZ0eX5Kp8NI4vaKFVI592wTjANBgkqhkiG9w0BAQsF -ADCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjEfMB0G -A1UECgwWVGhlIE5vZGUuanMgRm91bmRhdGlvbjEQMA4GA1UECwwHTm9kZS5qczEM -MAoGA1UEAwwDY2E0MR4wHAYJKoZIhvcNAQkBFg9jYTRAZXhhbXBsZS5vcmcwIBcN -MjIwOTAzMjE0MDM3WhgPMjI5NjA2MTcyMTQwMzdaMHgxCzAJBgNVBAYTAlVTMQsw -CQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxHzAdBgNVBAoMFlRoZSBOb2RlLmpzIEZv -dW5kYXRpb24xEDAOBgNVBAsMB05vZGUuanMxHDAaBgNVBAMME2FnZW50MTAuZXhh -bXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDP49yjMES5 -1sfYG4ac06jR7DnSizMDgW+0V6CFPguv6p1D08aBA60mhY8+tjsbin3DYRiTB2HN -7C9svZ2cAffKK9W/40G6+jfJuB6I8g+LtdZ9hViw2RC0k4PFLzpG3VsJRpM4Wfos -/ubZqBuNGLN+K68sAFU0jbUra4dtJQXMi7SlFlJIUx2g10OF312uJcREfFVgNAw4 -EIZ2H7bmGtpE0p3UfBir4HTy5nz4ruYCbbzNWDuX7RIGZSXtqaQc7P9QPvuLzspl -feI8S2oRTLRIgDEatXJFlIWzGu1kF7XjftOrnFHwRWICK6joqSzdLhSS02qfqIRF -JFVZ8QNq11bhAgMBAAEwDQYJKoZIhvcNAQELBQADggEBACenzaglCUisBHiI7H/v -tOF/75jxDUO8FmV3mksh33EpTmzoBiQD1DiTFQu/EEJ/iAbdTRJ1PVnJsMTFH0Bm -7SmkYOCpETleXjU1MwHZIvh/gGa/CjLZhop26FkK2oqENl7iaM9vvqxxQ8H4Niit -ay3cn+aB9o8MjTH9Ki9iH0LS6bwtqqRimXXX0sx3HTUnFxD/7tzE7s6t7ayk+rIJ -6mBeQAw3UjNzjtLTvSxHoPFto7z5imF+6/v236UlOTdQpkbRS1KlxA8wm/NisWeq -TLjPh5BkZof+CwTUoAFK+WILsIHuvVY9SZBNcsQvsBao/whRR2Z8bU1HDAh8jHnk -4wo= +MIIDijCCAnICFAa1gku/rBMKem53dr6+kaDTIvSCMA0GCSqGSIb3DQEBCwUAMIGI +MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExCzAJBgNVBAcMAlNGMR8wHQYDVQQK +DBZUaGUgTm9kZS5qcyBGb3VuZGF0aW9uMRAwDgYDVQQLDAdOb2RlLmpzMQwwCgYD +VQQDDANjYTQxHjAcBgkqhkiG9w0BCQEWD2NhNEBleGFtcGxlLm9yZzAgFw0yNDA4 +MjcyMjU4NDRaGA8yMjk4MDYxMTIyNTg0NFoweDELMAkGA1UEBhMCVVMxCzAJBgNV +BAgMAkNBMQswCQYDVQQHDAJTRjEfMB0GA1UECgwWVGhlIE5vZGUuanMgRm91bmRh +dGlvbjEQMA4GA1UECwwHTm9kZS5qczEcMBoGA1UEAwwTYWdlbnQxMC5leGFtcGxl +LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM/j3KMwRLnWx9gb +hpzTqNHsOdKLMwOBb7RXoIU+C6/qnUPTxoEDrSaFjz62OxuKfcNhGJMHYc3sL2y9 +nZwB98or1b/jQbr6N8m4HojyD4u11n2FWLDZELSTg8UvOkbdWwlGkzhZ+iz+5tmo +G40Ys34rrywAVTSNtStrh20lBcyLtKUWUkhTHaDXQ4XfXa4lxER8VWA0DDgQhnYf +tuYa2kTSndR8GKvgdPLmfPiu5gJtvM1YO5ftEgZlJe2ppBzs/1A++4vOymV94jxL +ahFMtEiAMRq1ckWUhbMa7WQXteN+06ucUfBFYgIrqOipLN0uFJLTap+ohEUkVVnx +A2rXVuECAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAy0rm8E+PR+ZuaQsz8Q3s0Y7I +fNICuwEyByMcwiwCjvMM2FwNZbnmagmSQ2eo+jD0GMAcBLS61AWhC8tPqO6DfFOj +7L07NYJWTKQMqAsv3n6Nl0uXd8Aa4iGDhsMeTZXXk4E/GsZZ8T4pDmE8TtY6285Y +ONU7uKKFcnIfQwtcEUnpwqSAYmQxKa+rhQ974rW3hBCxvtrwNRXsMjCoPyfkIuOz +9P6ThZfMWlmuKg852Yi2VglaOrxakQInQGz4Q0JHyROd/e9m3J+t/QFR9VqtRnX8 +UEOlxD8iazk//VFd7WrO2jzqjXFIzBNrdvmsNsP+8uIjrGJtHdKeHL7v5V687A== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIDFzCCAoCgAwIBAgIJAJHwBmNgafKfMA0GCSqGSIb3DQEBCwUAMHoxCzAJBgNV -BAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxDzANBgNVBAoMBkpveWVu -dDEQMA4GA1UECwwHTm9kZS5qczEMMAoGA1UEAwwDY2EyMSAwHgYJKoZIhvcNAQkB -FhFyeUB0aW55Y2xvdWRzLm9yZzAgFw0yMjA5MDMxNDQ2NTFaGA8yMjk2MDYxNzE0 -NDY1MVowgYgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0Yx -HzAdBgNVBAoMFlRoZSBOb2RlLmpzIEZvdW5kYXRpb24xEDAOBgNVBAsMB05vZGUu -anMxDDAKBgNVBAMMA2NhNDEeMBwGCSqGSIb3DQEJARYPY2E0QGV4YW1wbGUub3Jn -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0HnUahyfA25t8kaziu0i -vVMkTWntm0pJ8oemeO7yCGaY4QHEwN+QUzrzO7y7ngl2Dt76eEvj0mrgaW8Ao7Ns -ePfp3663g8RrBsb4cR1da2Tc8kpXCqgwbcTlm8HI/7OAdHGA2YDLNv7iyVk9meHM -gYfO9dVgrZ7RxfnGwNMJdNjYJrd02xeU6euoKl9j/ZWCG5xHAM2xAXOKHGm8toIm -+Ss6iZXY8kypy7Fjwyv7jMT8V+pzIWu24xd3Y3s07r59nkFmQ29nHMTaLP7Tf3TY -MBI5mp8fet732aBoywpQ/w05LR9gdM1jpUvIlmhj4qGskv17AMEmRecwic3opq/b -yQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GBADsFOR+N -Bcm2FyHOutoFpQn70qAFg0xlO3NTH87uubbs6rf3LDrsskhjskfs6wpUk56IJOoU -H7+F7aDDtSrnxzxxC5eZeGyaN05T5N01OdK3xvqUnr7mg/Ce0jnxrZhxHI8SHOqs -Kwrg4fRasUHGhH286Y13xOj2pLSrVoSbkXsA +MIIEaDCCA1CgAwIBAgIUDxaIwCfB2vttbQL/LlnVg4mwMUAwDQYJKoZIhvcNAQEL +BQAwejELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjEPMA0G +A1UECgwGSm95ZW50MRAwDgYDVQQLDAdOb2RlLmpzMQwwCgYDVQQDDANjYTIxIDAe +BgkqhkiG9w0BCQEWEXJ5QHRpbnljbG91ZHMub3JnMCAXDTI0MDgyNzIyNTg0NFoY +DzIyOTgwNjExMjI1ODQ0WjCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQsw +CQYDVQQHDAJTRjEfMB0GA1UECgwWVGhlIE5vZGUuanMgRm91bmRhdGlvbjEQMA4G +A1UECwwHTm9kZS5qczEMMAoGA1UEAwwDY2E0MR4wHAYJKoZIhvcNAQkBFg9jYTRA +ZXhhbXBsZS5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDQedRq +HJ8Dbm3yRrOK7SK9UyRNae2bSknyh6Z47vIIZpjhAcTA35BTOvM7vLueCXYO3vp4 +S+PSauBpbwCjs2x49+nfrreDxGsGxvhxHV1rZNzySlcKqDBtxOWbwcj/s4B0cYDZ +gMs2/uLJWT2Z4cyBh8711WCtntHF+cbA0wl02Ngmt3TbF5Tp66gqX2P9lYIbnEcA +zbEBc4ocaby2gib5KzqJldjyTKnLsWPDK/uMxPxX6nMha7bjF3djezTuvn2eQWZD +b2ccxNos/tN/dNgwEjmanx963vfZoGjLClD/DTktH2B0zWOlS8iWaGPioayS/XsA +wSZF5zCJzeimr9vJAgMBAAGjgdQwgdEwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQU +Tc8o3KouldTCYNQHvW09ZBv9sW0wgaEGA1UdIwSBmTCBlqF+pHwwejELMAkGA1UE +BhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjEPMA0GA1UECgwGSm95ZW50 +MRAwDgYDVQQLDAdOb2RlLmpzMQwwCgYDVQQDDANjYTIxIDAeBgkqhkiG9w0BCQEW +EXJ5QHRpbnljbG91ZHMub3JnghRsoeMhBMOB34RpWIz6SD/UwaqquzANBgkqhkiG +9w0BAQsFAAOCAQEAKtd7q+5123jVDzpydg4o3FO84u/1gzlkQ9gAc0q48/ePD/0g +GTeTLz3fODq84l0Nx0g2XbcnrnH/07dzykZokAI6TFhv9qioeMmZa5UhwLSFynXJ +tqP26jA2/dpofGrVV2up/dJ9nw/jmvsRTigvIjkPyofFyxyssNmUIOXgEB6szthQ +mg0VKqgcF3yPDFiSMNh7YnxKd6Rsw1uujtRR+dbkLJs3m0sk+MNra7+LIfqVU5Iv +UyieguUmYYtW9rWTjxVCEl84teryIFJK81GlX/wiq1Nx3DZj+DCSwJMdl5DDzvH8 +EnE1L+MapqCnP0eAmNdWwF5SVxfKUwtt6uPpYw== -----END CERTIFICATE----- diff --git a/test/js/node/test/fixtures/keys/agent10.pfx b/test/js/node/test/fixtures/keys/agent10.pfx index f1df772cbb..fc6a9a20b1 100644 Binary files a/test/js/node/test/fixtures/keys/agent10.pfx and b/test/js/node/test/fixtures/keys/agent10.pfx differ diff --git a/test/js/node/test/fixtures/keys/agent3-cert.pem b/test/js/node/test/fixtures/keys/agent3-cert.pem index 9a2b16b19f..e24a34c1bf 100644 --- a/test/js/node/test/fixtures/keys/agent3-cert.pem +++ b/test/js/node/test/fixtures/keys/agent3-cert.pem @@ -1,18 +1,21 @@ -----BEGIN CERTIFICATE----- -MIIC9DCCAl0CCQCR8AZjYGnyoDANBgkqhkiG9w0BAQsFADB6MQswCQYDVQQGEwJV -UzELMAkGA1UECAwCQ0ExCzAJBgNVBAcMAlNGMQ8wDQYDVQQKDAZKb3llbnQxEDAO -BgNVBAsMB05vZGUuanMxDDAKBgNVBAMMA2NhMjEgMB4GCSqGSIb3DQEJARYRcnlA -dGlueWNsb3Vkcy5vcmcwIBcNMjIwOTAzMTQ0NjUxWhgPMjI5NjA2MTcxNDQ2NTFa -MH0xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxDzANBgNV -BAoMBkpveWVudDEQMA4GA1UECwwHTm9kZS5qczEPMA0GA1UEAwwGYWdlbnQzMSAw -HgYJKoZIhvcNAQkBFhFyeUB0aW55Y2xvdWRzLm9yZzCCASIwDQYJKoZIhvcNAQEB -BQADggEPADCCAQoCggEBAMwdFX1RDh/WG1MyegBg2PqcmMSd3wKmO6QxSYpEdv2o -rhBJ8opfsdvMDvk66UfqBgMIryJhHWf1iznmAC2aT4hDYyKuqFuN7EDzHOWH7ta5 -E5+OXR/UvgYvsq5ptNKAUUbZ3MoOnQluEbNnJS0wqKSQWu1apnih8fUiqrTQjI/d -lnnN9A1aQwD2JMPy/GYD6bjx3psFcBjrPiSm/WuZxpcFg/r9cNW3mylEMMw2TUe2 -Wwaz92GfX6AbF/ENAS9DZSwz7UzVwaHzwv69TXTlskdvAvGA4j6FCvpbuTFNc03Y -YGUfnhO7WpiaS9lppj7UMAUOI0KLAIoYZYOCYarZeN0CAwEAATANBgkqhkiG9w0B -AQsFAAOBgQC3K2rmDobXHmAvKjQOndWY6xPUmmSzLPWr+WtFormgLG5UOiKAYa7K -ErG6aklZw2ZnYRSebotC+eVh1ZSuOdpFnLw36dt6XGe+ulp3jgc9nggTZGagCFB1 -yhgZ4y+7zx4u1t2oVqCbYn6mtw+AuwoszkdzHQqZIA42USnxUCLJPQ== +MIIDgDCCAmgCFHtnB1Iw05rTKjL+Xc+x+pXi6jGdMA0GCSqGSIb3DQEBCwUAMHox +CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxDzANBgNVBAoM +BkpveWVudDEQMA4GA1UECwwHTm9kZS5qczEMMAoGA1UEAwwDY2EyMSAwHgYJKoZI +hvcNAQkBFhFyeUB0aW55Y2xvdWRzLm9yZzAgFw0yNDA4MjcyMjU4NDRaGA8yMjk4 +MDYxMTIyNTg0NFowfTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQH +DAJTRjEPMA0GA1UECgwGSm95ZW50MRAwDgYDVQQLDAdOb2RlLmpzMQ8wDQYDVQQD +DAZhZ2VudDMxIDAeBgkqhkiG9w0BCQEWEXJ5QHRpbnljbG91ZHMub3JnMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzB0VfVEOH9YbUzJ6AGDY+pyYxJ3f +AqY7pDFJikR2/aiuEEnyil+x28wO+TrpR+oGAwivImEdZ/WLOeYALZpPiENjIq6o +W43sQPMc5Yfu1rkTn45dH9S+Bi+yrmm00oBRRtncyg6dCW4Rs2clLTCopJBa7Vqm +eKHx9SKqtNCMj92Wec30DVpDAPYkw/L8ZgPpuPHemwVwGOs+JKb9a5nGlwWD+v1w +1bebKUQwzDZNR7ZbBrP3YZ9foBsX8Q0BL0NlLDPtTNXBofPC/r1NdOWyR28C8YDi +PoUK+lu5MU1zTdhgZR+eE7tamJpL2WmmPtQwBQ4jQosAihhlg4Jhqtl43QIDAQAB +MA0GCSqGSIb3DQEBCwUAA4IBAQAfxPLKKEifOSGFXXFEa1Z2DXTxOc9YeY3dTVYa +py/ATdwnKhGDHknYmnHSUBzgvqRZqoZrG04S1HuatAdCifNx+ts2qrx3AmOdYrMH +A6PYQIY8RVNKgEoel776FjCJta2ta2KNOkyrVwEhY7jgIgHcYIGwAgM0Gcq8j63R +IomOu0+FE9M6a+oU9Z0EZ646LU0GgMEz8cegxKwRoA+KKEQzmdwnblzWXqNWf+VC +nljA0ReLl484iBt1eMZQ9tGMvu2QW8v7k1nnyuRF6Zmfe+ELgAk3rHWGCcFqB5ri +tEjlIc055+AmBlbf6Ba5oVawjrowvd+3BtlM0cx60DmC425T -----END CERTIFICATE----- diff --git a/test/js/node/test/fixtures/keys/agent4-cert.pem b/test/js/node/test/fixtures/keys/agent4-cert.pem index 81989bf2ee..5792845c74 100644 --- a/test/js/node/test/fixtures/keys/agent4-cert.pem +++ b/test/js/node/test/fixtures/keys/agent4-cert.pem @@ -1,19 +1,26 @@ -----BEGIN CERTIFICATE----- -MIIDEjCCAnugAwIBAgIJAJHwBmNgafKeMA0GCSqGSIb3DQEBCwUAMHoxCzAJBgNV -BAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxDzANBgNVBAoMBkpveWVu -dDEQMA4GA1UECwwHTm9kZS5qczEMMAoGA1UEAwwDY2EyMSAwHgYJKoZIhvcNAQkB -FhFyeUB0aW55Y2xvdWRzLm9yZzAgFw0yMjA5MDMxNDQ2NTFaGA8yMjk2MDYxNzE0 -NDY1MVowfTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjEP -MA0GA1UECgwGSm95ZW50MRAwDgYDVQQLDAdOb2RlLmpzMQ8wDQYDVQQDDAZhZ2Vu -dDQxIDAeBgkqhkiG9w0BCQEWEXJ5QHRpbnljbG91ZHMub3JnMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9loX+bQq2o1Sh+p2vfnNvDs/lvCexuKKWCst -/LZZyPhd6ywuUos0lxs0AN7B4cY54Aq0OUEfoX7oPBxS3rIuTdUwWcswz9Jg2PnU -EAvekJtFS78v77ORAqnegEyeQzpJ1i+MYZ/Ebnrp6m2Pt11UrvQpkSVofzerrZbx -SBBIRm2pianctaPuonL3tyV11kZb3i5YD9s0J+g3A51PfUCOB2umPnzDgeAAl97F -w/E+0bQu0C57Ej86AxEfSEnbj9l+ZKkDMuXQTZKVloY+Ec/6wj2m0/ABEsWN9h6q -Q0pb4oB15zFBpgCeRzWuRfL2tr96nGwYjQiM3dAzEkvSmDF3TwIDAQABoxcwFTAT -BgNVHSUEDDAKBggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOBgQB9szRHxchcB2qQ -+92InxIollN27xqUklcdNhlSqmH6MD1VOj2M3xwmRGzIroIx9da+A51k7h/QPsc9 -xMHrIRlRxb+/rJ2K6ayvwI2EPgduSjMfaor72CNRJ+/lsiRffo6weoBju1szAFgI -cSeYOOo8obGa7if3LvdzolXPue3dkg== +MIIEYzCCA0ugAwIBAgIUeDAG+o11vU6VBF7j7ALuBgnQQsIwDQYJKoZIhvcNAQEL +BQAwejELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjEPMA0G +A1UECgwGSm95ZW50MRAwDgYDVQQLDAdOb2RlLmpzMQwwCgYDVQQDDANjYTIxIDAe +BgkqhkiG9w0BCQEWEXJ5QHRpbnljbG91ZHMub3JnMCAXDTI0MDgyNzIyNTg0NFoY +DzIyOTgwNjExMjI1ODQ0WjB9MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExCzAJ +BgNVBAcMAlNGMQ8wDQYDVQQKDAZKb3llbnQxEDAOBgNVBAsMB05vZGUuanMxDzAN +BgNVBAMMBmFnZW50NDEgMB4GCSqGSIb3DQEJARYRcnlAdGlueWNsb3Vkcy5vcmcw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD2Whf5tCrajVKH6na9+c28 +Oz+W8J7G4opYKy38tlnI+F3rLC5SizSXGzQA3sHhxjngCrQ5QR+hfug8HFLesi5N +1TBZyzDP0mDY+dQQC96Qm0VLvy/vs5ECqd6ATJ5DOknWL4xhn8RueunqbY+3XVSu +9CmRJWh/N6utlvFIEEhGbamJqdy1o+6icve3JXXWRlveLlgP2zQn6DcDnU99QI4H +a6Y+fMOB4ACX3sXD8T7RtC7QLnsSPzoDER9ISduP2X5kqQMy5dBNkpWWhj4Rz/rC +PabT8AESxY32HqpDSlvigHXnMUGmAJ5HNa5F8va2v3qcbBiNCIzd0DMSS9KYMXdP +AgMBAAGjgdswgdgwEwYDVR0lBAwwCgYIKwYBBQUHAwIwHQYDVR0OBBYEFF1UHW4p +D6zk376eyKXCjPGn7HWKMIGhBgNVHSMEgZkwgZahfqR8MHoxCzAJBgNVBAYTAlVT +MQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxDzANBgNVBAoMBkpveWVudDEQMA4G +A1UECwwHTm9kZS5qczEMMAoGA1UEAwwDY2EyMSAwHgYJKoZIhvcNAQkBFhFyeUB0 +aW55Y2xvdWRzLm9yZ4IUbKHjIQTDgd+EaViM+kg/1MGqqrswDQYJKoZIhvcNAQEL +BQADggEBABgvOfGvXKVWIiPxTiQXcS76gwrxb7GdoW1WNrM/nqjqEl19gw/EopZi +RkRXyXE2NXHIrlr+b+QAIcIPNYhwWzMPzMIgwddlKjWVqZB+YOk8lbGJeCEBXQN2 +n6m2H4ILw83jg7XMeLr9hCRsn9ooC1EBzwN4N729lVya7V0zoFryBM/yYB5sTx/u +4xUBKC7XFZXTtDE2KuBq9b0PTV3jSNfhHfHLEOCp55i/H9MFz8cbk3kd+6aKYwDC +Lt09Y55fd3Bo1eTENNZ5FOgzFj2P50orIvSHHqIiYESegE3E7mzM08E4ek1ID5ub +SQU4LdYnC+Mo3MPoWJfQgiPLtxC3EyI= -----END CERTIFICATE----- diff --git a/test/js/node/test/fixtures/keys/agent5-cert.pem b/test/js/node/test/fixtures/keys/agent5-cert.pem index a1edef0739..b543340574 100644 --- a/test/js/node/test/fixtures/keys/agent5-cert.pem +++ b/test/js/node/test/fixtures/keys/agent5-cert.pem @@ -1,19 +1,26 @@ -----BEGIN CERTIFICATE----- -MIIDCTCCAnKgAwIBAgIJAJHwBmNgafKhMA0GCSqGSIb3DQEBCwUAMHoxCzAJBgNV -BAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxDzANBgNVBAoMBkpveWVu -dDEQMA4GA1UECwwHTm9kZS5qczEMMAoGA1UEAwwDY2EyMSAwHgYJKoZIhvcNAQkB -FhFyeUB0aW55Y2xvdWRzLm9yZzAgFw0yMjA5MDMxNDQ2NTJaGA8yMjk2MDYxNzE0 -NDY1MlowdDELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MREwDwYDVQQK -DAhUcmVzb3JpdDEWMBQGA1UEAwwNw4Fkw6FtIExpcHBhaTEnMCUGCSqGSIb3DQEJ -ARYYYWRhbS5saXBwYWlAdHJlc29yaXQuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEA0oKK05Cl/JmoVBAMR/bbJ4EPYGdh3GCrppPKNcgqGtvnmmJ7 -CMKWLzb4FA4O43SD/P0u9jJZdkOTfpzNMk9wjrQvBeXxCiSVS0fjDb+9YDolIfjq -hs/9arPa2FKQJcWX/2/TgBndEw1NOvumwrktxlgRK8IxxF4/28ub5Y4Kqo3DFks/ -uicH+IInjkujLV9hu3XfPTme6mr/NmKPa6DV3fm2rib7hby5Kk7WFfsYTiMGxl6S -WhHuoyeqK4sFycL3ly8letX8D/Kfz27dx2zBOIbXADbK0afJCtLDOYIFBEhZAYhi -+NWBRlP9NQrd1vT1zS2/eBlvB6QqCTgoX6uXEQIDAQABoxcwFTATBgNVHSUEDDAK -BggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOBgQAQtX59XTk/vLNN/nqSECzhelMV -WBOvtjGnA4WK/jtFpOLwFPwSp/FOpGT1Gbi38NseEAhEKjy6J266F/ncMS+UJetu -zDn27MRwGEUx0ZZR4Z2g8bf10XAZSUmS7SpzSCovsCeQ9g6oH3PIMvzRCeSUwzfD -c6KyjtZ++jH3gz6FlA== +MIIEWjCCA0KgAwIBAgIUBy64GxzmlZKybD2k6yMMkhjvFoQwDQYJKoZIhvcNAQEL +BQAwejELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjEPMA0G +A1UECgwGSm95ZW50MRAwDgYDVQQLDAdOb2RlLmpzMQwwCgYDVQQDDANjYTIxIDAe +BgkqhkiG9w0BCQEWEXJ5QHRpbnljbG91ZHMub3JnMCAXDTI0MDgyNzIyNTg0NFoY +DzIyOTgwNjExMjI1ODQ0WjB0MQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBl +c3QxETAPBgNVBAoMCFRyZXNvcml0MRYwFAYDVQQDDA3DgWTDoW0gTGlwcGFpMScw +JQYJKoZIhvcNAQkBFhhhZGFtLmxpcHBhaUB0cmVzb3JpdC5jb20wggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDSgorTkKX8mahUEAxH9tsngQ9gZ2HcYKum +k8o1yCoa2+eaYnsIwpYvNvgUDg7jdIP8/S72Mll2Q5N+nM0yT3COtC8F5fEKJJVL +R+MNv71gOiUh+OqGz/1qs9rYUpAlxZf/b9OAGd0TDU06+6bCuS3GWBErwjHEXj/b +y5vljgqqjcMWSz+6Jwf4gieOS6MtX2G7dd89OZ7qav82Yo9roNXd+bauJvuFvLkq +TtYV+xhOIwbGXpJaEe6jJ6oriwXJwveXLyV61fwP8p/Pbt3HbME4htcANsrRp8kK +0sM5ggUESFkBiGL41YFGU/01Ct3W9PXNLb94GW8HpCoJOChfq5cRAgMBAAGjgdsw +gdgwEwYDVR0lBAwwCgYIKwYBBQUHAwIwHQYDVR0OBBYEFI+g7kSaOiOaBhz+q3+3 +tpXdG2HtMIGhBgNVHSMEgZkwgZahfqR8MHoxCzAJBgNVBAYTAlVTMQswCQYDVQQI +DAJDQTELMAkGA1UEBwwCU0YxDzANBgNVBAoMBkpveWVudDEQMA4GA1UECwwHTm9k +ZS5qczEMMAoGA1UEAwwDY2EyMSAwHgYJKoZIhvcNAQkBFhFyeUB0aW55Y2xvdWRz +Lm9yZ4IUbKHjIQTDgd+EaViM+kg/1MGqqrswDQYJKoZIhvcNAQELBQADggEBAJmA +5ciG5btN3EgH7P5fcWS6SteEKAaSVlTSwsmEg+rKtCeUsVQZ0syMlVMfSwZQfWrq +dBsV1wFw61eX77HnvdoE0B5/Wj6DkjffOm3C7yzmxLo/507jN3mPzop3AMxdl9xC +sE3qEf1pNFJKyRBrc4UoD/lp0gfW4Zv6fbkZgttmynGWbyGtLyS76d/b6Wst7eRo +qkZODIi0wmJ9F8n+xWeJqRRruoqCGy3fr/NL1uCjrzXcRHOuKT8iCE0DnA9WaEs+ +hu5BxA4fZJZGYQTZREEALLUEOlpPFATt/Rel+OwNDCvYXfKaHfGLCmBxxKojzCcm +mhIiKquTKehJufrq/bY= -----END CERTIFICATE----- diff --git a/test/js/node/test/fixtures/keys/ca2-cert.pem b/test/js/node/test/fixtures/keys/ca2-cert.pem index 0c72d6c647..7ff23789d6 100644 --- a/test/js/node/test/fixtures/keys/ca2-cert.pem +++ b/test/js/node/test/fixtures/keys/ca2-cert.pem @@ -1,16 +1,21 @@ -----BEGIN CERTIFICATE----- -MIICbTCCAdYCCQDRrfgRk8tC1zANBgkqhkiG9w0BAQsFADB6MQswCQYDVQQGEwJV -UzELMAkGA1UECAwCQ0ExCzAJBgNVBAcMAlNGMQ8wDQYDVQQKDAZKb3llbnQxEDAO -BgNVBAsMB05vZGUuanMxDDAKBgNVBAMMA2NhMjEgMB4GCSqGSIb3DQEJARYRcnlA -dGlueWNsb3Vkcy5vcmcwIBcNMTgxMTE2MTg0MjIwWhgPMjI5MjA4MzAxODQyMjBa -MHoxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxDzANBgNV -BAoMBkpveWVudDEQMA4GA1UECwwHTm9kZS5qczEMMAoGA1UEAwwDY2EyMSAwHgYJ -KoZIhvcNAQkBFhFyeUB0aW55Y2xvdWRzLm9yZzCBnzANBgkqhkiG9w0BAQEFAAOB -jQAwgYkCgYEAv61gNiLff+zxCdAwdzlVoucGu5L+LFFN9TXzcT3ZD8U1H6CiLp3Q -02IlbK1JRHwpJBXgYOFvMWd9LD6JiJgJsp61kpZShl2qZSUIfhzeExWH7kkuPHWC -IEkiP/aDp5wuqbFBkNUJu8opYr0E6/t9sIzl4IK7WNDXWgQvv8cqin8CAwEAATAN -BgkqhkiG9w0BAQsFAAOBgQB80WTJ9neA5yVaDVV+hZtOasLiZlUT8m49ImQMnInA -jdoAkxgySNOJP8IrsilleAGeHF+JPy042z8NZ5C+xL9REaB1/OaQ7+nwHP0O0f+l -kXHgZATQ3YVf6db5euK3R1mdO1Vv++R4Nu4NYBu0cmfMpdl/uKdYpXMjPVn21iB7 -5w== +MIIDfTCCAmUCFGyh4yEEw4HfhGlYjPpIP9TBqqq7MA0GCSqGSIb3DQEBCwUAMHox +CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxDzANBgNVBAoM +BkpveWVudDEQMA4GA1UECwwHTm9kZS5qczEMMAoGA1UEAwwDY2EyMSAwHgYJKoZI +hvcNAQkBFhFyeUB0aW55Y2xvdWRzLm9yZzAgFw0yNDA4MjcyMjU4NDRaGA8yMjk4 +MDYxMTIyNTg0NFowejELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQH +DAJTRjEPMA0GA1UECgwGSm95ZW50MRAwDgYDVQQLDAdOb2RlLmpzMQwwCgYDVQQD +DANjYTIxIDAeBgkqhkiG9w0BCQEWEXJ5QHRpbnljbG91ZHMub3JnMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoq6k9bq0BgvZDesrfPPzYyA2PbxTA3hI +ziKAmglvuF1lbHVdG/7jOZV7JQpdViCRpcoO6uz1BmGnvd3UDS6Q/y/mkjE96E/y +O3h8gcn+CBzniKIYhB9QtrrVHDy5e/tOJGhGifLtver3iLf5kgiJPy4cGAD663oT +Vlzvo4U6E2j3vJw4l18pi9gpL7shU8QJka0/0F8BbhoaQK1ZqvD4p9bOMRDztfhZ +Gb5qJ+664bx80dck9a5UoLCid8tQIlOCnr9IrAwTPNpnk/xCC7nsbE0+CkMsI3+U +g+3gO0zApWy6DzSawYh6VVijFe6Q0N12duspxdpgt7Kk+8ejrAAOjwIDAQABMA0G +CSqGSIb3DQEBCwUAA4IBAQCSsx31ivZnnpAJqsF8yncin8kAvgy8YG1itguKO9sG +KQ5AIWpSRjhZjJ0JRMj2hxhoob2vZ68QbP8iEufByBJ7G1CkyHvBODaMSdydXWga +wBSKFpsiPt+Gj6rzb5yn0MuH577tWzVLi4C1KW8sFx9rtjDUHTqwf3i7/iuTA5Yo +yruWRmIXqFoIs3lnKC1f8CYmcZMT2hox8imQI8hIMjalB30WGrDudoqd67rDGWn7 +IKC12pRdgaADILx0vhdniieUwTq85r/6BaKFCJsZIaRd3aAoo3bl4qBA5Bt0uoCB +x6pEPQeypvU8qBmKKD+XQdY0Pf9Vh9Wq6g/iiw79IsY0 -----END CERTIFICATE----- diff --git a/test/js/node/test/fixtures/keys/ca2-crl.pem b/test/js/node/test/fixtures/keys/ca2-crl.pem index a07929b83d..a5a9f5fb6f 100644 --- a/test/js/node/test/fixtures/keys/ca2-crl.pem +++ b/test/js/node/test/fixtures/keys/ca2-crl.pem @@ -1,10 +1,14 @@ -----BEGIN X509 CRL----- -MIIBezCB5TANBgkqhkiG9w0BAQ0FADB6MQswCQYDVQQGEwJVUzELMAkGA1UECAwC -Q0ExCzAJBgNVBAcMAlNGMQ8wDQYDVQQKDAZKb3llbnQxEDAOBgNVBAsMB05vZGUu -anMxDDAKBgNVBAMMA2NhMjEgMB4GCSqGSIb3DQEJARYRcnlAdGlueWNsb3Vkcy5v -cmcXDTIyMDkwMzE0NDY1MVoYDzIwNTAwMTE4MTQ0NjUxWjA4MBoCCQCR8AZjYGny -mhcNMTgxMTE2MTg0MjIwWjAaAgkAkfAGY2Bp8p4XDTIyMDkwMzE0NDY1MVowDQYJ -KoZIhvcNAQENBQADgYEAl59y/rB5YcIT5ySOwTfAzDFX3fZq1YPF8KF7Afqzx/x6 -b+1w511+tkixm0evIHtxlOrlFrAFBSFGMlrfKnmg5EopJ2w5yOR53ZqUwtNryZMC -WJTEN+DeXU8WdY+iEXXCmpGZhvheRwKyCcY5xHxvwbnb3UdF+IaqA0aIN1Sa3Oc= +MIICJDCCAQwwDQYJKoZIhvcNAQENBQAwejELMAkGA1UEBhMCVVMxCzAJBgNVBAgM +AkNBMQswCQYDVQQHDAJTRjEPMA0GA1UECgwGSm95ZW50MRAwDgYDVQQLDAdOb2Rl +LmpzMQwwCgYDVQQDDANjYTIxIDAeBgkqhkiG9w0BCQEWEXJ5QHRpbnljbG91ZHMu +b3JnFw0yNDA4MjcyMjU4NDRaGA8yMDUyMDExMjIyNTg0NFowXzAaAgkAkfAGY2Bp +8poXDTE4MTExNjE4NDIyMFowGgIJAJHwBmNgafKeFw0yMjA5MDMxNDQ2NTFaMCUC +FHgwBvqNdb1OlQRe4+wC7gYJ0ELCFw0yNDA4MjcyMjU4NDRaMA0GCSqGSIb3DQEB +DQUAA4IBAQCbkvSL9eK6ejgu9I8h7idZ6kgmIT0NdURz0UqAptlHAWgCb5Qr9mnm +2WJCh7J8ohYRb1x16iB0mhJbkc/A/n81oNNIrvCPOsuZqM75mIwFS+jqzJ0FgaiW +qCcXWZxmx+4e3jqtwOc+sCZN5E1thqvVkJEuWNdOOj4gsW3wWL/MDTu2G/MCbnQY +MV5Nq27ipebpdPRpxzpYpt9j44C+L1GmsiU0mxqFx3VH9WeeAreA1NQSIBXWGLPg +Xmgf3s6B0t2he4IuSQvU+R2gAPugaHYOVuV0qMdhPE9QC0BTi8g4EwpEoZIJ+Oqw +zCTkq36a+NiDV2p1HIT4STHfe616o5DD -----END X509 CRL----- diff --git a/test/js/node/test/fixtures/keys/ca2-database.txt b/test/js/node/test/fixtures/keys/ca2-database.txt index bd86685210..3efd0b7af5 100644 --- a/test/js/node/test/fixtures/keys/ca2-database.txt +++ b/test/js/node/test/fixtures/keys/ca2-database.txt @@ -1,2 +1,3 @@ R 22920830184220Z 181116184220Z 91F006636069F29A unknown /C=US/ST=CA/L=SF/O=Joyent/OU=Node.js/CN=agent4/emailAddress=ry@tinyclouds.org R 22960617144651Z 220903144651Z 91F006636069F29E unknown /C=US/ST=CA/L=SF/O=Joyent/OU=Node.js/CN=agent4/emailAddress=ry@tinyclouds.org +R 22980611225844Z 240827225844Z 783006FA8D75BD4E95045EE3EC02EE0609D042C2 unknown /C=US/ST=CA/L=SF/O=Joyent/OU=Node.js/CN=agent4/emailAddress=ry@tinyclouds.org diff --git a/test/js/node/test/fixtures/keys/ca2-database.txt.old b/test/js/node/test/fixtures/keys/ca2-database.txt.old index 3981127cab..bd86685210 100644 --- a/test/js/node/test/fixtures/keys/ca2-database.txt.old +++ b/test/js/node/test/fixtures/keys/ca2-database.txt.old @@ -1 +1,2 @@ R 22920830184220Z 181116184220Z 91F006636069F29A unknown /C=US/ST=CA/L=SF/O=Joyent/OU=Node.js/CN=agent4/emailAddress=ry@tinyclouds.org +R 22960617144651Z 220903144651Z 91F006636069F29E unknown /C=US/ST=CA/L=SF/O=Joyent/OU=Node.js/CN=agent4/emailAddress=ry@tinyclouds.org diff --git a/test/js/node/test/fixtures/keys/ca2-key.pem b/test/js/node/test/fixtures/keys/ca2-key.pem index 2efd44d78c..e2aea23f18 100644 --- a/test/js/node/test/fixtures/keys/ca2-key.pem +++ b/test/js/node/test/fixtures/keys/ca2-key.pem @@ -1,18 +1,30 @@ -----BEGIN ENCRYPTED PRIVATE KEY----- -MIIC1DBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQI0/0Q5tLDQW0CAggA -MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECHCRfosVTaMUBIICgHq2VKpOxq8W -+KZ7bVFuWx/gJvE1FAJokIZogK52LH3oEk9kMlEujwYAMovEew4lPMgAnyQh5Mbx -BXIm8Arww9hUZlRPuHmeQQuikbz/Sy5LVFbrzRsM0xGZxeWkpq3iKj3Z4W1OneRd -HAtBADAlID1a4r5f/BxiuNBGn5X54x66qbC94mJ2b02zHJJaRVd6OQM5iZURlcbi -N1E/LtQ3/I9qWqGYfiVCZf39ItxbrBkIEk65BbCackpDpVxzOfEbvC8RdBZcHxZm -8g4XZ6p1rCmzLi22l7usgEhd4QSMQyT9JTnMfM1QFzaqAVTqWr4ZFP108a2vH574 -T/HFKBkI+DEUsKQTLmYqZ05mg0wx80KGP/+1jOB1yx0tGnxCihGJVhqqGoFqgBSm -aqC5arQIZSUt2eN4OamakgU4iLzrKFb6bWGwTNUoHZNh4TsYz4CvFkPcM5tOyX+l -RoUyPAyfu348Z2IKBzUwYUfXJ5WFW2xq+RiOmlt4zF1Lym+aktEP6REQZYTGZZZx -l1YsvIUDd0pj5AJ3/PSTZN+VzkKz5lJdKEDEqpoOkEZnE/FL5VJHnRLOANyNf1zl -qZFgLGRZgZQwGkwj2hAF3auRJWJyvjuQW57v86F3U6XKKKejgBVb2ohMk7U6WW8B -wPtYyEa2zW1hSCLWhMEaek5Y2/2NX/dPryHNZ5XJ1UD0SGrPumN4lbErKDWGmAoK -jH6bpX/xVdmur2BwgGdqt6S1BW9B2F+cXz46UNiFKPYL49iBe13xM5EFKk9N9DL3 -HWPWrExlmi+p4PASL6cR5t9sDw8wUYp5cyC/M1RHDJPvjgBX987F17fI6GkNNToE -ZIbM6M/EuKg= +MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQITamLkHox9jMCAggA +MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECIoxHzl7vHD+BIIEyEs0UE67+Yq5 +jEEvXy5nsAUOlJROurdaK5TCfR/PFiPmotRbS6dUdQrNRT2qicKjudYmVHlss5z7 +yCd9Q2WSpOClTDeuJ6uyGPkvRnWQOFKhzeAQ4I/pDdddQCw61MmZHC5BKVc9a/3J +AHJkQlXLXEb3O/Pc32YdUmFDpYB0VZMhWJdYripODX669miPu46W9E9Fz+9DaVkg +j+F+2jwkww310frsxMUhMAI/DFYQ+LemAwWpUxv7MCVGKpMV0QU0iUeSfhIvOcaC +zQy8tG5ftUtOLGgf53Ol8YFuTMwFx0+w6NxGtB7mskk9bNVitI7w1yWTS3SvCz6g +vyhRu9D4w4VRQEpvz0quooqlJFN9lpNBkNY1hDk0PymQ3mXQLQMXITlTwUb5tHHM +nJtOad1ztJLQBG7+28J1YVnm/e45hz8GgbaACBUZVIwW0z71AMsmo8JUXBncI874 +3xppj2CGCxrKAtz5ZDCotWk7FucdgAhHNsF/a6bIiOXULnMLFRQ0afYrZW4iEady +W5lXBpZvQzrsWZiq7X3EWjhlnfPl1sLo+Rc9OGFE6znMyR5xqgjJhcIP4tM6FOO5 +ko1MFCaA0qBpH66TredvooQL7cYSbhStCICc5XJpJw1beqIj5/No2NfI/viv0yIq +O9ebIzZ2muKuP21a72K0xjrquoO6JmFs6Fu4uytEDtAyQduBJ+xBma5KTDa9YjjG +bd5nGuEGpwQRnUPPoHDkZSqQ8IiBS5Pam2KIW5xReK3afUID8Dr01J/blk22lc+l +/fP2zSfVeJzxK0XscfZWlUu8d0LnRoOwUjpGhOLrQEXKMjxfGNzbuOXSJLsTAHu/ +nc2ozCmAMjjRb74E8GoNv8Sbo4L3/elT4IpKcWlhOb+mlJEz5oj6Z4qycAcfxwZz +m4BRhOTskJXBTwCAlOmTiz9IwzjEVeJ7nN6ayTFCMYHJlpmoEH7vOP0ovYL9TRKm +vWH5kzLCatQ7EBKMbaG/isCFw85ylmqbYth9wEBDq+vN9T+rNSM16uiTJXo8+Vo0 +hNPEfnqkdpCdTA0RgTpQHkjBx43ySzEtteEfNQyKLpHdHb12O8A3PdlL+u+0nq+l +Gx7LmwB2NJVmkRSac4Od1zt1EWMdRHik/VHaIayi16MLyWWo38pDlMVAzSfcMO9v +fFzKwxPTv+1y7R+2yaZwkD2VPzFy4DO2Wk5V31VAlxWmgebs7c5zcto5/MfHebAz +xurjZ0nq/ok3qjWsQSWOMxJcE8IE6JkBvv+o4v+klxuyjYxveUDSltyfOxgYlD8w +Cr0qGhshPCk5r/OSR3vfYTMMDNvaO4UTltNiyD4FpcWktSFuN+Sgurm0S1gSpj5e +4GZz5YjNYd7bR/YH9UwLp+IISGZ1CkpuTrnv7LP3DL4G5vmGx8+DvnVlQd1rL667 +fzIjtRKZTpo8fY8PMXzABzo2f8t7thpqXqRRKMWpz0VxuBrvsVjrHNLJma5J0+fv +O6ByHDzhEfZWhTDbHyKX1zq9cw9y6jHwyvSwxIBZ+w4i4UhI6xKy5t7OFEK2ESnS +vtRPMt92QXTS2soNe5/quQwKafMWaWdbQdPcuSacOOVcBpR5oeNPKJE4A3xtupBp +acjYoSoRCu1yxjWJRlLD9w== -----END ENCRYPTED PRIVATE KEY----- diff --git a/test/js/node/test/fixtures/keys/ca4-cert.pem b/test/js/node/test/fixtures/keys/ca4-cert.pem index c38dcf9f72..b72dc9dbd6 100644 --- a/test/js/node/test/fixtures/keys/ca4-cert.pem +++ b/test/js/node/test/fixtures/keys/ca4-cert.pem @@ -1,19 +1,26 @@ -----BEGIN CERTIFICATE----- -MIIDFzCCAoCgAwIBAgIJAJHwBmNgafKfMA0GCSqGSIb3DQEBCwUAMHoxCzAJBgNV -BAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxDzANBgNVBAoMBkpveWVu -dDEQMA4GA1UECwwHTm9kZS5qczEMMAoGA1UEAwwDY2EyMSAwHgYJKoZIhvcNAQkB -FhFyeUB0aW55Y2xvdWRzLm9yZzAgFw0yMjA5MDMxNDQ2NTFaGA8yMjk2MDYxNzE0 -NDY1MVowgYgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0Yx -HzAdBgNVBAoMFlRoZSBOb2RlLmpzIEZvdW5kYXRpb24xEDAOBgNVBAsMB05vZGUu -anMxDDAKBgNVBAMMA2NhNDEeMBwGCSqGSIb3DQEJARYPY2E0QGV4YW1wbGUub3Jn -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0HnUahyfA25t8kaziu0i -vVMkTWntm0pJ8oemeO7yCGaY4QHEwN+QUzrzO7y7ngl2Dt76eEvj0mrgaW8Ao7Ns -ePfp3663g8RrBsb4cR1da2Tc8kpXCqgwbcTlm8HI/7OAdHGA2YDLNv7iyVk9meHM -gYfO9dVgrZ7RxfnGwNMJdNjYJrd02xeU6euoKl9j/ZWCG5xHAM2xAXOKHGm8toIm -+Ss6iZXY8kypy7Fjwyv7jMT8V+pzIWu24xd3Y3s07r59nkFmQ29nHMTaLP7Tf3TY -MBI5mp8fet732aBoywpQ/w05LR9gdM1jpUvIlmhj4qGskv17AMEmRecwic3opq/b -yQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GBADsFOR+N -Bcm2FyHOutoFpQn70qAFg0xlO3NTH87uubbs6rf3LDrsskhjskfs6wpUk56IJOoU -H7+F7aDDtSrnxzxxC5eZeGyaN05T5N01OdK3xvqUnr7mg/Ce0jnxrZhxHI8SHOqs -Kwrg4fRasUHGhH286Y13xOj2pLSrVoSbkXsA +MIIEaDCCA1CgAwIBAgIUDxaIwCfB2vttbQL/LlnVg4mwMUAwDQYJKoZIhvcNAQEL +BQAwejELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjEPMA0G +A1UECgwGSm95ZW50MRAwDgYDVQQLDAdOb2RlLmpzMQwwCgYDVQQDDANjYTIxIDAe +BgkqhkiG9w0BCQEWEXJ5QHRpbnljbG91ZHMub3JnMCAXDTI0MDgyNzIyNTg0NFoY +DzIyOTgwNjExMjI1ODQ0WjCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQsw +CQYDVQQHDAJTRjEfMB0GA1UECgwWVGhlIE5vZGUuanMgRm91bmRhdGlvbjEQMA4G +A1UECwwHTm9kZS5qczEMMAoGA1UEAwwDY2E0MR4wHAYJKoZIhvcNAQkBFg9jYTRA +ZXhhbXBsZS5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDQedRq +HJ8Dbm3yRrOK7SK9UyRNae2bSknyh6Z47vIIZpjhAcTA35BTOvM7vLueCXYO3vp4 +S+PSauBpbwCjs2x49+nfrreDxGsGxvhxHV1rZNzySlcKqDBtxOWbwcj/s4B0cYDZ +gMs2/uLJWT2Z4cyBh8711WCtntHF+cbA0wl02Ngmt3TbF5Tp66gqX2P9lYIbnEcA +zbEBc4ocaby2gib5KzqJldjyTKnLsWPDK/uMxPxX6nMha7bjF3djezTuvn2eQWZD +b2ccxNos/tN/dNgwEjmanx963vfZoGjLClD/DTktH2B0zWOlS8iWaGPioayS/XsA +wSZF5zCJzeimr9vJAgMBAAGjgdQwgdEwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQU +Tc8o3KouldTCYNQHvW09ZBv9sW0wgaEGA1UdIwSBmTCBlqF+pHwwejELMAkGA1UE +BhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjEPMA0GA1UECgwGSm95ZW50 +MRAwDgYDVQQLDAdOb2RlLmpzMQwwCgYDVQQDDANjYTIxIDAeBgkqhkiG9w0BCQEW +EXJ5QHRpbnljbG91ZHMub3JnghRsoeMhBMOB34RpWIz6SD/UwaqquzANBgkqhkiG +9w0BAQsFAAOCAQEAKtd7q+5123jVDzpydg4o3FO84u/1gzlkQ9gAc0q48/ePD/0g +GTeTLz3fODq84l0Nx0g2XbcnrnH/07dzykZokAI6TFhv9qioeMmZa5UhwLSFynXJ +tqP26jA2/dpofGrVV2up/dJ9nw/jmvsRTigvIjkPyofFyxyssNmUIOXgEB6szthQ +mg0VKqgcF3yPDFiSMNh7YnxKd6Rsw1uujtRR+dbkLJs3m0sk+MNra7+LIfqVU5Iv +UyieguUmYYtW9rWTjxVCEl84teryIFJK81GlX/wiq1Nx3DZj+DCSwJMdl5DDzvH8 +EnE1L+MapqCnP0eAmNdWwF5SVxfKUwtt6uPpYw== -----END CERTIFICATE----- diff --git a/test/js/node/test/fixtures/keys/dh3072.pem b/test/js/node/test/fixtures/keys/dh3072.pem new file mode 100644 index 0000000000..50e0533d89 --- /dev/null +++ b/test/js/node/test/fixtures/keys/dh3072.pem @@ -0,0 +1,11 @@ +-----BEGIN DH PARAMETERS----- +MIIBiAKCAYEAmV6aZ8ADnmRQoF9aGlV1AmajCkoc2eEltua1KpGFrxM0cr99gcS9 +/zxTDo8ixwPoHBOOBD+9MN6KbSJ+61xvu9yQ2qt8HfNcUI7QZxdVQ4ZHCQM3Jw8h +BPHFgjpx8w/pteZ3+L42felUxbd8/qfDv+gKsfuxrm6Ht7zzKLfbX9oNdJwpxX7N +yGP3nNadYDM/ZmvmEY8xh2dwLHSMaAP1gxuWiitdYXX60Yg6EFgIotznqbdW075D +KccGTTseFx9gNbxYkW33qX/p5IAf3wRFmptiRWCol88NHTDqtQRs0nhVQ1R28tiL +rQhSJLHLSa4esF+whfC64oXECr2AtarcKWG+LX1dEWI4SXqurnBPiBoyqfVWHS4b +PVgR90LlBJoXqblhsVrd+CkJI7ULDJmSA/cpgCqXH6vSvhb40yr5rpU4vZz+zhHY +CTXVpH95JD35PiZOfQYhfDA4LGvfICPLIH7E8YL5v2F6Xxsf8trI5KiAs1S3TN8b +lsLV6og5VoPXAgEC +-----END DH PARAMETERS----- diff --git a/test/js/node/test/fixtures/keys/dh_private.pem b/test/js/node/test/fixtures/keys/dh_private.pem new file mode 100644 index 0000000000..25c4edc5ea --- /dev/null +++ b/test/js/node/test/fixtures/keys/dh_private.pem @@ -0,0 +1,9 @@ +-----BEGIN PRIVATE KEY----- +MIIBPgIBADCCARcGCSqGSIb3DQEDATCCAQgCggEBAP//////////rfhUWKK7Spqv +3FYgJz088di5xYPOLTaVqeE2QRRkM/vMk53OJJs++X0v42NjDHXY9oGyAq7EYXrT +3x7V1f1lYSQz9R9fBm7QhWNlVT3tGvO1VxNef1fJNZhPDHDg5ot34qaJ2vPv6HId +8VihNq3nNTCsyk9IOnl6vAqxgrMk+2HRCKlLssjj+7lq2rdg1/RoHU9Co945TfSu +Vu3nY3K7GQsHp8juCm1wngL84c334uzANATNKDQvYZFy/pzphYP/jk8SMu7ygYPD +/jsbTG+tczu1/LwuwiAFxY7xg30Wg7LG80omwbLv+ohrQjhhKFyX//////////8C +AQIEHgIcKNGyhQRxIhVXoyktdymwbN6MgXv85vPax+8eqQ== +-----END PRIVATE KEY----- diff --git a/test/js/node/test/fixtures/keys/dh_public.pem b/test/js/node/test/fixtures/keys/dh_public.pem new file mode 100644 index 0000000000..b32815e88a --- /dev/null +++ b/test/js/node/test/fixtures/keys/dh_public.pem @@ -0,0 +1,14 @@ +-----BEGIN PUBLIC KEY----- +MIICJTCCARcGCSqGSIb3DQEDATCCAQgCggEBAP//////////rfhUWKK7Spqv3FYg +Jz088di5xYPOLTaVqeE2QRRkM/vMk53OJJs++X0v42NjDHXY9oGyAq7EYXrT3x7V +1f1lYSQz9R9fBm7QhWNlVT3tGvO1VxNef1fJNZhPDHDg5ot34qaJ2vPv6HId8Vih +Nq3nNTCsyk9IOnl6vAqxgrMk+2HRCKlLssjj+7lq2rdg1/RoHU9Co945TfSuVu3n +Y3K7GQsHp8juCm1wngL84c334uzANATNKDQvYZFy/pzphYP/jk8SMu7ygYPD/jsb +TG+tczu1/LwuwiAFxY7xg30Wg7LG80omwbLv+ohrQjhhKFyX//////////8CAQID +ggEGAAKCAQEA2whDVdYtNbr/isSFdw7rOSdbmcWrxiX6ppqDZ6yp8XjUj3/CEf/P +60X7HndX+nXD7YaPtVZxktkIpArI7C+AH7fZxBduuv2eLnvYwK82jFHKe7zvfdMr +26akMCV0kBA3ktgcftHlqYsIj52BaJlG37FRha3SDOL2yJOij3hNQhHCXTWLg7tP +GtXmD202OoZ6Ll+LxBzBCFnxVauiKnzBGeawy4gDycUEHmq5oDRR68I2gmxmsLg5 +MQVAP5ljp+FEu4+TZm6hR4wQ5PRjCQ+teq+VqMro7EbbvZpn+X9kAgKSl2WDu0fT +FbUnBn3HPBmUa/Fv/ooXrlckTUDjLkbWZQ== +-----END PUBLIC KEY----- diff --git a/test/js/node/test/fixtures/keys/legacy.pfx b/test/js/node/test/fixtures/keys/legacy.pfx new file mode 100644 index 0000000000..66fa746fa5 Binary files /dev/null and b/test/js/node/test/fixtures/keys/legacy.pfx differ diff --git a/test/js/node/test/fixtures/loader-is-internal-thread.js b/test/js/node/test/fixtures/loader-is-internal-thread.js new file mode 100644 index 0000000000..d97328bc20 --- /dev/null +++ b/test/js/node/test/fixtures/loader-is-internal-thread.js @@ -0,0 +1,3 @@ +const { isInternalThread } = require('node:worker_threads'); + +console.log(`isInternalThread: ${isInternalThread}`); \ No newline at end of file diff --git a/test/js/node/test/fixtures/module-hooks/add-hook.js b/test/js/node/test/fixtures/module-hooks/add-hook.js new file mode 100644 index 0000000000..807a73953c --- /dev/null +++ b/test/js/node/test/fixtures/module-hooks/add-hook.js @@ -0,0 +1,30 @@ +'use strict'; +const { fileURLToPath } = require('url'); +const { registerHooks } = require('module'); + +// This is a simplified version of the pirates package API to +// check that a similar API can be built on top of the public +// hooks. +function addHook(hook, options) { + function load(url, context, nextLoad) { + const result = nextLoad(url, context); + const index = url.lastIndexOf('.'); + const ext = url.slice(index); + if (!options.exts.includes(ext)) { + return result; + } + const filename = fileURLToPath(url); + if (!options.matcher(filename)) { + return result; + } + return { ...result, source: hook(result.source.toString(), filename) } + } + + const registered = registerHooks({ load }); + + return function revert() { + registered.deregister(); + }; +} + +module.exports = { addHook }; diff --git a/test/js/node/test/fixtures/module-hooks/get-stats.js b/test/js/node/test/fixtures/module-hooks/get-stats.js new file mode 100644 index 0000000000..fa5869a455 --- /dev/null +++ b/test/js/node/test/fixtures/module-hooks/get-stats.js @@ -0,0 +1,20 @@ +'use strict'; + +const path = require('path'); + +// Adapted from https://github.com/watson/module-details-from-path/blob/master/index.js +// used by require-in-the-middle to check the logic is still compatible with our new hooks. +exports.getStats = function getStats(filepath) { + const segments = filepath.split(path.sep); + const index = segments.lastIndexOf('node_modules'); + if (index === -1) return {}; + if (!segments[index + 1]) return {}; + const scoped = segments[index + 1][0] === '@'; + const name = scoped ? segments[index + 1] + '/' + segments[index + 2] : segments[index + 1]; + const offset = scoped ? 3 : 2; + return { + name: name, + basedir: segments.slice(0, index + offset).join(path.sep), + path: segments.slice(index + offset).join(path.sep) + } +}; diff --git a/test/js/node/test/fixtures/module-hooks/load-from-this-dir.js b/test/js/node/test/fixtures/module-hooks/load-from-this-dir.js new file mode 100644 index 0000000000..e1c51d2f43 --- /dev/null +++ b/test/js/node/test/fixtures/module-hooks/load-from-this-dir.js @@ -0,0 +1,4 @@ +'use strict'; + +exports.require = require; +exports.import = (id) => import(id); diff --git a/test/js/node/test/fixtures/module-hooks/log-user.cts b/test/js/node/test/fixtures/module-hooks/log-user.cts new file mode 100644 index 0000000000..2b2754f48c --- /dev/null +++ b/test/js/node/test/fixtures/module-hooks/log-user.cts @@ -0,0 +1,3 @@ +const { UserAccount, UserType } = require('./user.ts'); +const account: typeof UserAccount = new UserAccount('john', 100, UserType.Admin); +console.log(account); diff --git a/test/js/node/test/fixtures/module-hooks/log-user.mts b/test/js/node/test/fixtures/module-hooks/log-user.mts new file mode 100644 index 0000000000..9e2c3bfe1a --- /dev/null +++ b/test/js/node/test/fixtures/module-hooks/log-user.mts @@ -0,0 +1,4 @@ +import { UserAccount, UserType } from './user.ts'; +import { log } from 'node:console'; +const account: UserAccount = new UserAccount('john', 100, UserType.Admin); +log(account); diff --git a/test/js/node/test/fixtures/module-hooks/node_modules/bar-esm/bar-esm.js b/test/js/node/test/fixtures/module-hooks/node_modules/bar-esm/bar-esm.js new file mode 100644 index 0000000000..2130577ddf --- /dev/null +++ b/test/js/node/test/fixtures/module-hooks/node_modules/bar-esm/bar-esm.js @@ -0,0 +1 @@ +export const $key = 'bar-esm'; diff --git a/test/js/node/test/fixtures/module-hooks/node_modules/bar-esm/package.json b/test/js/node/test/fixtures/module-hooks/node_modules/bar-esm/package.json new file mode 100644 index 0000000000..3c3282814f --- /dev/null +++ b/test/js/node/test/fixtures/module-hooks/node_modules/bar-esm/package.json @@ -0,0 +1,6 @@ +{ + "name": "bar-esm", + "main": "bar-esm.js", + "type": "module", + "version": "1.0.0" +} diff --git a/test/js/node/test/fixtures/module-hooks/node_modules/bar/bar.js b/test/js/node/test/fixtures/module-hooks/node_modules/bar/bar.js new file mode 100644 index 0000000000..4d1a1e6dc0 --- /dev/null +++ b/test/js/node/test/fixtures/module-hooks/node_modules/bar/bar.js @@ -0,0 +1,3 @@ +module.exports = { + $key: 'bar' +}; diff --git a/test/js/node/test/fixtures/module-hooks/node_modules/bar/package.json b/test/js/node/test/fixtures/module-hooks/node_modules/bar/package.json new file mode 100644 index 0000000000..0a2e2f7d1d --- /dev/null +++ b/test/js/node/test/fixtures/module-hooks/node_modules/bar/package.json @@ -0,0 +1,6 @@ +{ + "name": "bar", + "main": "bar.js", + "version": "1.0.0" +} + diff --git a/test/js/node/test/fixtures/module-hooks/node_modules/foo-esm/foo-esm.js b/test/js/node/test/fixtures/module-hooks/node_modules/foo-esm/foo-esm.js new file mode 100644 index 0000000000..caf20f7cf2 --- /dev/null +++ b/test/js/node/test/fixtures/module-hooks/node_modules/foo-esm/foo-esm.js @@ -0,0 +1 @@ +export const $key = 'foo-esm'; \ No newline at end of file diff --git a/test/js/node/test/fixtures/module-hooks/node_modules/foo-esm/package.json b/test/js/node/test/fixtures/module-hooks/node_modules/foo-esm/package.json new file mode 100644 index 0000000000..2a98229ba2 --- /dev/null +++ b/test/js/node/test/fixtures/module-hooks/node_modules/foo-esm/package.json @@ -0,0 +1,7 @@ +{ + "name": "foo-esm", + "type": "module", + "main": "foo-esm.js", + "version": "1.0.0" +} + diff --git a/test/js/node/test/fixtures/module-hooks/node_modules/foo/foo.js b/test/js/node/test/fixtures/module-hooks/node_modules/foo/foo.js new file mode 100644 index 0000000000..91592faf7c --- /dev/null +++ b/test/js/node/test/fixtures/module-hooks/node_modules/foo/foo.js @@ -0,0 +1,3 @@ +module.exports = { + $key: 'foo' +}; diff --git a/test/js/node/test/fixtures/module-hooks/node_modules/foo/package.json b/test/js/node/test/fixtures/module-hooks/node_modules/foo/package.json new file mode 100644 index 0000000000..53416530e8 --- /dev/null +++ b/test/js/node/test/fixtures/module-hooks/node_modules/foo/package.json @@ -0,0 +1,6 @@ +{ + "name": "foo", + "main": "foo.js", + "version": "1.0.0" +} + diff --git a/test/js/node/test/fixtures/module-hooks/redirected-assert.js b/test/js/node/test/fixtures/module-hooks/redirected-assert.js new file mode 100644 index 0000000000..9855afd7ee --- /dev/null +++ b/test/js/node/test/fixtures/module-hooks/redirected-assert.js @@ -0,0 +1 @@ +exports.exports_for_test = 'redirected assert' diff --git a/test/js/node/test/fixtures/module-hooks/redirected-fs.js b/test/js/node/test/fixtures/module-hooks/redirected-fs.js new file mode 100644 index 0000000000..84631b34c3 --- /dev/null +++ b/test/js/node/test/fixtures/module-hooks/redirected-fs.js @@ -0,0 +1 @@ +export const exports_for_test = 'redirected fs'; diff --git a/test/js/node/test/fixtures/module-hooks/redirected-zlib.js b/test/js/node/test/fixtures/module-hooks/redirected-zlib.js new file mode 100644 index 0000000000..9c2fcd5ac7 --- /dev/null +++ b/test/js/node/test/fixtures/module-hooks/redirected-zlib.js @@ -0,0 +1 @@ +exports.exports_for_test = 'redirected zlib'; diff --git a/test/js/node/test/fixtures/module-hooks/register-typescript-hooks.js b/test/js/node/test/fixtures/module-hooks/register-typescript-hooks.js new file mode 100644 index 0000000000..2f9177124a --- /dev/null +++ b/test/js/node/test/fixtures/module-hooks/register-typescript-hooks.js @@ -0,0 +1,4 @@ +'use strict'; + +const { registerHooks } = require('node:module'); +registerHooks(require('./typescript-transpiler')); diff --git a/test/js/node/test/fixtures/module-hooks/typescript-transpiler.js b/test/js/node/test/fixtures/module-hooks/typescript-transpiler.js new file mode 100644 index 0000000000..b8cb638332 --- /dev/null +++ b/test/js/node/test/fixtures/module-hooks/typescript-transpiler.js @@ -0,0 +1,71 @@ +'use strict'; + +const ts = require('../snapshot/typescript'); +const extensions = { + '.cts': 'commonjs-typescript', + '.mts': 'module-typescript', + '.ts': 'typescript', +}; + +const output = { + 'commonjs-typescript': { + options: { module: ts.ModuleKind.CommonJS }, + format: 'commonjs', + }, + 'module-typescript': { + options: { module: ts.ModuleKind.ESNext }, + format: 'module', + }, + 'typescript': { + options: { module: ts.ModuleKind.NodeNext }, + format: 'commonjs', + }, +}; + +function resolve(specifier, context, nextResolve) { + const resolved = nextResolve(specifier, context); + const index = resolved.url.lastIndexOf('.'); + if (index === -1) { + return resolved; + } + const ext = resolved.url.slice(index); + const supportedFormat = extensions[ext]; + if (!supportedFormat) { + return resolved; + } + const result = { + ...resolved, + format: supportedFormat, + }; + return result; +} + +let decoder; +function load(url, context, nextLoad) { + const loadResult = nextLoad(url, context); + const { source, format } = loadResult; + + if (!format || !format.includes('typescript')) { + return { format, source }; + } + + let str = source; + if (typeof str !== 'string') { + decoder ??= new TextDecoder(); + str = decoder.decode(source); + } + const transpiled = ts.transpileModule(str, { + compilerOptions: output[format].options + }); + + const result = { + ...loadResult, + format: output[format].format, + source: transpiled.outputText, + }; + + return result; +} + +exports.load = load; +exports.resolve = resolve; diff --git a/test/js/node/test/fixtures/module-hooks/user.ts b/test/js/node/test/fixtures/module-hooks/user.ts new file mode 100644 index 0000000000..f4e064b273 --- /dev/null +++ b/test/js/node/test/fixtures/module-hooks/user.ts @@ -0,0 +1,18 @@ +enum UserType { + Staff, + Admin, +}; + +class UserAccount { + name: string; + id: number; + type: UserType; + + constructor(name: string, id: number, type: UserType) { + this.name = name; + this.id = id; + this.type = type; + } +} + +export { UserAccount, UserType }; diff --git a/test/js/node/test/fixtures/module-mocking/basic-esm-without-extension.js b/test/js/node/test/fixtures/module-mocking/basic-esm-without-extension.js new file mode 100644 index 0000000000..f2b47223e3 --- /dev/null +++ b/test/js/node/test/fixtures/module-mocking/basic-esm-without-extension.js @@ -0,0 +1 @@ +export let string = 'original esm string'; diff --git a/test/js/node/test/fixtures/module-mocking/don't-open.mjs b/test/js/node/test/fixtures/module-mocking/don't-open.mjs new file mode 100644 index 0000000000..f2b47223e3 --- /dev/null +++ b/test/js/node/test/fixtures/module-mocking/don't-open.mjs @@ -0,0 +1 @@ +export let string = 'original esm string'; diff --git a/test/js/node/test/fixtures/module-mocking/wrong-import-after-module-mocking.js b/test/js/node/test/fixtures/module-mocking/wrong-import-after-module-mocking.js new file mode 100644 index 0000000000..9220e23f50 --- /dev/null +++ b/test/js/node/test/fixtures/module-mocking/wrong-import-after-module-mocking.js @@ -0,0 +1,8 @@ +import { mock } from 'node:test'; + +try { + mock.module?.('Whatever, this is not significant', { namedExports: {} }); +} catch {} + +const { string } = await import('./basic-esm-without-extension'); +console.log(`Found string: ${string}`); // prints 'original esm string' diff --git a/test/js/node/test/fixtures/module-require-symlink/node_modules/bar/index.js b/test/js/node/test/fixtures/module-require-symlink/node_modules/bar/index.js new file mode 100644 index 0000000000..f8d439ec7e --- /dev/null +++ b/test/js/node/test/fixtures/module-require-symlink/node_modules/bar/index.js @@ -0,0 +1 @@ +exports.version = 'INCORRECT_VERSION'; diff --git a/test/js/node/test/fixtures/module-require-symlink/node_modules/dep1/index.js b/test/js/node/test/fixtures/module-require-symlink/node_modules/dep1/index.js new file mode 100644 index 0000000000..78f255b8f4 --- /dev/null +++ b/test/js/node/test/fixtures/module-require-symlink/node_modules/dep1/index.js @@ -0,0 +1,2 @@ +exports.bar = require('bar'); +exports.dep2 = require('dep2'); diff --git a/test/js/node/test/fixtures/module-require-symlink/node_modules/dep1/node_modules/bar/index.js b/test/js/node/test/fixtures/module-require-symlink/node_modules/dep1/node_modules/bar/index.js new file mode 100644 index 0000000000..6d8b0321d2 --- /dev/null +++ b/test/js/node/test/fixtures/module-require-symlink/node_modules/dep1/node_modules/bar/index.js @@ -0,0 +1 @@ +exports.version = 'CORRECT_VERSION'; diff --git a/test/js/node/test/fixtures/module-require-symlink/node_modules/dep2/index.js b/test/js/node/test/fixtures/module-require-symlink/node_modules/dep2/index.js new file mode 100644 index 0000000000..2b81d15128 --- /dev/null +++ b/test/js/node/test/fixtures/module-require-symlink/node_modules/dep2/index.js @@ -0,0 +1 @@ +exports.bar = require('bar'); diff --git a/test/js/node/test/fixtures/module-require/child/node_modules/target.js b/test/js/node/test/fixtures/module-require/child/node_modules/target.js new file mode 100644 index 0000000000..5df2baeb7e --- /dev/null +++ b/test/js/node/test/fixtures/module-require/child/node_modules/target.js @@ -0,0 +1 @@ +exports.loaded = 'from child'; diff --git a/test/js/node/test/fixtures/module-require/not-found/node_modules/module1/package.json b/test/js/node/test/fixtures/module-require/not-found/node_modules/module1/package.json new file mode 100644 index 0000000000..b5018d73b2 --- /dev/null +++ b/test/js/node/test/fixtures/module-require/not-found/node_modules/module1/package.json @@ -0,0 +1,3 @@ +{ + "main": "doesnotexist" +} diff --git a/test/js/node/test/fixtures/module-require/parent/node_modules/target.js b/test/js/node/test/fixtures/module-require/parent/node_modules/target.js new file mode 100644 index 0000000000..ee7e1f1933 --- /dev/null +++ b/test/js/node/test/fixtures/module-require/parent/node_modules/target.js @@ -0,0 +1 @@ +exports.loaded = 'from parent'; diff --git a/test/js/node/test/fixtures/node_modules/#cjs/index.js b/test/js/node/test/fixtures/node_modules/#cjs/index.js new file mode 100644 index 0000000000..c60af75988 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/#cjs/index.js @@ -0,0 +1,2 @@ +module.exports = 'cjs backcompat'; + diff --git a/test/js/node/test/fixtures/node_modules/@nodejsscope/index.js b/test/js/node/test/fixtures/node_modules/@nodejsscope/index.js new file mode 100644 index 0000000000..b42ff442ae --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/@nodejsscope/index.js @@ -0,0 +1 @@ +// Not used diff --git a/test/js/node/test/fixtures/node_modules/@nodejsscope/pkg/index.js b/test/js/node/test/fixtures/node_modules/@nodejsscope/pkg/index.js new file mode 100644 index 0000000000..ad9a93a7c1 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/@nodejsscope/pkg/index.js @@ -0,0 +1 @@ +'use strict'; diff --git a/test/js/node/test/fixtures/node_modules/asdf.js b/test/js/node/test/fixtures/node_modules/asdf.js new file mode 100644 index 0000000000..84b74de9d9 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/asdf.js @@ -0,0 +1,24 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +console.error(__filename); +console.error(module.paths.join('\n') + '\n'); +throw new Error('Should not ever get here.'); diff --git a/test/js/node/test/fixtures/node_modules/bar.js b/test/js/node/test/fixtures/node_modules/bar.js new file mode 100644 index 0000000000..5d00c9592e --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/bar.js @@ -0,0 +1,23 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +console.error(__filename); +console.error(module.paths.join('\n') + '\n'); diff --git a/test/js/node/test/fixtures/node_modules/baz/index.js b/test/js/node/test/fixtures/node_modules/baz/index.js new file mode 100644 index 0000000000..96018ee3e3 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/baz/index.js @@ -0,0 +1,31 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +console.error(__filename); +console.error(module.paths.join('\n') + '\n'); +// this should work, and get the one that doesn't throw +const assert = require('assert'); +assert.strictEqual(require('bar'), require('../bar.js')); + +// this should work, and get the one in ./node_modules/asdf.js +assert.strictEqual(require('asdf'), require('./node_modules/asdf.js')); + +module.exports = 'eye catcher'; diff --git a/test/js/node/test/fixtures/node_modules/baz/node_modules/asdf.js b/test/js/node/test/fixtures/node_modules/baz/node_modules/asdf.js new file mode 100644 index 0000000000..5d00c9592e --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/baz/node_modules/asdf.js @@ -0,0 +1,23 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +console.error(__filename); +console.error(module.paths.join('\n') + '\n'); diff --git a/test/js/node/test/fixtures/node_modules/default_index/index.js b/test/js/node/test/fixtures/node_modules/default_index/index.js new file mode 100644 index 0000000000..748e47637e --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/default_index/index.js @@ -0,0 +1 @@ +export default 'main' diff --git a/test/js/node/test/fixtures/node_modules/default_index/package.json b/test/js/node/test/fixtures/node_modules/default_index/package.json new file mode 100644 index 0000000000..7665d7a803 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/default_index/package.json @@ -0,0 +1,4 @@ +{ + "main": "index", + "type": "module" +} diff --git a/test/js/node/test/fixtures/node_modules/foo.js b/test/js/node/test/fixtures/node_modules/foo.js new file mode 100644 index 0000000000..8df770577c --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/foo.js @@ -0,0 +1,25 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +console.error(__filename); +console.error(module.paths.join('\n') + '\n'); +const assert = require('assert'); +assert.strictEqual(require('baz'), require('./baz/index.js')); diff --git a/test/js/node/test/fixtures/node_modules/interop-cjs-esm/false-esm.js b/test/js/node/test/fixtures/node_modules/interop-cjs-esm/false-esm.js new file mode 100644 index 0000000000..44dd289dd0 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjs-esm/false-esm.js @@ -0,0 +1,3 @@ +import dep from 'interop-cjsdep-false-esm'; +export default dep; +export { dep as 'module.exports' } diff --git a/test/js/node/test/fixtures/node_modules/interop-cjs-esm/false.js b/test/js/node/test/fixtures/node_modules/interop-cjs-esm/false.js new file mode 100644 index 0000000000..63d896a473 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjs-esm/false.js @@ -0,0 +1,3 @@ +import dep from 'interop-cjsdep-false'; +export default dep; +export { dep as 'module.exports' } diff --git a/test/js/node/test/fixtures/node_modules/interop-cjs-esm/fauxesmdefault-esm.js b/test/js/node/test/fixtures/node_modules/interop-cjs-esm/fauxesmdefault-esm.js new file mode 100644 index 0000000000..3b87be4bd0 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjs-esm/fauxesmdefault-esm.js @@ -0,0 +1,3 @@ +import dep from 'interop-cjsdep-fauxesmdefault-esm'; +export default dep; +export { dep as 'module.exports' } diff --git a/test/js/node/test/fixtures/node_modules/interop-cjs-esm/fauxesmdefault.js b/test/js/node/test/fixtures/node_modules/interop-cjs-esm/fauxesmdefault.js new file mode 100644 index 0000000000..325fa352e1 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjs-esm/fauxesmdefault.js @@ -0,0 +1,3 @@ +import dep from 'interop-cjsdep-fauxesmdefault'; +export default dep; +export { dep as 'module.exports' } diff --git a/test/js/node/test/fixtures/node_modules/interop-cjs-esm/fauxesmmixed-esm.js b/test/js/node/test/fixtures/node_modules/interop-cjs-esm/fauxesmmixed-esm.js new file mode 100644 index 0000000000..9390b24f8d --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjs-esm/fauxesmmixed-esm.js @@ -0,0 +1,4 @@ +import dep from 'interop-cjsdep-fauxesmmixed-esm'; +export default dep; +export { dep as 'module.exports' } + diff --git a/test/js/node/test/fixtures/node_modules/interop-cjs-esm/fauxesmmixed.js b/test/js/node/test/fixtures/node_modules/interop-cjs-esm/fauxesmmixed.js new file mode 100644 index 0000000000..d649233736 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjs-esm/fauxesmmixed.js @@ -0,0 +1,3 @@ +import dep from 'interop-cjsdep-fauxesmmixed'; +export default dep; +export { dep as 'module.exports' } diff --git a/test/js/node/test/fixtures/node_modules/interop-cjs-esm/fauxesmnamed-esm.js b/test/js/node/test/fixtures/node_modules/interop-cjs-esm/fauxesmnamed-esm.js new file mode 100644 index 0000000000..6ba7e266bc --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjs-esm/fauxesmnamed-esm.js @@ -0,0 +1,3 @@ +import dep from 'interop-cjsdep-fauxesmnamed-esm'; +export default dep; +export { dep as 'module.exports' } diff --git a/test/js/node/test/fixtures/node_modules/interop-cjs-esm/fauxesmnamed.js b/test/js/node/test/fixtures/node_modules/interop-cjs-esm/fauxesmnamed.js new file mode 100644 index 0000000000..7c6c6bfc14 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjs-esm/fauxesmnamed.js @@ -0,0 +1,3 @@ +import dep from 'interop-cjsdep-fauxesmnamed'; +export default dep; +export { dep as 'module.exports' } diff --git a/test/js/node/test/fixtures/node_modules/interop-cjs-esm/object-esm.js b/test/js/node/test/fixtures/node_modules/interop-cjs-esm/object-esm.js new file mode 100644 index 0000000000..0a4e428362 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjs-esm/object-esm.js @@ -0,0 +1,3 @@ +import dep from 'interop-cjsdep-object-esm'; +export default dep; +export { dep as 'module.exports' } diff --git a/test/js/node/test/fixtures/node_modules/interop-cjs-esm/object.js b/test/js/node/test/fixtures/node_modules/interop-cjs-esm/object.js new file mode 100644 index 0000000000..08ef3ba4f9 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjs-esm/object.js @@ -0,0 +1,3 @@ +import dep from 'interop-cjsdep-object'; +export default dep; +export { dep as 'module.exports' } diff --git a/test/js/node/test/fixtures/node_modules/interop-cjs-esm/package.json b/test/js/node/test/fixtures/node_modules/interop-cjs-esm/package.json new file mode 100644 index 0000000000..95315e635e --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjs-esm/package.json @@ -0,0 +1,17 @@ +{ + "type": "module", + "exports": { + "./false-esm": "./false-esm.js", + "./false": "./false.js", + "./fauxesmdefault-esm": "./fauxesmdefault-esm.js", + "./fauxesmdefault": "./fauxesmdefault.js", + "./fauxesmmixed-esm": "./fauxesmmixed-esm.js", + "./fauxesmmixed": "./fauxesmmixed.js", + "./fauxesmnamed-esm": "./fauxesmnamed-esm.js", + "./fauxesmnamed": "./fauxesmnamed.js", + "./object-esm": "./object-esm.js", + "./object": "./object.js", + "./string-esm": "./string-esm.js", + "./string": "./string.js" + } +} diff --git a/test/js/node/test/fixtures/node_modules/interop-cjs-esm/string-esm.js b/test/js/node/test/fixtures/node_modules/interop-cjs-esm/string-esm.js new file mode 100644 index 0000000000..6072f01bc9 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjs-esm/string-esm.js @@ -0,0 +1,3 @@ +import dep from 'interop-cjsdep-string-esm'; +export default dep; +export { dep as 'module.exports' } diff --git a/test/js/node/test/fixtures/node_modules/interop-cjs-esm/string.js b/test/js/node/test/fixtures/node_modules/interop-cjs-esm/string.js new file mode 100644 index 0000000000..74297e8eee --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjs-esm/string.js @@ -0,0 +1,3 @@ +import dep from 'interop-cjsdep-string'; +export default dep; +export { dep as 'module.exports' } diff --git a/test/js/node/test/fixtures/node_modules/interop-cjs/false-esm.js b/test/js/node/test/fixtures/node_modules/interop-cjs/false-esm.js new file mode 100644 index 0000000000..eeb934952b --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjs/false-esm.js @@ -0,0 +1 @@ +module.exports = require('interop-cjsdep-false-esm'); diff --git a/test/js/node/test/fixtures/node_modules/interop-cjs/false.js b/test/js/node/test/fixtures/node_modules/interop-cjs/false.js new file mode 100644 index 0000000000..459ccbeee4 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjs/false.js @@ -0,0 +1 @@ +module.exports = require('interop-cjsdep-false'); diff --git a/test/js/node/test/fixtures/node_modules/interop-cjs/fauxesmdefault-esm.js b/test/js/node/test/fixtures/node_modules/interop-cjs/fauxesmdefault-esm.js new file mode 100644 index 0000000000..45e91e3c3c --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjs/fauxesmdefault-esm.js @@ -0,0 +1 @@ +module.exports = require('interop-cjsdep-fauxesmdefault-esm'); diff --git a/test/js/node/test/fixtures/node_modules/interop-cjs/fauxesmdefault.js b/test/js/node/test/fixtures/node_modules/interop-cjs/fauxesmdefault.js new file mode 100644 index 0000000000..c6e5176f52 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjs/fauxesmdefault.js @@ -0,0 +1 @@ +module.exports = require('interop-cjsdep-fauxesmdefault'); diff --git a/test/js/node/test/fixtures/node_modules/interop-cjs/fauxesmmixed-esm.js b/test/js/node/test/fixtures/node_modules/interop-cjs/fauxesmmixed-esm.js new file mode 100644 index 0000000000..6b16d657b0 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjs/fauxesmmixed-esm.js @@ -0,0 +1 @@ +module.exports = require('interop-cjsdep-fauxesmmixed-esm'); diff --git a/test/js/node/test/fixtures/node_modules/interop-cjs/fauxesmmixed.js b/test/js/node/test/fixtures/node_modules/interop-cjs/fauxesmmixed.js new file mode 100644 index 0000000000..8897d00fb3 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjs/fauxesmmixed.js @@ -0,0 +1 @@ +module.exports = require('interop-cjsdep-fauxesmmixed'); diff --git a/test/js/node/test/fixtures/node_modules/interop-cjs/fauxesmnamed-esm.js b/test/js/node/test/fixtures/node_modules/interop-cjs/fauxesmnamed-esm.js new file mode 100644 index 0000000000..67ed05bfa7 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjs/fauxesmnamed-esm.js @@ -0,0 +1 @@ +module.exports = require('interop-cjsdep-fauxesmnamed-esm'); diff --git a/test/js/node/test/fixtures/node_modules/interop-cjs/fauxesmnamed.js b/test/js/node/test/fixtures/node_modules/interop-cjs/fauxesmnamed.js new file mode 100644 index 0000000000..092ec33326 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjs/fauxesmnamed.js @@ -0,0 +1 @@ +module.exports = require('interop-cjsdep-fauxesmnamed'); diff --git a/test/js/node/test/fixtures/node_modules/interop-cjs/object-esm.js b/test/js/node/test/fixtures/node_modules/interop-cjs/object-esm.js new file mode 100644 index 0000000000..f0e0d3fa3d --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjs/object-esm.js @@ -0,0 +1 @@ +module.exports = require('interop-cjsdep-object-esm'); diff --git a/test/js/node/test/fixtures/node_modules/interop-cjs/object.js b/test/js/node/test/fixtures/node_modules/interop-cjs/object.js new file mode 100644 index 0000000000..ff2d57e11b --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjs/object.js @@ -0,0 +1 @@ +module.exports = require('interop-cjsdep-object'); diff --git a/test/js/node/test/fixtures/node_modules/interop-cjs/package.json b/test/js/node/test/fixtures/node_modules/interop-cjs/package.json new file mode 100644 index 0000000000..9e8c0b3f59 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjs/package.json @@ -0,0 +1,17 @@ +{ + "type": "commonjs", + "exports": { + "./false-esm": "./false-esm.js", + "./false": "./false.js", + "./fauxesmdefault-esm": "./fauxesmdefault-esm.js", + "./fauxesmdefault": "./fauxesmdefault.js", + "./fauxesmmixed-esm": "./fauxesmmixed-esm.js", + "./fauxesmmixed": "./fauxesmmixed.js", + "./fauxesmnamed-esm": "./fauxesmnamed-esm.js", + "./fauxesmnamed": "./fauxesmnamed.js", + "./object-esm": "./object-esm.js", + "./object": "./object.js", + "./string-esm": "./string-esm.js", + "./string": "./string.js" + } +} diff --git a/test/js/node/test/fixtures/node_modules/interop-cjs/string-esm.js b/test/js/node/test/fixtures/node_modules/interop-cjs/string-esm.js new file mode 100644 index 0000000000..bdd23a1b1d --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjs/string-esm.js @@ -0,0 +1 @@ +module.exports = require('interop-cjsdep-string-esm'); diff --git a/test/js/node/test/fixtures/node_modules/interop-cjs/string.js b/test/js/node/test/fixtures/node_modules/interop-cjs/string.js new file mode 100644 index 0000000000..65010183f2 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjs/string.js @@ -0,0 +1 @@ +module.exports = require('interop-cjsdep-string'); diff --git a/test/js/node/test/fixtures/node_modules/interop-cjsdep-false-esm/dep.js b/test/js/node/test/fixtures/node_modules/interop-cjsdep-false-esm/dep.js new file mode 100644 index 0000000000..7ef62281a7 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjsdep-false-esm/dep.js @@ -0,0 +1,3 @@ +const output = false; +export default output; +export { output as 'module.exports' } diff --git a/test/js/node/test/fixtures/node_modules/interop-cjsdep-false-esm/package.json b/test/js/node/test/fixtures/node_modules/interop-cjsdep-false-esm/package.json new file mode 100644 index 0000000000..f5b94a8549 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjsdep-false-esm/package.json @@ -0,0 +1,4 @@ +{ + "type": "module", + "exports": "./dep.js" +} diff --git a/test/js/node/test/fixtures/node_modules/interop-cjsdep-false/dep.js b/test/js/node/test/fixtures/node_modules/interop-cjsdep-false/dep.js new file mode 100644 index 0000000000..a5d30209bd --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjsdep-false/dep.js @@ -0,0 +1 @@ +module.exports = false; diff --git a/test/js/node/test/fixtures/node_modules/interop-cjsdep-false/package.json b/test/js/node/test/fixtures/node_modules/interop-cjsdep-false/package.json new file mode 100644 index 0000000000..e6fc986357 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjsdep-false/package.json @@ -0,0 +1,4 @@ +{ + "type": "commonjs", + "exports": "./dep.js" +} diff --git a/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmdefault-esm/dep.js b/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmdefault-esm/dep.js new file mode 100644 index 0000000000..731bf61547 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmdefault-esm/dep.js @@ -0,0 +1,7 @@ +const exports = {}; +Object.defineProperty(exports, '__esModule', { value: true }); +exports.default = 'faux esm default'; + +export default exports; + +export { exports as 'module.exports' } \ No newline at end of file diff --git a/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmdefault-esm/package.json b/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmdefault-esm/package.json new file mode 100644 index 0000000000..f5b94a8549 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmdefault-esm/package.json @@ -0,0 +1,4 @@ +{ + "type": "module", + "exports": "./dep.js" +} diff --git a/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmdefault/dep.js b/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmdefault/dep.js new file mode 100644 index 0000000000..5cd0b37b27 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmdefault/dep.js @@ -0,0 +1,2 @@ +Object.defineProperty(exports, '__esModule', { value: true }); +exports.default = 'faux esm default'; diff --git a/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmdefault/package.json b/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmdefault/package.json new file mode 100644 index 0000000000..e6fc986357 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmdefault/package.json @@ -0,0 +1,4 @@ +{ + "type": "commonjs", + "exports": "./dep.js" +} diff --git a/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmmixed-esm/dep.js b/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmmixed-esm/dep.js new file mode 100644 index 0000000000..0eef418de7 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmmixed-esm/dep.js @@ -0,0 +1,9 @@ +const exports = {}; +Object.defineProperty(exports, '__esModule', { value: true }); +exports.default = 'faux esm default'; +exports.a = 'faux esm a'; +exports.b = 'faux esm b'; + +export default exports; + +export { exports as 'module.exports' } diff --git a/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmmixed-esm/package.json b/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmmixed-esm/package.json new file mode 100644 index 0000000000..f5b94a8549 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmmixed-esm/package.json @@ -0,0 +1,4 @@ +{ + "type": "module", + "exports": "./dep.js" +} diff --git a/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmmixed/dep.js b/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmmixed/dep.js new file mode 100644 index 0000000000..926ce033f8 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmmixed/dep.js @@ -0,0 +1,4 @@ +Object.defineProperty(exports, '__esModule', { value: true }); +exports.default = 'faux esm default'; +exports.a = 'faux esm a'; +exports.b = 'faux esm b'; diff --git a/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmmixed/package.json b/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmmixed/package.json new file mode 100644 index 0000000000..e6fc986357 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmmixed/package.json @@ -0,0 +1,4 @@ +{ + "type": "commonjs", + "exports": "./dep.js" +} diff --git a/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmnamed-esm/dep.js b/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmnamed-esm/dep.js new file mode 100644 index 0000000000..ac048c7b16 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmnamed-esm/dep.js @@ -0,0 +1,8 @@ +const exports = {}; +Object.defineProperty(exports, '__esModule', { value: true }); +exports.a = 'faux esm a'; +exports.b = 'faux esm b'; + +export default exports; + +export { exports as 'module.exports' } diff --git a/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmnamed-esm/package.json b/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmnamed-esm/package.json new file mode 100644 index 0000000000..f5b94a8549 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmnamed-esm/package.json @@ -0,0 +1,4 @@ +{ + "type": "module", + "exports": "./dep.js" +} diff --git a/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmnamed/dep.js b/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmnamed/dep.js new file mode 100644 index 0000000000..e3218c09b3 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmnamed/dep.js @@ -0,0 +1,3 @@ +Object.defineProperty(exports, '__esModule', { value: true }); +exports.a = 'faux esm a'; +exports.b = 'faux esm b'; diff --git a/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmnamed/package.json b/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmnamed/package.json new file mode 100644 index 0000000000..e6fc986357 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjsdep-fauxesmnamed/package.json @@ -0,0 +1,4 @@ +{ + "type": "commonjs", + "exports": "./dep.js" +} diff --git a/test/js/node/test/fixtures/node_modules/interop-cjsdep-object-esm/dep.js b/test/js/node/test/fixtures/node_modules/interop-cjsdep-object-esm/dep.js new file mode 100644 index 0000000000..f53cd1c055 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjsdep-object-esm/dep.js @@ -0,0 +1,8 @@ +const output = { + a: 'cjs a', + b: 'cjs b' +}; + +export default output; + +export { output as 'module.exports' } diff --git a/test/js/node/test/fixtures/node_modules/interop-cjsdep-object-esm/package.json b/test/js/node/test/fixtures/node_modules/interop-cjsdep-object-esm/package.json new file mode 100644 index 0000000000..f5b94a8549 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjsdep-object-esm/package.json @@ -0,0 +1,4 @@ +{ + "type": "module", + "exports": "./dep.js" +} diff --git a/test/js/node/test/fixtures/node_modules/interop-cjsdep-object/dep.js b/test/js/node/test/fixtures/node_modules/interop-cjsdep-object/dep.js new file mode 100644 index 0000000000..c37089bccc --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjsdep-object/dep.js @@ -0,0 +1,2 @@ +exports.a = 'cjs a'; +exports.b = 'cjs b'; diff --git a/test/js/node/test/fixtures/node_modules/interop-cjsdep-object/package.json b/test/js/node/test/fixtures/node_modules/interop-cjsdep-object/package.json new file mode 100644 index 0000000000..e6fc986357 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjsdep-object/package.json @@ -0,0 +1,4 @@ +{ + "type": "commonjs", + "exports": "./dep.js" +} diff --git a/test/js/node/test/fixtures/node_modules/interop-cjsdep-string-esm/dep.js b/test/js/node/test/fixtures/node_modules/interop-cjsdep-string-esm/dep.js new file mode 100644 index 0000000000..8b718c32a1 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjsdep-string-esm/dep.js @@ -0,0 +1,3 @@ +const output = 'cjs'; +export default output; +export { output as 'module.exports' } diff --git a/test/js/node/test/fixtures/node_modules/interop-cjsdep-string-esm/package.json b/test/js/node/test/fixtures/node_modules/interop-cjsdep-string-esm/package.json new file mode 100644 index 0000000000..f5b94a8549 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjsdep-string-esm/package.json @@ -0,0 +1,4 @@ +{ + "type": "module", + "exports": "./dep.js" +} diff --git a/test/js/node/test/fixtures/node_modules/interop-cjsdep-string/dep.js b/test/js/node/test/fixtures/node_modules/interop-cjsdep-string/dep.js new file mode 100644 index 0000000000..b2825bd3c9 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjsdep-string/dep.js @@ -0,0 +1 @@ +module.exports = 'cjs'; diff --git a/test/js/node/test/fixtures/node_modules/interop-cjsdep-string/package.json b/test/js/node/test/fixtures/node_modules/interop-cjsdep-string/package.json new file mode 100644 index 0000000000..e6fc986357 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/interop-cjsdep-string/package.json @@ -0,0 +1,4 @@ +{ + "type": "commonjs", + "exports": "./dep.js" +} diff --git a/test/js/node/test/fixtures/node_modules/invalid-pjson/package.json b/test/js/node/test/fixtures/node_modules/invalid-pjson/package.json new file mode 100644 index 0000000000..5864c29c04 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/invalid-pjson/package.json @@ -0,0 +1,3 @@ +{ + "invalid" +} diff --git a/test/js/node/test/fixtures/node_modules/lone_file.js b/test/js/node/test/fixtures/node_modules/lone_file.js new file mode 100644 index 0000000000..ad9a93a7c1 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/lone_file.js @@ -0,0 +1 @@ +'use strict'; diff --git a/test/js/node/test/fixtures/node_modules/no_exports/index.js b/test/js/node/test/fixtures/node_modules/no_exports/index.js new file mode 100644 index 0000000000..8d97dd4b70 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/no_exports/index.js @@ -0,0 +1 @@ +export default 'index' diff --git a/test/js/node/test/fixtures/node_modules/no_exports/package.json b/test/js/node/test/fixtures/node_modules/no_exports/package.json new file mode 100644 index 0000000000..3dbc1ca591 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/no_exports/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/test/js/node/test/fixtures/node_modules/no_index/lib/index.js b/test/js/node/test/fixtures/node_modules/no_index/lib/index.js new file mode 100644 index 0000000000..4ba52ba2c8 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/no_index/lib/index.js @@ -0,0 +1 @@ +module.exports = {} diff --git a/test/js/node/test/fixtures/node_modules/no_index/package.json b/test/js/node/test/fixtures/node_modules/no_index/package.json new file mode 100644 index 0000000000..0c6100eada --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/no_index/package.json @@ -0,0 +1,3 @@ +{ + "main": "./lib/index.js" +} diff --git a/test/js/node/test/fixtures/node_modules/node_modules/bar.js b/test/js/node/test/fixtures/node_modules/node_modules/bar.js new file mode 100644 index 0000000000..a2aab083b7 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/node_modules/bar.js @@ -0,0 +1,22 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +throw new Error('Should not ever get here.'); diff --git a/test/js/node/test/fixtures/node_modules/pkgexports-main/main.cjs b/test/js/node/test/fixtures/node_modules/pkgexports-main/main.cjs new file mode 100644 index 0000000000..b2825bd3c9 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports-main/main.cjs @@ -0,0 +1 @@ +module.exports = 'cjs'; diff --git a/test/js/node/test/fixtures/node_modules/pkgexports-main/module.mjs b/test/js/node/test/fixtures/node_modules/pkgexports-main/module.mjs new file mode 100644 index 0000000000..bd15962246 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports-main/module.mjs @@ -0,0 +1 @@ +export default 'module'; diff --git a/test/js/node/test/fixtures/node_modules/pkgexports-main/package.json b/test/js/node/test/fixtures/node_modules/pkgexports-main/package.json new file mode 100644 index 0000000000..471ae6f713 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports-main/package.json @@ -0,0 +1,6 @@ +{ + "main": "./main.cjs", + "exports": { + "import": "./module.mjs" + } +} diff --git a/test/js/node/test/fixtures/node_modules/pkgexports-number/hidden.js b/test/js/node/test/fixtures/node_modules/pkgexports-number/hidden.js new file mode 100644 index 0000000000..c04e6ee618 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports-number/hidden.js @@ -0,0 +1 @@ +module.exports = 'not-part-of-api'; diff --git a/test/js/node/test/fixtures/node_modules/pkgexports-number/package.json b/test/js/node/test/fixtures/node_modules/pkgexports-number/package.json new file mode 100644 index 0000000000..c5807f588c --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports-number/package.json @@ -0,0 +1,3 @@ +{ + "exports": {} +} diff --git a/test/js/node/test/fixtures/node_modules/pkgexports-numeric/package.json b/test/js/node/test/fixtures/node_modules/pkgexports-numeric/package.json new file mode 100644 index 0000000000..6d20abe1d5 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports-numeric/package.json @@ -0,0 +1,6 @@ +{ + "main": "./main.cjs", + "exports": { + "0": "./should-throw" + } +} diff --git a/test/js/node/test/fixtures/node_modules/pkgexports-sugar-fail/main.js b/test/js/node/test/fixtures/node_modules/pkgexports-sugar-fail/main.js new file mode 100644 index 0000000000..dfdd47b877 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports-sugar-fail/main.js @@ -0,0 +1 @@ +module.exports = 'main'; diff --git a/test/js/node/test/fixtures/node_modules/pkgexports-sugar-fail/not-exported.js b/test/js/node/test/fixtures/node_modules/pkgexports-sugar-fail/not-exported.js new file mode 100644 index 0000000000..02e146dbe9 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports-sugar-fail/not-exported.js @@ -0,0 +1,3 @@ +'use strict'; + +module.exports = 'not-exported'; diff --git a/test/js/node/test/fixtures/node_modules/pkgexports-sugar-fail/package.json b/test/js/node/test/fixtures/node_modules/pkgexports-sugar-fail/package.json new file mode 100644 index 0000000000..bfa040647c --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports-sugar-fail/package.json @@ -0,0 +1,6 @@ +{ + "exports": { + "module": "./main.js", + "./main": "./main.js" + } +} diff --git a/test/js/node/test/fixtures/node_modules/pkgexports-sugar/main.js b/test/js/node/test/fixtures/node_modules/pkgexports-sugar/main.js new file mode 100644 index 0000000000..6655b150f2 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports-sugar/main.js @@ -0,0 +1,10 @@ +const assert = require('assert'); +module.exports = 'main'; + +// Test self-resolve +require('@exports/sugar'); + +// Test self-resolve dynamic import +import('@exports/sugar').then(impt => { + assert.strictEqual(impt.default, 'main'); +}); diff --git a/test/js/node/test/fixtures/node_modules/pkgexports-sugar/not-exported.js b/test/js/node/test/fixtures/node_modules/pkgexports-sugar/not-exported.js new file mode 100644 index 0000000000..02e146dbe9 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports-sugar/not-exported.js @@ -0,0 +1,3 @@ +'use strict'; + +module.exports = 'not-exported'; diff --git a/test/js/node/test/fixtures/node_modules/pkgexports-sugar/package.json b/test/js/node/test/fixtures/node_modules/pkgexports-sugar/package.json new file mode 100644 index 0000000000..93f7d18f4a --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports-sugar/package.json @@ -0,0 +1,4 @@ +{ + "name": "@exports/sugar", + "exports": "./main.js" +} diff --git a/test/js/node/test/fixtures/node_modules/pkgexports-sugar2/main.js b/test/js/node/test/fixtures/node_modules/pkgexports-sugar2/main.js new file mode 100644 index 0000000000..dfdd47b877 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports-sugar2/main.js @@ -0,0 +1 @@ +module.exports = 'main'; diff --git a/test/js/node/test/fixtures/node_modules/pkgexports-sugar2/not-exported.js b/test/js/node/test/fixtures/node_modules/pkgexports-sugar2/not-exported.js new file mode 100644 index 0000000000..02e146dbe9 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports-sugar2/not-exported.js @@ -0,0 +1,3 @@ +'use strict'; + +module.exports = 'not-exported'; diff --git a/test/js/node/test/fixtures/node_modules/pkgexports-sugar2/package.json b/test/js/node/test/fixtures/node_modules/pkgexports-sugar2/package.json new file mode 100644 index 0000000000..bef4889bea --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports-sugar2/package.json @@ -0,0 +1,6 @@ +{ + "exports": { + "require": "./not-exported.js", + "import": "./main.js" + } +} diff --git a/test/js/node/test/fixtures/node_modules/pkgexports/addons-entry.js b/test/js/node/test/fixtures/node_modules/pkgexports/addons-entry.js new file mode 100644 index 0000000000..6487c639f4 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports/addons-entry.js @@ -0,0 +1,3 @@ +'use strict'; + +module.exports = 'using native addons'; diff --git a/test/js/node/test/fixtures/node_modules/pkgexports/asdf.js b/test/js/node/test/fixtures/node_modules/pkgexports/asdf.js new file mode 100644 index 0000000000..683f2d8ba6 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports/asdf.js @@ -0,0 +1 @@ +module.exports = 'asdf'; diff --git a/test/js/node/test/fixtures/node_modules/pkgexports/custom-condition.js b/test/js/node/test/fixtures/node_modules/pkgexports/custom-condition.js new file mode 100644 index 0000000000..63d77460d8 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports/custom-condition.js @@ -0,0 +1 @@ +module.exports = 'from custom condition'; diff --git a/test/js/node/test/fixtures/node_modules/pkgexports/custom-condition.mjs b/test/js/node/test/fixtures/node_modules/pkgexports/custom-condition.mjs new file mode 100644 index 0000000000..87d8b8a8fa --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports/custom-condition.mjs @@ -0,0 +1 @@ +export default 'from custom condition'; diff --git a/test/js/node/test/fixtures/node_modules/pkgexports/internal/test.js b/test/js/node/test/fixtures/node_modules/pkgexports/internal/test.js new file mode 100644 index 0000000000..bdf53dcd04 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports/internal/test.js @@ -0,0 +1,3 @@ +'use strict'; + +module.exports = 'internal only'; diff --git a/test/js/node/test/fixtures/node_modules/pkgexports/lib/hole.js b/test/js/node/test/fixtures/node_modules/pkgexports/lib/hole.js new file mode 100644 index 0000000000..124b0932ad --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports/lib/hole.js @@ -0,0 +1,10 @@ +'use strict'; + +module.exports = { + async importFromInside(specifier) { + return import(specifier); + }, + async requireFromInside(specifier) { + return { default: require(specifier) }; + }, +}; diff --git a/test/js/node/test/fixtures/node_modules/pkgexports/no-addons-entry.js b/test/js/node/test/fixtures/node_modules/pkgexports/no-addons-entry.js new file mode 100644 index 0000000000..85096c5aab --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports/no-addons-entry.js @@ -0,0 +1,3 @@ +'use strict'; + +module.exports = 'not using native addons'; diff --git a/test/js/node/test/fixtures/node_modules/pkgexports/node_modules/internalpkg/x.js b/test/js/node/test/fixtures/node_modules/pkgexports/node_modules/internalpkg/x.js new file mode 100644 index 0000000000..888cae37af --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports/node_modules/internalpkg/x.js @@ -0,0 +1 @@ +module.exports = 42; diff --git a/test/js/node/test/fixtures/node_modules/pkgexports/not-exported.js b/test/js/node/test/fixtures/node_modules/pkgexports/not-exported.js new file mode 100644 index 0000000000..02e146dbe9 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports/not-exported.js @@ -0,0 +1,3 @@ +'use strict'; + +module.exports = 'not-exported'; diff --git a/test/js/node/test/fixtures/node_modules/pkgexports/package.json b/test/js/node/test/fixtures/node_modules/pkgexports/package.json new file mode 100644 index 0000000000..f68f1ac812 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports/package.json @@ -0,0 +1,68 @@ +{ + "name": "pkg-exports", + "exports": { + "./hole": "./lib/hole.js", + "./space": "./sp%20ce.js", + "./valid-cjs": "./asdf.js", + "./sub/*": "./*", + "./sub/internal/*": null, + "./belowdir/*": "../belowdir/*", + "./belowfile": "../belowfile", + "./null": null, + "./null/": null, + "./invalid1": {}, + "./invalid2": 1234, + "./invalid3": "", + "./invalid4": {}, + "./invalid5": "invalid5.js", + "./fallbackdir/*": [[], null, {}, "builtin:x/*", "./*"], + "./fallbackfile": [[], null, {}, "builtin:x", "./asdf.js"], + "./nofallback1": [], + "./nofallback2": [null, {}, "builtin:x"], + "./nodemodules": "./node_modules/internalpkg/x.js", + "./doubleslash": ".//asdf.js", + "./no-addons": { + "node-addons": "./addons-entry.js", + "default": "./no-addons-entry.js" + }, + "./condition": [{ + "custom-condition": { + "import": "./custom-condition.mjs", + "require": "./custom-condition.js" + }, + "import": "///overridden", + "require": { + "require": { + "nomatch": "./nothing.js" + }, + "default": "./sp ce.js" + }, + "default": "./asdf.js", + "node": "./lib/hole.js", + "import": { + "nomatch": "./nothing.js" + } + }], + "./no-ext": "./asdf", + "./resolve-self": { + "require": "./resolve-self.js", + "import": "./resolve-self.mjs" + }, + "./resolve-self-invalid": { + "require": "./resolve-self-invalid.js", + "import": "./resolve-self-invalid.mjs" + }, + "./*/trailer": "./subpath/*.js", + "./*/*railer": "never", + "./*trailer": "never", + "./*/dir2/trailer": "./subpath/*/index.js", + "./a/*": "./subpath/*.js", + "./a/b/": "./nomatch/", + "./a/b*": "./subpath*.js", + "./subpath/*": "./subpath/*", + "./subpath/sub-*": "./subpath/dir1/*.js", + "./subpath/sub-*.js": "./subpath/dir1/*.js", + "./features/*": "./subpath/*/*.js", + "./trailing-pattern-slash*": "./trailing-pattern-slash*index.js" + } +} diff --git a/test/js/node/test/fixtures/node_modules/pkgexports/resolve-self-invalid.js b/test/js/node/test/fixtures/node_modules/pkgexports/resolve-self-invalid.js new file mode 100644 index 0000000000..c3ebf76fc1 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports/resolve-self-invalid.js @@ -0,0 +1 @@ +require('pkg-exports/invalid2'); diff --git a/test/js/node/test/fixtures/node_modules/pkgexports/resolve-self-invalid.mjs b/test/js/node/test/fixtures/node_modules/pkgexports/resolve-self-invalid.mjs new file mode 100644 index 0000000000..1edbf62c4b --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports/resolve-self-invalid.mjs @@ -0,0 +1 @@ +import 'pkg-exports/invalid2'; diff --git a/test/js/node/test/fixtures/node_modules/pkgexports/resolve-self.js b/test/js/node/test/fixtures/node_modules/pkgexports/resolve-self.js new file mode 100644 index 0000000000..38ded86f3b --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports/resolve-self.js @@ -0,0 +1,2 @@ +require('pkg-exports/valid-cjs'); +module.exports = 'self-cjs'; diff --git a/test/js/node/test/fixtures/node_modules/pkgexports/resolve-self.mjs b/test/js/node/test/fixtures/node_modules/pkgexports/resolve-self.mjs new file mode 100644 index 0000000000..1bec0af0ce --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports/resolve-self.mjs @@ -0,0 +1,2 @@ +import 'pkg-exports/valid-cjs'; +export default 'self-mjs'; diff --git a/test/js/node/test/fixtures/node_modules/pkgexports/sp ce.js b/test/js/node/test/fixtures/node_modules/pkgexports/sp ce.js new file mode 100644 index 0000000000..570237506e --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports/sp ce.js @@ -0,0 +1,3 @@ +'use strict'; + +module.exports = 'encoded path'; diff --git a/test/js/node/test/fixtures/node_modules/pkgexports/subpath/dir1/dir1.js b/test/js/node/test/fixtures/node_modules/pkgexports/subpath/dir1/dir1.js new file mode 100644 index 0000000000..dfdd47b877 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports/subpath/dir1/dir1.js @@ -0,0 +1 @@ +module.exports = 'main'; diff --git a/test/js/node/test/fixtures/node_modules/pkgexports/subpath/dir1/package.json b/test/js/node/test/fixtures/node_modules/pkgexports/subpath/dir1/package.json new file mode 100644 index 0000000000..ca1584ec6f --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports/subpath/dir1/package.json @@ -0,0 +1,3 @@ +{ + "main": "dir1" +} diff --git a/test/js/node/test/fixtures/node_modules/pkgexports/subpath/dir2/index.js b/test/js/node/test/fixtures/node_modules/pkgexports/subpath/dir2/index.js new file mode 100644 index 0000000000..d17bd0f1e9 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports/subpath/dir2/index.js @@ -0,0 +1 @@ +module.exports = 'index'; diff --git a/test/js/node/test/fixtures/node_modules/pkgexports/subpath/file.js b/test/js/node/test/fixtures/node_modules/pkgexports/subpath/file.js new file mode 100644 index 0000000000..1485f701f4 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports/subpath/file.js @@ -0,0 +1,2 @@ +module.exports = 'file'; + diff --git a/test/js/node/test/fixtures/node_modules/pkgexports/trailing-pattern-slash/index.js b/test/js/node/test/fixtures/node_modules/pkgexports/trailing-pattern-slash/index.js new file mode 100644 index 0000000000..613bddbb6a --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/pkgexports/trailing-pattern-slash/index.js @@ -0,0 +1 @@ +module.exports = 'trailing-pattern-slash'; diff --git a/test/js/node/test/fixtures/node_modules/some_module/folder%25with percentage#/index.js b/test/js/node/test/fixtures/node_modules/some_module/folder%25with percentage#/index.js new file mode 100644 index 0000000000..ad9a93a7c1 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/some_module/folder%25with percentage#/index.js @@ -0,0 +1 @@ +'use strict'; diff --git a/test/js/node/test/fixtures/node_modules/some_module/index.js b/test/js/node/test/fixtures/node_modules/some_module/index.js new file mode 100644 index 0000000000..a2d739266c --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/some_module/index.js @@ -0,0 +1,3 @@ +'use strict' + +module.exports = { main: true } diff --git a/test/js/node/test/fixtures/node_modules/some_module/obj.js b/test/js/node/test/fixtures/node_modules/some_module/obj.js new file mode 100644 index 0000000000..249478e5ca --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/some_module/obj.js @@ -0,0 +1,3 @@ +'use strict'; + +module.exports = { obj: 'module' } diff --git a/test/js/node/test/fixtures/node_modules/some_module/package.json b/test/js/node/test/fixtures/node_modules/some_module/package.json new file mode 100644 index 0000000000..95a52cc610 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/some_module/package.json @@ -0,0 +1,12 @@ +{ + "name": "some_module", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/test/js/node/test/fixtures/node_modules/type-main/index.js b/test/js/node/test/fixtures/node_modules/type-main/index.js new file mode 100644 index 0000000000..a4cb539643 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/type-main/index.js @@ -0,0 +1 @@ +export default 'asdf'; diff --git a/test/js/node/test/fixtures/node_modules/type-main/package.json b/test/js/node/test/fixtures/node_modules/type-main/package.json new file mode 100644 index 0000000000..7665d7a803 --- /dev/null +++ b/test/js/node/test/fixtures/node_modules/type-main/package.json @@ -0,0 +1,4 @@ +{ + "main": "index", + "type": "module" +} diff --git a/test/js/node/test/fixtures/package-main-enoent/node_modules/package-main-enoent/fhqwhgads.js b/test/js/node/test/fixtures/package-main-enoent/node_modules/package-main-enoent/fhqwhgads.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/js/node/test/fixtures/package-main-enoent/node_modules/package-main-enoent/package.json b/test/js/node/test/fixtures/package-main-enoent/node_modules/package-main-enoent/package.json new file mode 100644 index 0000000000..4b90985c74 --- /dev/null +++ b/test/js/node/test/fixtures/package-main-enoent/node_modules/package-main-enoent/package.json @@ -0,0 +1,4 @@ +{ + "name": "package-main-enoent", + "main": "./fhqwhgads.js" +} diff --git a/test/js/node/test/fixtures/packages/cjs-main-no-index/main.js b/test/js/node/test/fixtures/packages/cjs-main-no-index/main.js new file mode 100644 index 0000000000..888cae37af --- /dev/null +++ b/test/js/node/test/fixtures/packages/cjs-main-no-index/main.js @@ -0,0 +1 @@ +module.exports = 42; diff --git a/test/js/node/test/fixtures/packages/cjs-main-no-index/other.js b/test/js/node/test/fixtures/packages/cjs-main-no-index/other.js new file mode 100644 index 0000000000..8fa4827678 --- /dev/null +++ b/test/js/node/test/fixtures/packages/cjs-main-no-index/other.js @@ -0,0 +1,3 @@ +const answer = require('./'); + +module.exports = answer+1; diff --git a/test/js/node/test/fixtures/packages/cjs-main-no-index/package.json b/test/js/node/test/fixtures/packages/cjs-main-no-index/package.json new file mode 100644 index 0000000000..897d3f99da --- /dev/null +++ b/test/js/node/test/fixtures/packages/cjs-main-no-index/package.json @@ -0,0 +1,5 @@ +{ + "name": "main-no-index", + "main": "./main.js", + "type":"commonjs" +} diff --git a/test/js/node/test/fixtures/packages/nested/package.json b/test/js/node/test/fixtures/packages/nested/package.json new file mode 100644 index 0000000000..0ce6c71db4 --- /dev/null +++ b/test/js/node/test/fixtures/packages/nested/package.json @@ -0,0 +1 @@ +{"name": "package-with-sub-package"} diff --git a/test/js/node/test/fixtures/packages/nested/sub-pkg-cjs/index.js b/test/js/node/test/fixtures/packages/nested/sub-pkg-cjs/index.js new file mode 100644 index 0000000000..679ad2d65e --- /dev/null +++ b/test/js/node/test/fixtures/packages/nested/sub-pkg-cjs/index.js @@ -0,0 +1,3 @@ +const { findPackageJSON } = require('node:module'); + +module.exports = findPackageJSON('..', __filename); diff --git a/test/js/node/test/fixtures/packages/nested/sub-pkg-cjs/package.json b/test/js/node/test/fixtures/packages/nested/sub-pkg-cjs/package.json new file mode 100644 index 0000000000..2dec7591cd --- /dev/null +++ b/test/js/node/test/fixtures/packages/nested/sub-pkg-cjs/package.json @@ -0,0 +1 @@ +{"name": "sub-package", "type": "commonjs"} diff --git a/test/js/node/test/fixtures/packages/nested/sub-pkg-esm/index.js b/test/js/node/test/fixtures/packages/nested/sub-pkg-esm/index.js new file mode 100644 index 0000000000..546390de4b --- /dev/null +++ b/test/js/node/test/fixtures/packages/nested/sub-pkg-esm/index.js @@ -0,0 +1,3 @@ +import { findPackageJSON } from 'node:module'; + +export default findPackageJSON('..', import.meta.url); diff --git a/test/js/node/test/fixtures/packages/nested/sub-pkg-esm/package.json b/test/js/node/test/fixtures/packages/nested/sub-pkg-esm/package.json new file mode 100644 index 0000000000..c294ec5158 --- /dev/null +++ b/test/js/node/test/fixtures/packages/nested/sub-pkg-esm/package.json @@ -0,0 +1 @@ +{"name": "sub-package", "type": "module"} diff --git a/test/js/node/test/fixtures/packages/root-types-field/index.js b/test/js/node/test/fixtures/packages/root-types-field/index.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/js/node/test/fixtures/packages/root-types-field/package.json b/test/js/node/test/fixtures/packages/root-types-field/package.json new file mode 100644 index 0000000000..4af6844244 --- /dev/null +++ b/test/js/node/test/fixtures/packages/root-types-field/package.json @@ -0,0 +1,5 @@ +{ + "name": "package-with-unrecognised-fields", + "type": "module", + "types": "./index.d.ts" +} diff --git a/test/js/node/test/fixtures/permission/fs-read.js b/test/js/node/test/fixtures/permission/fs-read.js index 0fdbc3ced9..fa4ea1207f 100644 --- a/test/js/node/test/fixtures/permission/fs-read.js +++ b/test/js/node/test/fixtures/permission/fs-read.js @@ -5,9 +5,11 @@ const common = require('../../common'); const assert = require('assert'); const fs = require('fs'); const path = require('path'); +const { pathToFileURL } = require('url'); const blockedFile = process.env.BLOCKEDFILE; -const blockedFileURL = new URL('file://' + process.env.BLOCKEDFILE); +const bufferBlockedFile = Buffer.from(process.env.BLOCKEDFILE); +const blockedFileURL = pathToFileURL(process.env.BLOCKEDFILE); const blockedFolder = process.env.BLOCKEDFOLDER; const allowedFolder = process.env.ALLOWEDFOLDER; const regularFile = __filename; @@ -19,6 +21,11 @@ const regularFile = __filename; permission: 'FileSystemRead', resource: path.toNamespacedPath(blockedFile), })); + fs.readFile(bufferBlockedFile, common.expectsError({ + code: 'ERR_ACCESS_DENIED', + permission: 'FileSystemRead', + resource: path.toNamespacedPath(blockedFile), + })); assert.throws(() => { fs.readFileSync(blockedFile); }, common.expectsError({ @@ -77,6 +84,11 @@ const regularFile = __filename; permission: 'FileSystemRead', resource: path.toNamespacedPath(blockedFile), })); + fs.stat(bufferBlockedFile, common.expectsError({ + code: 'ERR_ACCESS_DENIED', + permission: 'FileSystemRead', + resource: path.toNamespacedPath(blockedFile), + })); assert.throws(() => { fs.statSync(blockedFile); }, common.expectsError({ @@ -110,6 +122,11 @@ const regularFile = __filename; permission: 'FileSystemRead', resource: path.toNamespacedPath(blockedFile), })); + fs.access(bufferBlockedFile, fs.constants.R_OK, common.expectsError({ + code: 'ERR_ACCESS_DENIED', + permission: 'FileSystemRead', + resource: path.toNamespacedPath(blockedFile), + })); assert.throws(() => { fs.accessSync(blockedFileURL, fs.constants.R_OK); }, common.expectsError({ @@ -138,6 +155,11 @@ const regularFile = __filename; permission: 'FileSystemRead', resource: path.toNamespacedPath(blockedFile), })); + fs.copyFile(bufferBlockedFile, path.join(blockedFolder, 'any-other-file'), common.expectsError({ + code: 'ERR_ACCESS_DENIED', + permission: 'FileSystemRead', + resource: path.toNamespacedPath(blockedFile), + })); assert.throws(() => { fs.copyFileSync(blockedFileURL, path.join(blockedFolder, 'any-other-file')); }, common.expectsError({ @@ -161,23 +183,28 @@ const regularFile = __filename; }, common.expectsError({ code: 'ERR_ACCESS_DENIED', permission: 'FileSystemRead', - // cpSync calls statSync before reading blockedFile - resource: path.toNamespacedPath(blockedFolder), + resource: path.toNamespacedPath(blockedFile), + })); + assert.throws(() => { + fs.cpSync(bufferBlockedFile, path.join(blockedFolder, 'any-other-file')); + }, common.expectsError({ + code: 'ERR_ACCESS_DENIED', + permission: 'FileSystemRead', + resource: path.toNamespacedPath(blockedFile), })); assert.throws(() => { fs.cpSync(blockedFileURL, path.join(blockedFolder, 'any-other-file')); }, common.expectsError({ code: 'ERR_ACCESS_DENIED', permission: 'FileSystemRead', - // cpSync calls statSync before reading blockedFile - resource: path.toNamespacedPath(blockedFolder), + resource: path.toNamespacedPath(blockedFile), })); assert.throws(() => { fs.cpSync(blockedFile, path.join(__dirname, 'any-other-file')); }, common.expectsError({ code: 'ERR_ACCESS_DENIED', permission: 'FileSystemRead', - resource: path.toNamespacedPath(__dirname), + resource: path.toNamespacedPath(blockedFile), })); } @@ -188,6 +215,11 @@ const regularFile = __filename; permission: 'FileSystemRead', resource: path.toNamespacedPath(blockedFile), })); + fs.open(bufferBlockedFile, 'r', common.expectsError({ + code: 'ERR_ACCESS_DENIED', + permission: 'FileSystemRead', + resource: path.toNamespacedPath(blockedFile), + })); assert.throws(() => { fs.openSync(blockedFileURL, 'r'); }, common.expectsError({ @@ -250,6 +282,18 @@ const regularFile = __filename; permission: 'FileSystemRead', resource: path.toNamespacedPath(blockedFolder), })); + assert.throws(() => { + fs.readdirSync(blockedFolder, { recursive: true }); + }, common.expectsError({ + code: 'ERR_ACCESS_DENIED', + permission: 'FileSystemRead', + resource: path.toNamespacedPath(blockedFolder), + })); + fs.readdir(blockedFolder, { recursive: true }, common.expectsError({ + code: 'ERR_ACCESS_DENIED', + permission: 'FileSystemRead', + resource: path.toNamespacedPath(blockedFolder), + })); assert.throws(() => { fs.readdirSync(blockedFolder); }, common.expectsError({ @@ -312,6 +356,11 @@ const regularFile = __filename; permission: 'FileSystemRead', resource: path.toNamespacedPath(blockedFile), })); + fs.rename(bufferBlockedFile, 'newfile', common.expectsError({ + code: 'ERR_ACCESS_DENIED', + permission: 'FileSystemRead', + resource: path.toNamespacedPath(blockedFile), + })); assert.throws(() => { fs.renameSync(blockedFile, 'newfile'); }, common.expectsError({ @@ -337,6 +386,13 @@ const regularFile = __filename; permission: 'FileSystemRead', resource: path.toNamespacedPath(blockedFile), })); + assert.throws(() => { + fs.openAsBlob(bufferBlockedFile); + }, common.expectsError({ + code: 'ERR_ACCESS_DENIED', + permission: 'FileSystemRead', + resource: path.toNamespacedPath(blockedFile), + })); assert.throws(() => { fs.openAsBlob(blockedFileURL); }, common.expectsError({ @@ -371,6 +427,11 @@ const regularFile = __filename; permission: 'FileSystemRead', resource: path.toNamespacedPath(blockedFile), })); + fs.statfs(bufferBlockedFile, common.expectsError({ + code: 'ERR_ACCESS_DENIED', + permission: 'FileSystemRead', + resource: path.toNamespacedPath(blockedFile), + })); assert.throws(() => { fs.statfsSync(blockedFile); }, common.expectsError({ @@ -396,4 +457,33 @@ const regularFile = __filename; permission: 'FileSystemRead', resource: blockedFolder, })); +} + +// fs.lstat +{ + assert.throws(() => { + fs.lstatSync(blockedFile); + }, common.expectsError({ + code: 'ERR_ACCESS_DENIED', + })); + assert.throws(() => { + fs.lstatSync(bufferBlockedFile); + }, common.expectsError({ + code: 'ERR_ACCESS_DENIED', + })); + assert.throws(() => { + fs.lstatSync(path.join(blockedFolder, 'anyfile')); + }, common.expectsError({ + code: 'ERR_ACCESS_DENIED', + })); + assert.throws(() => { + fs.lstatSync(bufferBlockedFile); + }, common.expectsError({ + code: 'ERR_ACCESS_DENIED', + })); + + // doesNotThrow + fs.lstat(regularFile, (err) => { + assert.ifError(err); + }); } \ No newline at end of file diff --git a/test/js/node/test/fixtures/permission/fs-traversal.js b/test/js/node/test/fixtures/permission/fs-traversal.js index b568ede5b8..764ae66925 100644 --- a/test/js/node/test/fixtures/permission/fs-traversal.js +++ b/test/js/node/test/fixtures/permission/fs-traversal.js @@ -65,7 +65,17 @@ const uint8ArrayTraversalPath = new TextEncoder().encode(traversalPath); fs.readFile(bufferTraversalPath, common.expectsError({ code: 'ERR_ACCESS_DENIED', permission: 'FileSystemRead', - resource: traversalPath, + resource: path.toNamespacedPath(traversalPath), + })); +} + +{ + fs.lstat(bufferTraversalPath, common.expectsError({ + code: 'ERR_ACCESS_DENIED', + permission: 'FileSystemRead', + // lstat checks and throw on JS side. + // resource is only resolved on C++ (is_granted) + resource: bufferTraversalPath.toString(), })); } @@ -73,27 +83,7 @@ const uint8ArrayTraversalPath = new TextEncoder().encode(traversalPath); fs.readFile(uint8ArrayTraversalPath, common.expectsError({ code: 'ERR_ACCESS_DENIED', permission: 'FileSystemRead', - resource: traversalPath, - })); -} - -// Monkey-patching path module should also not allow path traversal. -{ - const fs = require('fs'); - const path = require('path'); - - const cwd = Buffer.from('.'); - try { - path.toNamespacedPath = (path) => { return traversalPath; }; - assert.fail('should throw error when pacthing'); - } catch { } - - assert.throws(() => { - fs.readFileSync(cwd); - }, common.expectsError({ - code: 'ERR_ACCESS_DENIED', - permission: 'FileSystemRead', - resource: cwd.toString(), + resource: path.toNamespacedPath(traversalPath), })); } @@ -118,7 +108,7 @@ const uint8ArrayTraversalPath = new TextEncoder().encode(traversalPath); }, common.expectsError({ code: 'ERR_ACCESS_DENIED', permission: 'FileSystemRead', - resource: traversalPathWithExtraChars, + resource: path.toNamespacedPath(traversalPathWithExtraChars), })); assert.throws(() => { @@ -126,7 +116,7 @@ const uint8ArrayTraversalPath = new TextEncoder().encode(traversalPath); }, common.expectsError({ code: 'ERR_ACCESS_DENIED', permission: 'FileSystemRead', - resource: traversalPathWithExtraChars, + resource: path.toNamespacedPath(traversalPathWithExtraChars), })); } diff --git a/test/js/node/test/fixtures/permission/fs-write.js b/test/js/node/test/fixtures/permission/fs-write.js index a1f26df2c8..0c0ec72602 100644 --- a/test/js/node/test/fixtures/permission/fs-write.js +++ b/test/js/node/test/fixtures/permission/fs-write.js @@ -11,6 +11,7 @@ const regularFolder = process.env.ALLOWEDFOLDER; const regularFile = process.env.ALLOWEDFILE; const blockedFolder = process.env.BLOCKEDFOLDER; const blockedFile = process.env.BLOCKEDFILE; +const bufferBlockedFile = Buffer.from(process.env.BLOCKEDFILE); const blockedFileURL = require('url').pathToFileURL(process.env.BLOCKEDFILE); const relativeProtectedFile = process.env.RELATIVEBLOCKEDFILE; const relativeProtectedFolder = process.env.RELATIVEBLOCKEDFOLDER; @@ -34,6 +35,11 @@ const relativeProtectedFolder = process.env.RELATIVEBLOCKEDFOLDER; permission: 'FileSystemWrite', resource: path.toNamespacedPath(blockedFile), })); + fs.writeFile(bufferBlockedFile, 'example', common.expectsError({ + code: 'ERR_ACCESS_DENIED', + permission: 'FileSystemWrite', + resource: path.toNamespacedPath(blockedFile), + })); assert.throws(() => { fs.writeFileSync(blockedFileURL, 'example'); }, { @@ -102,6 +108,13 @@ const relativeProtectedFolder = process.env.RELATIVEBLOCKEDFOLDER; permission: 'FileSystemWrite', resource: path.toNamespacedPath(blockedFile), }); + assert.throws(() => { + fs.utimes(bufferBlockedFile, new Date(), new Date(), () => {}); + }, { + code: 'ERR_ACCESS_DENIED', + permission: 'FileSystemWrite', + resource: path.toNamespacedPath(blockedFile), + }); assert.throws(() => { fs.utimes(blockedFileURL, new Date(), new Date(), () => {}); }, { @@ -135,6 +148,13 @@ const relativeProtectedFolder = process.env.RELATIVEBLOCKEDFOLDER; permission: 'FileSystemWrite', resource: path.toNamespacedPath(blockedFile), }); + assert.throws(() => { + fs.lutimes(bufferBlockedFile, new Date(), new Date(), () => {}); + },{ + code: 'ERR_ACCESS_DENIED', + permission: 'FileSystemWrite', + resource: path.toNamespacedPath(blockedFile), + }); assert.throws(() => { fs.lutimes(blockedFileURL, new Date(), new Date(), () => {}); }, { @@ -193,6 +213,11 @@ const relativeProtectedFolder = process.env.RELATIVEBLOCKEDFOLDER; permission: 'FileSystemWrite', resource: path.toNamespacedPath(blockedFile), })); + fs.rename(bufferBlockedFile, path.join(blockedFile, 'renamed'), common.expectsError({ + code: 'ERR_ACCESS_DENIED', + permission: 'FileSystemWrite', + resource: path.toNamespacedPath(blockedFile), + })); assert.throws(() => { fs.renameSync(blockedFileURL, path.join(blockedFile, 'renamed')); }, { @@ -245,6 +270,11 @@ const relativeProtectedFolder = process.env.RELATIVEBLOCKEDFOLDER; permission: 'FileSystemWrite', resource: path.toNamespacedPath(path.join(relativeProtectedFolder, 'any-file')), })); + fs.copyFile(bufferBlockedFile, path.join(relativeProtectedFolder, 'any-file'), common.expectsError({ + code: 'ERR_ACCESS_DENIED', + permission: 'FileSystemWrite', + resource: path.toNamespacedPath(path.join(relativeProtectedFolder, 'any-file')), + })); } // fs.cp @@ -295,6 +325,10 @@ const relativeProtectedFolder = process.env.RELATIVEBLOCKEDFOLDER; code: 'ERR_ACCESS_DENIED', permission: 'FileSystemWrite', })); + fs.open(bufferBlockedFile, fs.constants.O_RDWR | 0x10000000, common.expectsError({ + code: 'ERR_ACCESS_DENIED', + permission: 'FileSystemWrite', + })); assert.rejects(async () => { await fs.promises.open(blockedFile, fs.constants.O_RDWR | fs.constants.O_NOFOLLOW); }, { @@ -322,6 +356,12 @@ const relativeProtectedFolder = process.env.RELATIVEBLOCKEDFOLDER; code: 'ERR_ACCESS_DENIED', permission: 'FileSystemWrite', }); + assert.throws(() => { + fs.chmod(bufferBlockedFile, 0o755, common.mustNotCall()); + }, { + code: 'ERR_ACCESS_DENIED', + permission: 'FileSystemWrite', + }); assert.throws(() => { fs.chmod(blockedFileURL, 0o755, common.mustNotCall()); }, { @@ -338,7 +378,7 @@ const relativeProtectedFolder = process.env.RELATIVEBLOCKEDFOLDER; // fs.lchmod { - if (common.isOSX) { + if (common.isMacOS) { fs.lchmod(blockedFile, 0o755, common.expectsError({ code: 'ERR_ACCESS_DENIED', permission: 'FileSystemWrite', @@ -358,6 +398,10 @@ const relativeProtectedFolder = process.env.RELATIVEBLOCKEDFOLDER; code: 'ERR_ACCESS_DENIED', permission: 'FileSystemWrite', })); + fs.appendFile(bufferBlockedFile, 'new data', common.expectsError({ + code: 'ERR_ACCESS_DENIED', + permission: 'FileSystemWrite', + })); assert.throws(() => { fs.appendFileSync(blockedFileURL, 'new data'); }, { @@ -378,6 +422,10 @@ const relativeProtectedFolder = process.env.RELATIVEBLOCKEDFOLDER; code: 'ERR_ACCESS_DENIED', permission: 'FileSystemWrite', })); + fs.chown(bufferBlockedFile, 1541, 999, common.expectsError({ + code: 'ERR_ACCESS_DENIED', + permission: 'FileSystemWrite', + })); assert.throws(() => { fs.chownSync(blockedFileURL, 1541, 999); }, { @@ -399,6 +447,10 @@ const relativeProtectedFolder = process.env.RELATIVEBLOCKEDFOLDER; code: 'ERR_ACCESS_DENIED', permission: 'FileSystemWrite', })); + fs.lchown(bufferBlockedFile, 1541, 999, common.expectsError({ + code: 'ERR_ACCESS_DENIED', + permission: 'FileSystemWrite', + })); assert.throws(() => { fs.lchownSync(blockedFileURL, 1541, 999); }, { @@ -426,6 +478,10 @@ const relativeProtectedFolder = process.env.RELATIVEBLOCKEDFOLDER; code: 'ERR_ACCESS_DENIED', permission: 'FileSystemWrite', })); + fs.link(bufferBlockedFile, path.join(blockedFolder, '/linked'), common.expectsError({ + code: 'ERR_ACCESS_DENIED', + permission: 'FileSystemWrite', + })); assert.throws(() => { fs.linkSync(blockedFileURL, path.join(blockedFolder, '/linked')); }, { @@ -450,6 +506,13 @@ const relativeProtectedFolder = process.env.RELATIVEBLOCKEDFOLDER; permission: 'FileSystemWrite', resource: path.toNamespacedPath(blockedFile), }); + assert.throws(() => { + fs.unlinkSync(bufferBlockedFile); + }, { + code: 'ERR_ACCESS_DENIED', + permission: 'FileSystemWrite', + resource: path.toNamespacedPath(blockedFile), + }); fs.unlink(blockedFile, common.expectsError({ code: 'ERR_ACCESS_DENIED', permission: 'FileSystemWrite', @@ -462,4 +525,32 @@ const relativeProtectedFolder = process.env.RELATIVEBLOCKEDFOLDER; permission: 'FileSystemWrite', resource: path.toNamespacedPath(blockedFile), }); +} + +// fs.fchown with read-only fd +{ + assert.throws(() => { + // blocked file is allowed to read + const fd = fs.openSync(blockedFile, 'r'); + fs.fchmod(fd, 777, common.expectsError({ + code: 'ERR_ACCESS_DENIED', + })); + fs.fchmodSync(fd, 777); + }, { + code: 'ERR_ACCESS_DENIED', + }); +} + +// fs.fchmod with read-only fd +{ + assert.throws(() => { + // blocked file is allowed to read + const fd = fs.openSync(blockedFile, 'r'); + fs.fchown(fd, 999, 999, common.expectsError({ + code: 'ERR_ACCESS_DENIED', + })); + fs.fchownSync(fd, 999, 999); + }, { + code: 'ERR_ACCESS_DENIED', + }); } \ No newline at end of file diff --git a/test/js/node/test/fixtures/permission/main-module.js b/test/js/node/test/fixtures/permission/main-module.js new file mode 100644 index 0000000000..caf3c61b38 --- /dev/null +++ b/test/js/node/test/fixtures/permission/main-module.js @@ -0,0 +1 @@ +require('./required-module'); diff --git a/test/js/node/test/fixtures/permission/main-module.mjs b/test/js/node/test/fixtures/permission/main-module.mjs new file mode 100644 index 0000000000..c43f24efab --- /dev/null +++ b/test/js/node/test/fixtures/permission/main-module.mjs @@ -0,0 +1 @@ +import './required-module.mjs'; diff --git a/test/js/node/test/fixtures/permission/required-module.js b/test/js/node/test/fixtures/permission/required-module.js new file mode 100644 index 0000000000..37108886b5 --- /dev/null +++ b/test/js/node/test/fixtures/permission/required-module.js @@ -0,0 +1 @@ +console.log('ok'); diff --git a/test/js/node/test/fixtures/permission/required-module.mjs b/test/js/node/test/fixtures/permission/required-module.mjs new file mode 100644 index 0000000000..37108886b5 --- /dev/null +++ b/test/js/node/test/fixtures/permission/required-module.mjs @@ -0,0 +1 @@ +console.log('ok'); diff --git a/test/js/node/test/fixtures/pkgexports.mjs b/test/js/node/test/fixtures/pkgexports.mjs index 7d642c443e..b71566b95c 100644 --- a/test/js/node/test/fixtures/pkgexports.mjs +++ b/test/js/node/test/fixtures/pkgexports.mjs @@ -3,6 +3,10 @@ import { createRequire } from 'module'; const rawRequire = createRequire(fileURLToPath(import.meta.url)); +export function directRequireFixture(specifier) { + return rawRequire(specifier); +} + export async function requireFixture(specifier) { return { default: rawRequire(specifier ) }; } diff --git a/test/js/node/test/fixtures/postject-copy/node_modules/.package-lock.json b/test/js/node/test/fixtures/postject-copy/node_modules/.package-lock.json new file mode 100644 index 0000000000..2d4e6adbff --- /dev/null +++ b/test/js/node/test/fixtures/postject-copy/node_modules/.package-lock.json @@ -0,0 +1,30 @@ +{ + "name": "postject-copy", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/postject": { + "version": "1.0.0-alpha.6", + "resolved": "https://registry.npmjs.org/postject/-/postject-1.0.0-alpha.6.tgz", + "integrity": "sha512-b9Eb8h2eVqNE8edvKdwqkrY6O7kAwmI8kcnBv1NScolYJbo59XUF0noFq+lxbC1yN20bmC0WBEbDC5H/7ASb0A==", + "dependencies": { + "commander": "^9.4.0" + }, + "bin": { + "postject": "dist/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + } + } +} diff --git a/test/js/node/test/fixtures/postject-copy/node_modules/commander/LICENSE b/test/js/node/test/fixtures/postject-copy/node_modules/commander/LICENSE new file mode 100644 index 0000000000..10f997ab10 --- /dev/null +++ b/test/js/node/test/fixtures/postject-copy/node_modules/commander/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2011 TJ Holowaychuk + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/test/js/node/test/fixtures/postject-copy/node_modules/commander/Readme.md b/test/js/node/test/fixtures/postject-copy/node_modules/commander/Readme.md new file mode 100644 index 0000000000..ed19cff633 --- /dev/null +++ b/test/js/node/test/fixtures/postject-copy/node_modules/commander/Readme.md @@ -0,0 +1,1129 @@ +# Commander.js + +[![Build Status](https://github.com/tj/commander.js/workflows/build/badge.svg)](https://github.com/tj/commander.js/actions?query=workflow%3A%22build%22) +[![NPM Version](http://img.shields.io/npm/v/commander.svg?style=flat)](https://www.npmjs.org/package/commander) +[![NPM Downloads](https://img.shields.io/npm/dm/commander.svg?style=flat)](https://npmcharts.com/compare/commander?minimal=true) +[![Install Size](https://packagephobia.now.sh/badge?p=commander)](https://packagephobia.now.sh/result?p=commander) + +The complete solution for [node.js](http://nodejs.org) command-line interfaces. + +Read this in other languages: English | [简体中文](./Readme_zh-CN.md) + +- [Commander.js](#commanderjs) + - [Installation](#installation) + - [Quick Start](#quick-start) + - [Declaring _program_ variable](#declaring-program-variable) + - [Options](#options) + - [Common option types, boolean and value](#common-option-types-boolean-and-value) + - [Default option value](#default-option-value) + - [Other option types, negatable boolean and boolean|value](#other-option-types-negatable-boolean-and-booleanvalue) + - [Required option](#required-option) + - [Variadic option](#variadic-option) + - [Version option](#version-option) + - [More configuration](#more-configuration) + - [Custom option processing](#custom-option-processing) + - [Commands](#commands) + - [Command-arguments](#command-arguments) + - [More configuration](#more-configuration-1) + - [Custom argument processing](#custom-argument-processing) + - [Action handler](#action-handler) + - [Stand-alone executable (sub)commands](#stand-alone-executable-subcommands) + - [Life cycle hooks](#life-cycle-hooks) + - [Automated help](#automated-help) + - [Custom help](#custom-help) + - [Display help after errors](#display-help-after-errors) + - [Display help from code](#display-help-from-code) + - [.name](#name) + - [.usage](#usage) + - [.description and .summary](#description-and-summary) + - [.helpOption(flags, description)](#helpoptionflags-description) + - [.addHelpCommand()](#addhelpcommand) + - [More configuration](#more-configuration-2) + - [Custom event listeners](#custom-event-listeners) + - [Bits and pieces](#bits-and-pieces) + - [.parse() and .parseAsync()](#parse-and-parseasync) + - [Parsing Configuration](#parsing-configuration) + - [Legacy options as properties](#legacy-options-as-properties) + - [TypeScript](#typescript) + - [createCommand()](#createcommand) + - [Node options such as `--harmony`](#node-options-such-as---harmony) + - [Debugging stand-alone executable subcommands](#debugging-stand-alone-executable-subcommands) + - [Display error](#display-error) + - [Override exit and output handling](#override-exit-and-output-handling) + - [Additional documentation](#additional-documentation) + - [Support](#support) + - [Commander for enterprise](#commander-for-enterprise) + +For information about terms used in this document see: [terminology](./docs/terminology.md) + +## Installation + +```sh +npm install commander +``` + +## Quick Start + +You write code to describe your command line interface. +Commander looks after parsing the arguments into options and command-arguments, +displays usage errors for problems, and implements a help system. + +Commander is strict and displays an error for unrecognised options. +The two most used option types are a boolean option, and an option which takes its value from the following argument. + +Example file: [split.js](./examples/split.js) + +```js +const { program } = require('commander'); + +program + .option('--first') + .option('-s, --separator '); + +program.parse(); + +const options = program.opts(); +const limit = options.first ? 1 : undefined; +console.log(program.args[0].split(options.separator, limit)); +``` + +```console +$ node split.js -s / --fits a/b/c +error: unknown option '--fits' +(Did you mean --first?) +$ node split.js -s / --first a/b/c +[ 'a' ] +``` + +Here is a more complete program using a subcommand and with descriptions for the help. In a multi-command program, you have an action handler for each command (or stand-alone executables for the commands). + +Example file: [string-util.js](./examples/string-util.js) + +```js +const { Command } = require('commander'); +const program = new Command(); + +program + .name('string-util') + .description('CLI to some JavaScript string utilities') + .version('0.8.0'); + +program.command('split') + .description('Split a string into substrings and display as an array') + .argument('', 'string to split') + .option('--first', 'display just the first substring') + .option('-s, --separator ', 'separator character', ',') + .action((str, options) => { + const limit = options.first ? 1 : undefined; + console.log(str.split(options.separator, limit)); + }); + +program.parse(); +``` + +```console +$ node string-util.js help split +Usage: string-util split [options] + +Split a string into substrings and display as an array. + +Arguments: + string string to split + +Options: + --first display just the first substring + -s, --separator separator character (default: ",") + -h, --help display help for command + +$ node string-util.js split --separator=/ a/b/c +[ 'a', 'b', 'c' ] +``` + +More samples can be found in the [examples](https://github.com/tj/commander.js/tree/master/examples) directory. + +## Declaring _program_ variable + +Commander exports a global object which is convenient for quick programs. +This is used in the examples in this README for brevity. + +```js +// CommonJS (.cjs) +const { program } = require('commander'); +``` + +For larger programs which may use commander in multiple ways, including unit testing, it is better to create a local Command object to use. + +```js +// CommonJS (.cjs) +const { Command } = require('commander'); +const program = new Command(); +``` + +```js +// ECMAScript (.mjs) +import { Command } from 'commander'; +const program = new Command(); +``` + +```ts +// TypeScript (.ts) +import { Command } from 'commander'; +const program = new Command(); +``` + +## Options + +Options are defined with the `.option()` method, also serving as documentation for the options. Each option can have a short flag (single character) and a long name, separated by a comma or space or vertical bar ('|'). + +The parsed options can be accessed by calling `.opts()` on a `Command` object, and are passed to the action handler. + +Multi-word options such as "--template-engine" are camel-cased, becoming `program.opts().templateEngine` etc. + +An option and its option-argument can be separated by a space, or combined into the same argument. The option-argument can follow the short option directly or follow an `=` for a long option. + +```sh +serve -p 80 +serve -p80 +serve --port 80 +serve --port=80 +``` + +You can use `--` to indicate the end of the options, and any remaining arguments will be used without being interpreted. + +By default options on the command line are not positional, and can be specified before or after other arguments. + +There are additional related routines for when `.opts()` is not enough: + +- `.optsWithGlobals()` returns merged local and global option values +- `.getOptionValue()` and `.setOptionValue()` work with a single option value +- `.getOptionValueSource()` and `.setOptionValueWithSource()` include where the option value came from + +### Common option types, boolean and value + +The two most used option types are a boolean option, and an option which takes its value +from the following argument (declared with angle brackets like `--expect `). Both are `undefined` unless specified on command line. + +Example file: [options-common.js](./examples/options-common.js) + +```js +program + .option('-d, --debug', 'output extra debugging') + .option('-s, --small', 'small pizza size') + .option('-p, --pizza-type ', 'flavour of pizza'); + +program.parse(process.argv); + +const options = program.opts(); +if (options.debug) console.log(options); +console.log('pizza details:'); +if (options.small) console.log('- small pizza size'); +if (options.pizzaType) console.log(`- ${options.pizzaType}`); +``` + +```console +$ pizza-options -p +error: option '-p, --pizza-type ' argument missing +$ pizza-options -d -s -p vegetarian +{ debug: true, small: true, pizzaType: 'vegetarian' } +pizza details: +- small pizza size +- vegetarian +$ pizza-options --pizza-type=cheese +pizza details: +- cheese +``` + +Multiple boolean short options may be combined together following the dash, and may be followed by a single short option taking a value. +For example `-d -s -p cheese` may be written as `-ds -p cheese` or even `-dsp cheese`. + +Options with an expected option-argument are greedy and will consume the following argument whatever the value. +So `--id -xyz` reads `-xyz` as the option-argument. + +`program.parse(arguments)` processes the arguments, leaving any args not consumed by the program options in the `program.args` array. The parameter is optional and defaults to `process.argv`. + +### Default option value + +You can specify a default value for an option. + +Example file: [options-defaults.js](./examples/options-defaults.js) + +```js +program + .option('-c, --cheese ', 'add the specified type of cheese', 'blue'); + +program.parse(); + +console.log(`cheese: ${program.opts().cheese}`); +``` + +```console +$ pizza-options +cheese: blue +$ pizza-options --cheese stilton +cheese: stilton +``` + +### Other option types, negatable boolean and boolean|value + +You can define a boolean option long name with a leading `no-` to set the option value to false when used. +Defined alone this also makes the option true by default. + +If you define `--foo` first, adding `--no-foo` does not change the default value from what it would +otherwise be. + +Example file: [options-negatable.js](./examples/options-negatable.js) + +```js +program + .option('--no-sauce', 'Remove sauce') + .option('--cheese ', 'cheese flavour', 'mozzarella') + .option('--no-cheese', 'plain with no cheese') + .parse(); + +const options = program.opts(); +const sauceStr = options.sauce ? 'sauce' : 'no sauce'; +const cheeseStr = (options.cheese === false) ? 'no cheese' : `${options.cheese} cheese`; +console.log(`You ordered a pizza with ${sauceStr} and ${cheeseStr}`); +``` + +```console +$ pizza-options +You ordered a pizza with sauce and mozzarella cheese +$ pizza-options --sauce +error: unknown option '--sauce' +$ pizza-options --cheese=blue +You ordered a pizza with sauce and blue cheese +$ pizza-options --no-sauce --no-cheese +You ordered a pizza with no sauce and no cheese +``` + +You can specify an option which may be used as a boolean option but may optionally take an option-argument +(declared with square brackets like `--optional [value]`). + +Example file: [options-boolean-or-value.js](./examples/options-boolean-or-value.js) + +```js +program + .option('-c, --cheese [type]', 'Add cheese with optional type'); + +program.parse(process.argv); + +const options = program.opts(); +if (options.cheese === undefined) console.log('no cheese'); +else if (options.cheese === true) console.log('add cheese'); +else console.log(`add cheese type ${options.cheese}`); +``` + +```console +$ pizza-options +no cheese +$ pizza-options --cheese +add cheese +$ pizza-options --cheese mozzarella +add cheese type mozzarella +``` + +Options with an optional option-argument are not greedy and will ignore arguments starting with a dash. +So `id` behaves as a boolean option for `--id -5`, but you can use a combined form if needed like `--id=-5`. + +For information about possible ambiguous cases, see [options taking varying arguments](./docs/options-taking-varying-arguments.md). + +### Required option + +You may specify a required (mandatory) option using `.requiredOption()`. The option must have a value after parsing, usually specified on the command line, or perhaps from a default value (say from environment). The method is otherwise the same as `.option()` in format, taking flags and description, and optional default value or custom processing. + +Example file: [options-required.js](./examples/options-required.js) + +```js +program + .requiredOption('-c, --cheese ', 'pizza must have cheese'); + +program.parse(); +``` + +```console +$ pizza +error: required option '-c, --cheese ' not specified +``` + +### Variadic option + +You may make an option variadic by appending `...` to the value placeholder when declaring the option. On the command line you +can then specify multiple option-arguments, and the parsed option value will be an array. The extra arguments +are read until the first argument starting with a dash. The special argument `--` stops option processing entirely. If a value +is specified in the same argument as the option then no further values are read. + +Example file: [options-variadic.js](./examples/options-variadic.js) + +```js +program + .option('-n, --number ', 'specify numbers') + .option('-l, --letter [letters...]', 'specify letters'); + +program.parse(); + +console.log('Options: ', program.opts()); +console.log('Remaining arguments: ', program.args); +``` + +```console +$ collect -n 1 2 3 --letter a b c +Options: { number: [ '1', '2', '3' ], letter: [ 'a', 'b', 'c' ] } +Remaining arguments: [] +$ collect --letter=A -n80 operand +Options: { number: [ '80' ], letter: [ 'A' ] } +Remaining arguments: [ 'operand' ] +$ collect --letter -n 1 -n 2 3 -- operand +Options: { number: [ '1', '2', '3' ], letter: true } +Remaining arguments: [ 'operand' ] +``` + +For information about possible ambiguous cases, see [options taking varying arguments](./docs/options-taking-varying-arguments.md). + +### Version option + +The optional `version` method adds handling for displaying the command version. The default option flags are `-V` and `--version`, and when present the command prints the version number and exits. + +```js +program.version('0.0.1'); +``` + +```console +$ ./examples/pizza -V +0.0.1 +``` + +You may change the flags and description by passing additional parameters to the `version` method, using +the same syntax for flags as the `option` method. + +```js +program.version('0.0.1', '-v, --vers', 'output the current version'); +``` + +### More configuration + +You can add most options using the `.option()` method, but there are some additional features available +by constructing an `Option` explicitly for less common cases. + +Example files: [options-extra.js](./examples/options-extra.js), [options-env.js](./examples/options-env.js), [options-conflicts.js](./examples/options-conflicts.js), [options-implies.js](./examples/options-implies.js) + +```js +program + .addOption(new Option('-s, --secret').hideHelp()) + .addOption(new Option('-t, --timeout ', 'timeout in seconds').default(60, 'one minute')) + .addOption(new Option('-d, --drink ', 'drink size').choices(['small', 'medium', 'large'])) + .addOption(new Option('-p, --port ', 'port number').env('PORT')) + .addOption(new Option('--donate [amount]', 'optional donation in dollars').preset('20').argParser(parseFloat)) + .addOption(new Option('--disable-server', 'disables the server').conflicts('port')) + .addOption(new Option('--free-drink', 'small drink included free ').implies({ drink: 'small' })); +``` + +```console +$ extra --help +Usage: help [options] + +Options: + -t, --timeout timeout in seconds (default: one minute) + -d, --drink drink cup size (choices: "small", "medium", "large") + -p, --port port number (env: PORT) + --donate [amount] optional donation in dollars (preset: "20") + --disable-server disables the server + --free-drink small drink included free + -h, --help display help for command + +$ extra --drink huge +error: option '-d, --drink ' argument 'huge' is invalid. Allowed choices are small, medium, large. + +$ PORT=80 extra --donate --free-drink +Options: { timeout: 60, donate: 20, port: '80', freeDrink: true, drink: 'small' } + +$ extra --disable-server --port 8000 +error: option '--disable-server' cannot be used with option '-p, --port ' +``` + +Specify a required (mandatory) option using the `Option` method `.makeOptionMandatory()`. This matches the `Command` method [.requiredOption()](#required-option). + +### Custom option processing + +You may specify a function to do custom processing of option-arguments. The callback function receives two parameters, +the user specified option-argument and the previous value for the option. It returns the new value for the option. + +This allows you to coerce the option-argument to the desired type, or accumulate values, or do entirely custom processing. + +You can optionally specify the default/starting value for the option after the function parameter. + +Example file: [options-custom-processing.js](./examples/options-custom-processing.js) + +```js +function myParseInt(value, dummyPrevious) { + // parseInt takes a string and a radix + const parsedValue = parseInt(value, 10); + if (isNaN(parsedValue)) { + throw new commander.InvalidArgumentError('Not a number.'); + } + return parsedValue; +} + +function increaseVerbosity(dummyValue, previous) { + return previous + 1; +} + +function collect(value, previous) { + return previous.concat([value]); +} + +function commaSeparatedList(value, dummyPrevious) { + return value.split(','); +} + +program + .option('-f, --float ', 'float argument', parseFloat) + .option('-i, --integer ', 'integer argument', myParseInt) + .option('-v, --verbose', 'verbosity that can be increased', increaseVerbosity, 0) + .option('-c, --collect ', 'repeatable value', collect, []) + .option('-l, --list ', 'comma separated list', commaSeparatedList) +; + +program.parse(); + +const options = program.opts(); +if (options.float !== undefined) console.log(`float: ${options.float}`); +if (options.integer !== undefined) console.log(`integer: ${options.integer}`); +if (options.verbose > 0) console.log(`verbosity: ${options.verbose}`); +if (options.collect.length > 0) console.log(options.collect); +if (options.list !== undefined) console.log(options.list); +``` + +```console +$ custom -f 1e2 +float: 100 +$ custom --integer 2 +integer: 2 +$ custom -v -v -v +verbose: 3 +$ custom -c a -c b -c c +[ 'a', 'b', 'c' ] +$ custom --list x,y,z +[ 'x', 'y', 'z' ] +``` + +## Commands + +You can specify (sub)commands using `.command()` or `.addCommand()`. There are two ways these can be implemented: using an action handler attached to the command, or as a stand-alone executable file (described in more detail later). The subcommands may be nested ([example](./examples/nestedCommands.js)). + +In the first parameter to `.command()` you specify the command name. You may append the command-arguments after the command name, or specify them separately using `.argument()`. The arguments may be `` or `[optional]`, and the last argument may also be `variadic...`. + +You can use `.addCommand()` to add an already configured subcommand to the program. + +For example: + +```js +// Command implemented using action handler (description is supplied separately to `.command`) +// Returns new command for configuring. +program + .command('clone [destination]') + .description('clone a repository into a newly created directory') + .action((source, destination) => { + console.log('clone command called'); + }); + +// Command implemented using stand-alone executable file, indicated by adding description as second parameter to `.command`. +// Returns `this` for adding more commands. +program + .command('start ', 'start named service') + .command('stop [service]', 'stop named service, or all if no name supplied'); + +// Command prepared separately. +// Returns `this` for adding more commands. +program + .addCommand(build.makeBuildCommand()); +``` + +Configuration options can be passed with the call to `.command()` and `.addCommand()`. Specifying `hidden: true` will +remove the command from the generated help output. Specifying `isDefault: true` will run the subcommand if no other +subcommand is specified ([example](./examples/defaultCommand.js)). + +You can add alternative names for a command with `.alias()`. ([example](./examples/alias.js)) + +For safety, `.addCommand()` does not automatically copy the inherited settings from the parent command. There is a helper routine `.copyInheritedSettings()` for copying the settings when they are wanted. + +### Command-arguments + +For subcommands, you can specify the argument syntax in the call to `.command()` (as shown above). This +is the only method usable for subcommands implemented using a stand-alone executable, but for other subcommands +you can instead use the following method. + +To configure a command, you can use `.argument()` to specify each expected command-argument. +You supply the argument name and an optional description. The argument may be `` or `[optional]`. +You can specify a default value for an optional command-argument. + +Example file: [argument.js](./examples/argument.js) + +```js +program + .version('0.1.0') + .argument('', 'user to login') + .argument('[password]', 'password for user, if required', 'no password given') + .action((username, password) => { + console.log('username:', username); + console.log('password:', password); + }); +``` + + The last argument of a command can be variadic, and only the last argument. To make an argument variadic you + append `...` to the argument name. A variadic argument is passed to the action handler as an array. For example: + +```js +program + .version('0.1.0') + .command('rmdir') + .argument('') + .action(function (dirs) { + dirs.forEach((dir) => { + console.log('rmdir %s', dir); + }); + }); +``` + +There is a convenience method to add multiple arguments at once, but without descriptions: + +```js +program + .arguments(' '); +``` + +#### More configuration + +There are some additional features available by constructing an `Argument` explicitly for less common cases. + +Example file: [arguments-extra.js](./examples/arguments-extra.js) + +```js +program + .addArgument(new commander.Argument('', 'drink cup size').choices(['small', 'medium', 'large'])) + .addArgument(new commander.Argument('[timeout]', 'timeout in seconds').default(60, 'one minute')) +``` + +#### Custom argument processing + +You may specify a function to do custom processing of command-arguments (like for option-arguments). +The callback function receives two parameters, the user specified command-argument and the previous value for the argument. +It returns the new value for the argument. + +The processed argument values are passed to the action handler, and saved as `.processedArgs`. + +You can optionally specify the default/starting value for the argument after the function parameter. + +Example file: [arguments-custom-processing.js](./examples/arguments-custom-processing.js) + +```js +program + .command('add') + .argument('', 'integer argument', myParseInt) + .argument('[second]', 'integer argument', myParseInt, 1000) + .action((first, second) => { + console.log(`${first} + ${second} = ${first + second}`); + }) +; +``` + +### Action handler + +The action handler gets passed a parameter for each command-argument you declared, and two additional parameters +which are the parsed options and the command object itself. + +Example file: [thank.js](./examples/thank.js) + +```js +program + .argument('') + .option('-t, --title ', 'title to use before name') + .option('-d, --debug', 'display some debugging') + .action((name, options, command) => { + if (options.debug) { + console.error('Called %s with options %o', command.name(), options); + } + const title = options.title ? `${options.title} ` : ''; + console.log(`Thank-you ${title}${name}`); + }); +``` + +If you prefer, you can work with the command directly and skip declaring the parameters for the action handler. The `this` keyword is set to the running command and can be used from a function expression (but not from an arrow function). + +Example file: [action-this.js](./examples/action-this.js) + +```js +program + .command('serve') + .argument(' +++ +++ +++ +++

Ensure a source map loads for resources with sourceMappingURLs.

+++ +++ ++-- ++2.39.2 ++ +diff --git a/LayoutTests/imported/tg4/source-map-tests/webkit/source-map-spec.html b/LayoutTests/imported/tg4/source-map-tests/webkit/source-map-spec.html +new file mode 100644 +index 000000000000..b30b1dd526fc +--- /dev/null ++++ b/LayoutTests/imported/tg4/source-map-tests/webkit/source-map-spec.html +@@ -0,0 +1,83 @@ ++ ++ ++ ++ ++ ++ ++ ++

Ensure a source map loads for resources with sourceMappingURLs.

++ ++ +diff --git a/LayoutTests/inspector/model/source-map-spec-expected.txt b/LayoutTests/inspector/model/source-map-spec-expected.txt +new file mode 100644 +index 000000000000..fd0094a8ac46 +--- /dev/null ++++ b/LayoutTests/inspector/model/source-map-spec-expected.txt +@@ -0,0 +1,828 @@ ++Run source map specification consumer test cases. ++ ++ ++== Running test suite: SourceMapSpec ++-- Running test case: SourceMapSpec ++versionValid ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++versionMissing ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++versionNotANumber ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++versionNumericString ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++versionTooHigh ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++versionTooLow ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++sourcesMissing ++PASS: Expected that there is an associated failed source map URL ++PASS: Expected no source map resource loaded ++sourcesNotAList1 ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++sourcesNotAList2 ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++sourcesNotStringOrNull ++PASS: Expected that there is an associated failed source map URL ++PASS: Expected no source map resource loaded ++sourcesAndSourcesContentBothNull ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++fileNotAString1 ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++fileNotAString2 ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++sourceRootNotAString1 ++PASS: Expected that there is an associated failed source map URL ++PASS: Expected no source map resource loaded ++sourceRootNotAString2 ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++PASS: Expected no source map resource loaded ++namesMissing ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++namesNotAList1 ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++namesNotAList2 ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++namesNotString ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++ignoreListEmpty ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++ignoreListValid1 ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++Ignore list test ignored (unsupported) ++ignoreListWrongType1 ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++ignoreListWrongType2 ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++ignoreListWrongType3 ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++ignoreListWrongType4 ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++PASS: Expected no source map resource loaded ++ignoreListOutOfBounds1 ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++ignoreListOutOfBounds2 ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++unrecognizedProperty ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++invalidVLQDueToNonBase64Character ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++invalidVLQDueToMissingContinuationDigits ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++invalidMappingNotAString1 ++PASS: Expected that there is an associated failed source map URL ++PASS: Expected no source map resource loaded ++invalidMappingNotAString2 ++PASS: Expected that there is an associated failed source map URL ++PASS: Expected no source map resource loaded ++invalidMappingSegmentBadSeparator ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++invalidMappingSegmentWithZeroFields ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++PASS: Expected no source map resource loaded ++invalidMappingSegmentWithTwoFields ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++PASS: Expected no source map resource loaded ++invalidMappingSegmentWithThreeFields ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++PASS: Expected no source map resource loaded ++invalidMappingSegmentWithSourceIndexOutOfBounds ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++invalidMappingSegmentWithNameIndexOutOfBounds ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++invalidMappingSegmentWithNegativeColumn ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++invalidMappingSegmentWithNegativeSourceIndex ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++invalidMappingSegmentWithNegativeOriginalLine ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++invalidMappingSegmentWithNegativeOriginalColumn ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++invalidMappingSegmentWithNegativeNameIndex ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++invalidMappingSegmentWithNegativeRelativeColumn ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++invalidMappingSegmentWithNegativeRelativeSourceIndex ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++invalidMappingSegmentWithNegativeRelativeOriginalLine ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++invalidMappingSegmentWithNegativeRelativeOriginalColumn ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++invalidMappingSegmentWithNegativeRelativeNameIndex ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++invalidMappingSegmentWithColumnExceeding32Bits ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++invalidMappingSegmentWithSourceIndexExceeding32Bits ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++invalidMappingSegmentWithOriginalLineExceeding32Bits ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++invalidMappingSegmentWithOriginalColumnExceeding32Bits ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++invalidMappingSegmentWithNameIndexExceeding32Bits ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++validMappingFieldsWith32BitMaxValues ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++validMappingLargeVLQ ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++validMappingEmptyGroups ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++validMappingEmptyString ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++indexMapWrongTypeSections ++PASS: Expected that there is an associated failed source map URL ++PASS: Expected no source map resource loaded ++indexMapWrongTypeOffset ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++indexMapWrongTypeMap ++PASS: Expected that there is an associated failed source map URL ++PASS: Expected no source map resource loaded ++indexMapInvalidBaseMappings ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++indexMapInvalidOverlap ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++indexMapInvalidOrder ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++indexMapMissingMap ++PASS: Expected that there is an associated failed source map URL ++PASS: Expected no source map resource loaded ++indexMapInvalidSubMap ++PASS: Expected that there is an associated failed source map URL ++PASS: Expected no source map resource loaded ++indexMapMissingOffset ++PASS: Expected that there is an associated failed source map URL ++PASS: Expected no source map resource loaded ++indexMapMissingOffsetLine ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++indexMapMissingOffsetColumn ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++indexMapOffsetLineWrongType ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++indexMapOffsetColumnWrongType ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++indexMapEmptySections ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++indexMapFileWrongType1 ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++indexMapFileWrongType2 ++FAIL: Expected that there is an associated failed source map URL ++ Expected: truthy ++ Actual: false ++FAIL: Expected no source map resource loaded ++ Expected: 0 ++ Actual: 1 ++basicMapping ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++PASS: Test location (0, 0) should be mapped ++PASS: Original line: 0, expected: 0 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 9) should be mapped ++PASS: Original line: 0, expected: 0 ++PASS: Original column: 9, expected: 9 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 15) should be mapped ++PASS: Original line: 1, expected: 1 ++PASS: Original column: 2, expected: 2 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 22) should be mapped ++PASS: Original line: 1, expected: 1 ++PASS: Original column: 9, expected: 9 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 24) should be mapped ++PASS: Original line: 2, expected: 2 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 25) should be mapped ++PASS: Original line: 3, expected: 3 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 34) should be mapped ++PASS: Original line: 3, expected: 3 ++PASS: Original column: 9, expected: 9 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 40) should be mapped ++PASS: Original line: 4, expected: 4 ++PASS: Original column: 2, expected: 2 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 47) should be mapped ++PASS: Original line: 4, expected: 4 ++PASS: Original column: 9, expected: 9 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 49) should be mapped ++PASS: Original line: 5, expected: 5 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 50) should be mapped ++PASS: Original line: 6, expected: 6 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 56) should be mapped ++PASS: Original line: 7, expected: 7 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++sourceRootResolution ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++PASS: Test location (0, 0) should be mapped ++PASS: Original line: 0, expected: 0 ++PASS: Original column: 0, expected: 0 ++FAIL: Original source: basic-mapping-original.js, expected: theroot/basic-mapping-original.js ++ Expected: "theroot/basic-mapping-original.js" ++ Actual: "basic-mapping-original.js" ++PASS: Test location (0, 9) should be mapped ++PASS: Original line: 0, expected: 0 ++PASS: Original column: 9, expected: 9 ++FAIL: Original source: basic-mapping-original.js, expected: theroot/basic-mapping-original.js ++ Expected: "theroot/basic-mapping-original.js" ++ Actual: "basic-mapping-original.js" ++sourceResolutionAbsoluteURL ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++PASS: Test location (0, 0) should be mapped ++PASS: Original line: 0, expected: 0 ++PASS: Original column: 0, expected: 0 ++FAIL: Original source: basic-mapping-original.js, expected: /baz/quux/basic-mapping-original.js ++ Expected: "/baz/quux/basic-mapping-original.js" ++ Actual: "basic-mapping-original.js" ++PASS: Test location (0, 9) should be mapped ++PASS: Original line: 0, expected: 0 ++PASS: Original column: 9, expected: 9 ++FAIL: Original source: basic-mapping-original.js, expected: /baz/quux/basic-mapping-original.js ++ Expected: "/baz/quux/basic-mapping-original.js" ++ Actual: "basic-mapping-original.js" ++basicMappingWithIndexMap ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++PASS: Test location (0, 0) should be mapped ++PASS: Original line: 0, expected: 0 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 9) should be mapped ++PASS: Original line: 0, expected: 0 ++PASS: Original column: 9, expected: 9 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 15) should be mapped ++PASS: Original line: 1, expected: 1 ++PASS: Original column: 2, expected: 2 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 22) should be mapped ++PASS: Original line: 1, expected: 1 ++PASS: Original column: 9, expected: 9 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 24) should be mapped ++PASS: Original line: 2, expected: 2 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 25) should be mapped ++PASS: Original line: 3, expected: 3 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 34) should be mapped ++PASS: Original line: 3, expected: 3 ++PASS: Original column: 9, expected: 9 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 40) should be mapped ++PASS: Original line: 4, expected: 4 ++PASS: Original column: 2, expected: 2 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 47) should be mapped ++PASS: Original line: 4, expected: 4 ++PASS: Original column: 9, expected: 9 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 49) should be mapped ++PASS: Original line: 5, expected: 5 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 50) should be mapped ++PASS: Original line: 6, expected: 6 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 56) should be mapped ++PASS: Original line: 7, expected: 7 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++indexMapWithMissingFile ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++PASS: Test location (0, 0) should be mapped ++PASS: Original line: 0, expected: 0 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 9) should be mapped ++PASS: Original line: 0, expected: 0 ++PASS: Original column: 9, expected: 9 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 15) should be mapped ++PASS: Original line: 1, expected: 1 ++PASS: Original column: 2, expected: 2 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 22) should be mapped ++PASS: Original line: 1, expected: 1 ++PASS: Original column: 9, expected: 9 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 24) should be mapped ++PASS: Original line: 2, expected: 2 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 25) should be mapped ++PASS: Original line: 3, expected: 3 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 34) should be mapped ++PASS: Original line: 3, expected: 3 ++PASS: Original column: 9, expected: 9 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 40) should be mapped ++PASS: Original line: 4, expected: 4 ++PASS: Original column: 2, expected: 2 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 47) should be mapped ++PASS: Original line: 4, expected: 4 ++PASS: Original column: 9, expected: 9 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 49) should be mapped ++PASS: Original line: 5, expected: 5 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 50) should be mapped ++PASS: Original line: 6, expected: 6 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 56) should be mapped ++PASS: Original line: 7, expected: 7 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++indexMapWithTwoConcatenatedSources ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++PASS: Test location (0, 0) should be mapped ++PASS: Original line: 0, expected: 0 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 9) should be mapped ++PASS: Original line: 0, expected: 0 ++PASS: Original column: 9, expected: 9 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 15) should be mapped ++PASS: Original line: 1, expected: 1 ++PASS: Original column: 2, expected: 2 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 22) should be mapped ++PASS: Original line: 1, expected: 1 ++PASS: Original column: 9, expected: 9 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 24) should be mapped ++PASS: Original line: 2, expected: 2 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 25) should be mapped ++PASS: Original line: 3, expected: 3 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 34) should be mapped ++PASS: Original line: 3, expected: 3 ++PASS: Original column: 9, expected: 9 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 40) should be mapped ++PASS: Original line: 4, expected: 4 ++PASS: Original column: 2, expected: 2 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 47) should be mapped ++PASS: Original line: 4, expected: 4 ++PASS: Original column: 9, expected: 9 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 49) should be mapped ++PASS: Original line: 5, expected: 5 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 50) should be mapped ++PASS: Original line: 6, expected: 6 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 56) should be mapped ++PASS: Original line: 7, expected: 7 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 62) should be mapped ++PASS: Original line: 0, expected: 0 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: second-source-original.js, expected: second-source-original.js ++PASS: Test location (0, 71) should be mapped ++PASS: Original line: 0, expected: 0 ++PASS: Original column: 9, expected: 9 ++PASS: Original source: second-source-original.js, expected: second-source-original.js ++PASS: Test location (0, 77) should be mapped ++PASS: Original line: 1, expected: 1 ++PASS: Original column: 2, expected: 2 ++PASS: Original source: second-source-original.js, expected: second-source-original.js ++PASS: Test location (0, 83) should be mapped ++PASS: Original line: 1, expected: 1 ++PASS: Original column: 9, expected: 9 ++PASS: Original source: second-source-original.js, expected: second-source-original.js ++PASS: Test location (0, 88) should be mapped ++PASS: Original line: 2, expected: 2 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: second-source-original.js, expected: second-source-original.js ++PASS: Test location (0, 89) should be mapped ++PASS: Original line: 3, expected: 3 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: second-source-original.js, expected: second-source-original.js ++sourcesNullSourcesContentNonNull ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++PASS: Test location (0, 0) should be mapped ++PASS: Original line: 0, expected: 0 ++PASS: Original column: 0, expected: 0 ++FAIL: Original source: sources-null-sources-content-non-null.js.map, expected: null ++ Expected: null ++ Actual: "sources-null-sources-content-non-null.js.map" ++PASS: Test location (0, 9) should be mapped ++PASS: Original line: 0, expected: 0 ++PASS: Original column: 9, expected: 9 ++FAIL: Original source: sources-null-sources-content-non-null.js.map, expected: null ++ Expected: null ++ Actual: "sources-null-sources-content-non-null.js.map" ++sourcesNonNullSourcesContentNull ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++PASS: Test location (0, 0) should be mapped ++PASS: Original line: 0, expected: 0 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++PASS: Test location (0, 9) should be mapped ++PASS: Original line: 0, expected: 0 ++PASS: Original column: 9, expected: 9 ++PASS: Original source: basic-mapping-original.js, expected: basic-mapping-original.js ++transitiveMapping ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++Transitive mapping test ignored ++Transitive mapping test ignored ++Transitive mapping test ignored ++Transitive mapping test ignored ++Transitive mapping test ignored ++Transitive mapping test ignored ++Transitive mapping test ignored ++Transitive mapping test ignored ++transitiveMappingWithThreeSteps ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++Transitive mapping test ignored ++Transitive mapping test ignored ++Transitive mapping test ignored ++Transitive mapping test ignored ++Transitive mapping test ignored ++Transitive mapping test ignored ++Transitive mapping test ignored ++Transitive mapping test ignored ++vlqValidSingleDigit ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++PASS: Test location (0, 15) should be mapped ++PASS: Original line: 0, expected: 0 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: vlq-valid-single-digit-original.js, expected: vlq-valid-single-digit-original.js ++vlqValidNegativeDigit ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++PASS: Test location (2, 15) should be mapped ++PASS: Original line: 1, expected: 1 ++FAIL: Original column: 1, expected: 3 ++ Expected: 3 ++ Actual: 1 ++PASS: Original source: vlq-valid-negative-digit-original.js, expected: vlq-valid-negative-digit-original.js ++PASS: Test location (2, 2) should be mapped ++PASS: Original line: 1, expected: 1 ++PASS: Original column: 1, expected: 1 ++PASS: Original source: vlq-valid-negative-digit-original.js, expected: vlq-valid-negative-digit-original.js ++vlqValidContinuationBitPresent1 ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++PASS: Test location (0, 15) should be mapped ++PASS: Original line: 0, expected: 0 ++PASS: Original column: 1, expected: 1 ++PASS: Original source: vlq-valid-continuation-bit-present-1-original.js, expected: vlq-valid-continuation-bit-present-1-original.js ++vlqValidContinuationBitPresent2 ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++PASS: Test location (2, 16) should be mapped ++PASS: Original line: 1, expected: 1 ++PASS: Original column: 1, expected: 1 ++PASS: Original source: vlq-valid-continuation-bit-present-2-original.js, expected: vlq-valid-continuation-bit-present-2-original.js ++mappingSemanticsSingleFieldSegment ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++PASS: Test location (0, 0) should be mapped ++PASS: Original line: 0, expected: 0 ++PASS: Original column: 1, expected: 1 ++PASS: Original source: mapping-semantics-single-field-segment-original.js, expected: mapping-semantics-single-field-segment-original.js ++PASS: Test location (0, 2) should be mapped ++FAIL: Original line: 0, expected: null ++ Expected: null ++ Actual: 0 ++FAIL: Original column: 1, expected: null ++ Expected: null ++ Actual: 1 ++FAIL: Original source: mapping-semantics-single-field-segment-original.js, expected: null ++ Expected: null ++ Actual: "mapping-semantics-single-field-segment-original.js" ++mappingSemanticsFourFieldSegment ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++PASS: Test location (0, 1) should be mapped ++PASS: Original line: 2, expected: 2 ++PASS: Original column: 2, expected: 2 ++PASS: Original source: mapping-semantics-four-field-segment-original.js, expected: mapping-semantics-four-field-segment-original.js ++mappingSemanticsFiveFieldSegment ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++PASS: Test location (0, 1) should be mapped ++PASS: Original line: 2, expected: 2 ++PASS: Original column: 2, expected: 2 ++PASS: Original source: mapping-semantics-five-field-segment-original.js, expected: mapping-semantics-five-field-segment-original.js ++mappingSemanticsColumnReset ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++PASS: Test location (0, 1) should be mapped ++PASS: Original line: 0, expected: 0 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: mapping-semantics-column-reset-original.js, expected: mapping-semantics-column-reset-original.js ++PASS: Test location (1, 1) should be mapped ++PASS: Original line: 1, expected: 1 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: mapping-semantics-column-reset-original.js, expected: mapping-semantics-column-reset-original.js ++mappingSemanticsRelative1 ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++PASS: Test location (0, 1) should be mapped ++PASS: Original line: 0, expected: 0 ++PASS: Original column: 0, expected: 0 ++PASS: Original source: mapping-semantics-relative-1-original.js, expected: mapping-semantics-relative-1-original.js ++PASS: Test location (0, 5) should be mapped ++PASS: Original line: 0, expected: 0 ++PASS: Original column: 4, expected: 4 ++PASS: Original source: mapping-semantics-relative-1-original.js, expected: mapping-semantics-relative-1-original.js ++mappingSemanticsRelative2 ++PASS: Resource should have loaded 1 SourceMap. ++PASS: SourceMap should be a WI.SourceMap instance. ++PASS: Test location (0, 1) should be mapped ++PASS: Original line: 0, expected: 0 ++PASS: Original column: 2, expected: 2 ++PASS: Original source: mapping-semantics-relative-2-original.js, expected: mapping-semantics-relative-2-original.js ++PASS: Test location (1, 2) should be mapped ++PASS: Original line: 1, expected: 1 ++PASS: Original column: 2, expected: 2 ++PASS: Original source: mapping-semantics-relative-2-original.js, expected: mapping-semantics-relative-2-original.js ++ +diff --git a/LayoutTests/inspector/model/source-map-spec.html b/LayoutTests/inspector/model/source-map-spec.html +new file mode 100644 +index 000000000000..08979e569710 +--- /dev/null ++++ b/LayoutTests/inspector/model/source-map-spec.html +@@ -0,0 +1,87 @@ ++ ++ ++ ++ ++ ++ ++ ++

Run source map specification consumer test cases.

++ ++ +-- +2.39.2 + diff --git a/test/js/node/test/fixtures/typescript/cts/node_modules/bar/bar.ts b/test/js/node/test/fixtures/typescript/cts/node_modules/bar/bar.ts new file mode 100644 index 0000000000..e0716bfd56 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/cts/node_modules/bar/bar.ts @@ -0,0 +1,5 @@ +const bar: string = "Hello, TypeScript!"; + +module.exports = { + bar, +}; diff --git a/test/js/node/test/fixtures/typescript/cts/node_modules/bar/package.json b/test/js/node/test/fixtures/typescript/cts/node_modules/bar/package.json new file mode 100644 index 0000000000..18ef424398 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/cts/node_modules/bar/package.json @@ -0,0 +1,13 @@ +{ + "name": "bar", + "version": "1.0.0", + "main": "bar.ts", + "devDependencies": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "description": "" +} \ No newline at end of file diff --git a/test/js/node/test/fixtures/typescript/cts/node_modules/baz/baz.mts b/test/js/node/test/fixtures/typescript/cts/node_modules/baz/baz.mts new file mode 100644 index 0000000000..746109acf8 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/cts/node_modules/baz/baz.mts @@ -0,0 +1 @@ +export const baz: string = 'Hello, TypeScript!'; diff --git a/test/js/node/test/fixtures/typescript/cts/node_modules/baz/package.json b/test/js/node/test/fixtures/typescript/cts/node_modules/baz/package.json new file mode 100644 index 0000000000..5260f9a33d --- /dev/null +++ b/test/js/node/test/fixtures/typescript/cts/node_modules/baz/package.json @@ -0,0 +1,14 @@ +{ + "name": "baz", + "version": "1.0.0", + "type": "module", + "main": "baz.mts", + "devDependencies": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "description": "" +} \ No newline at end of file diff --git a/test/js/node/test/fixtures/typescript/cts/node_modules/foo/foo.cts b/test/js/node/test/fixtures/typescript/cts/node_modules/foo/foo.cts new file mode 100644 index 0000000000..c7dbc8680a --- /dev/null +++ b/test/js/node/test/fixtures/typescript/cts/node_modules/foo/foo.cts @@ -0,0 +1,5 @@ +const foo: string = 'Hello, TypeScript!'; + +module.exports = { + foo +}; diff --git a/test/js/node/test/fixtures/typescript/cts/node_modules/foo/package.json b/test/js/node/test/fixtures/typescript/cts/node_modules/foo/package.json new file mode 100644 index 0000000000..3036e61850 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/cts/node_modules/foo/package.json @@ -0,0 +1,14 @@ +{ + "name": "foo", + "version": "1.0.0", + "type": "commonjs", + "main": "foo.cts", + "devDependencies": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "description": "" +} \ No newline at end of file diff --git a/test/js/node/test/fixtures/typescript/cts/test-commonjs-export.ts b/test/js/node/test/fixtures/typescript/cts/test-commonjs-export.ts new file mode 100644 index 0000000000..27d36ea1fe --- /dev/null +++ b/test/js/node/test/fixtures/typescript/cts/test-commonjs-export.ts @@ -0,0 +1,3 @@ +const foo: string = 'Hello, TypeScript!'; + +module.exports = { foo }; diff --git a/test/js/node/test/fixtures/typescript/cts/test-cts-but-module-syntax.cts b/test/js/node/test/fixtures/typescript/cts/test-cts-but-module-syntax.cts new file mode 100644 index 0000000000..87c784633d --- /dev/null +++ b/test/js/node/test/fixtures/typescript/cts/test-cts-but-module-syntax.cts @@ -0,0 +1,5 @@ +import util from 'node:util'; + +export const text: string = 'Hello, TypeScript!'; + +console.log(util.styleText(['bold', 'red'], text)); diff --git a/test/js/node/test/fixtures/typescript/cts/test-cts-export-foo.cts b/test/js/node/test/fixtures/typescript/cts/test-cts-export-foo.cts new file mode 100644 index 0000000000..27d36ea1fe --- /dev/null +++ b/test/js/node/test/fixtures/typescript/cts/test-cts-export-foo.cts @@ -0,0 +1,3 @@ +const foo: string = 'Hello, TypeScript!'; + +module.exports = { foo }; diff --git a/test/js/node/test/fixtures/typescript/cts/test-cts-node_modules.cts b/test/js/node/test/fixtures/typescript/cts/test-cts-node_modules.cts new file mode 100644 index 0000000000..d27bb40c6d --- /dev/null +++ b/test/js/node/test/fixtures/typescript/cts/test-cts-node_modules.cts @@ -0,0 +1,5 @@ +const { foo } = require('foo'); + +interface Foo {}; + +console.log(foo); diff --git a/test/js/node/test/fixtures/typescript/cts/test-extensionless-require.ts b/test/js/node/test/fixtures/typescript/cts/test-extensionless-require.ts new file mode 100644 index 0000000000..20e2ffdc7c --- /dev/null +++ b/test/js/node/test/fixtures/typescript/cts/test-extensionless-require.ts @@ -0,0 +1,3 @@ +const { foo } = require('./test-commonjs-export'); + +console.log(foo); diff --git a/test/js/node/test/fixtures/typescript/cts/test-import-require.cts b/test/js/node/test/fixtures/typescript/cts/test-import-require.cts new file mode 100644 index 0000000000..2d21a9c6ec --- /dev/null +++ b/test/js/node/test/fixtures/typescript/cts/test-import-require.cts @@ -0,0 +1,5 @@ +import util = require("node:util"); + +const foo: string = "Hello, TypeScript!"; + +console.log(util.styleText(["red"], foo)); diff --git a/test/js/node/test/fixtures/typescript/cts/test-mts-node_modules.cts b/test/js/node/test/fixtures/typescript/cts/test-mts-node_modules.cts new file mode 100644 index 0000000000..125d98571a --- /dev/null +++ b/test/js/node/test/fixtures/typescript/cts/test-mts-node_modules.cts @@ -0,0 +1,5 @@ +const { baz } = require('baz'); + +interface Foo { }; + +console.log(baz); diff --git a/test/js/node/test/fixtures/typescript/cts/test-require-commonjs.cts b/test/js/node/test/fixtures/typescript/cts/test-require-commonjs.cts new file mode 100644 index 0000000000..ee0f4410d7 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/cts/test-require-commonjs.cts @@ -0,0 +1,5 @@ +const { foo } = require('./test-cts-export-foo.cts'); + +interface Foo {}; + +console.log(foo); diff --git a/test/js/node/test/fixtures/typescript/cts/test-require-mts-module.cts b/test/js/node/test/fixtures/typescript/cts/test-require-mts-module.cts new file mode 100644 index 0000000000..0b40b3b566 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/cts/test-require-mts-module.cts @@ -0,0 +1,5 @@ +const { foo } = require('../mts/test-mts-export-foo.mts'); + +interface Foo {}; + +console.log(foo); diff --git a/test/js/node/test/fixtures/typescript/cts/test-require-ts-file.cts b/test/js/node/test/fixtures/typescript/cts/test-require-ts-file.cts new file mode 100644 index 0000000000..08015a6cdc --- /dev/null +++ b/test/js/node/test/fixtures/typescript/cts/test-require-ts-file.cts @@ -0,0 +1,5 @@ +const { foo } = require('./test-commonjs-export.ts'); + +interface Foo {}; + +console.log(foo); diff --git a/test/js/node/test/fixtures/typescript/cts/test-ts-node_modules.cts b/test/js/node/test/fixtures/typescript/cts/test-ts-node_modules.cts new file mode 100644 index 0000000000..c565a00a9b --- /dev/null +++ b/test/js/node/test/fixtures/typescript/cts/test-ts-node_modules.cts @@ -0,0 +1,5 @@ +const { bar } = require('bar'); + +interface Foo { }; + +console.log(bar); diff --git a/test/js/node/test/fixtures/typescript/echo-process-features-typescript.cjs b/test/js/node/test/fixtures/typescript/echo-process-features-typescript.cjs new file mode 100644 index 0000000000..7f8b14e9e0 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/echo-process-features-typescript.cjs @@ -0,0 +1,2 @@ +'use strict'; +console.log(process.features.typescript); diff --git a/test/js/node/test/fixtures/typescript/mts/node_modules/bar/bar.ts b/test/js/node/test/fixtures/typescript/mts/node_modules/bar/bar.ts new file mode 100644 index 0000000000..a0f11c62ba --- /dev/null +++ b/test/js/node/test/fixtures/typescript/mts/node_modules/bar/bar.ts @@ -0,0 +1,5 @@ +const bar: string = 'Hello, TypeScript!' + +module.exports = { + bar +}; diff --git a/test/js/node/test/fixtures/typescript/mts/node_modules/bar/package.json b/test/js/node/test/fixtures/typescript/mts/node_modules/bar/package.json new file mode 100644 index 0000000000..18ef424398 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/mts/node_modules/bar/package.json @@ -0,0 +1,13 @@ +{ + "name": "bar", + "version": "1.0.0", + "main": "bar.ts", + "devDependencies": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "description": "" +} \ No newline at end of file diff --git a/test/js/node/test/fixtures/typescript/mts/node_modules/baz/baz.mts b/test/js/node/test/fixtures/typescript/mts/node_modules/baz/baz.mts new file mode 100644 index 0000000000..746109acf8 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/mts/node_modules/baz/baz.mts @@ -0,0 +1 @@ +export const baz: string = 'Hello, TypeScript!'; diff --git a/test/js/node/test/fixtures/typescript/mts/node_modules/baz/package.json b/test/js/node/test/fixtures/typescript/mts/node_modules/baz/package.json new file mode 100644 index 0000000000..e44b74aa18 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/mts/node_modules/baz/package.json @@ -0,0 +1,13 @@ +{ + "name": "baz", + "version": "1.0.0", + "main": "baz.mts", + "devDependencies": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "description": "" +} \ No newline at end of file diff --git a/test/js/node/test/fixtures/typescript/mts/node_modules/foo/foo.cts b/test/js/node/test/fixtures/typescript/mts/node_modules/foo/foo.cts new file mode 100644 index 0000000000..c7dbc8680a --- /dev/null +++ b/test/js/node/test/fixtures/typescript/mts/node_modules/foo/foo.cts @@ -0,0 +1,5 @@ +const foo: string = 'Hello, TypeScript!'; + +module.exports = { + foo +}; diff --git a/test/js/node/test/fixtures/typescript/mts/node_modules/foo/package.json b/test/js/node/test/fixtures/typescript/mts/node_modules/foo/package.json new file mode 100644 index 0000000000..3036e61850 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/mts/node_modules/foo/package.json @@ -0,0 +1,14 @@ +{ + "name": "foo", + "version": "1.0.0", + "type": "commonjs", + "main": "foo.cts", + "devDependencies": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "description": "" +} \ No newline at end of file diff --git a/test/js/node/test/fixtures/typescript/mts/test-cts-node_modules.mts b/test/js/node/test/fixtures/typescript/mts/test-cts-node_modules.mts new file mode 100644 index 0000000000..410daa11b6 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/mts/test-cts-node_modules.mts @@ -0,0 +1,5 @@ +import { foo } from 'foo'; + +interface Foo { }; + +console.log(foo); diff --git a/test/js/node/test/fixtures/typescript/mts/test-import-commonjs.mts b/test/js/node/test/fixtures/typescript/mts/test-import-commonjs.mts new file mode 100644 index 0000000000..1a18d4f4d9 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/mts/test-import-commonjs.mts @@ -0,0 +1,5 @@ +import { foo } from '../cts/test-cts-export-foo.cts'; + +interface Foo {}; + +console.log(foo); diff --git a/test/js/node/test/fixtures/typescript/mts/test-import-module.mts b/test/js/node/test/fixtures/typescript/mts/test-import-module.mts new file mode 100644 index 0000000000..24e15fedae --- /dev/null +++ b/test/js/node/test/fixtures/typescript/mts/test-import-module.mts @@ -0,0 +1,5 @@ +import { foo } from './test-mts-export-foo.mts'; + +interface Foo {}; + +console.log(foo); diff --git a/test/js/node/test/fixtures/typescript/mts/test-import-ts-file.mts b/test/js/node/test/fixtures/typescript/mts/test-import-ts-file.mts new file mode 100644 index 0000000000..2cfc1a9156 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/mts/test-import-ts-file.mts @@ -0,0 +1,5 @@ +import { foo } from './test-module-export.ts'; + +interface Foo {}; + +console.log(foo); diff --git a/test/js/node/test/fixtures/typescript/mts/test-module-export.ts b/test/js/node/test/fixtures/typescript/mts/test-module-export.ts new file mode 100644 index 0000000000..4ed5c6cfde --- /dev/null +++ b/test/js/node/test/fixtures/typescript/mts/test-module-export.ts @@ -0,0 +1 @@ +export const foo: string = 'Hello, TypeScript!'; diff --git a/test/js/node/test/fixtures/typescript/mts/test-mts-but-commonjs-syntax.mts b/test/js/node/test/fixtures/typescript/mts/test-mts-but-commonjs-syntax.mts new file mode 100644 index 0000000000..bb2973190d --- /dev/null +++ b/test/js/node/test/fixtures/typescript/mts/test-mts-but-commonjs-syntax.mts @@ -0,0 +1,9 @@ +const util = require('node:util'); + +const text: string = 'Hello, TypeScript!'; + +console.log(util.styleText(['bold', 'red'], text)); + +module.exports = { + text +}; diff --git a/test/js/node/test/fixtures/typescript/mts/test-mts-export-foo.mts b/test/js/node/test/fixtures/typescript/mts/test-mts-export-foo.mts new file mode 100644 index 0000000000..4ed5c6cfde --- /dev/null +++ b/test/js/node/test/fixtures/typescript/mts/test-mts-export-foo.mts @@ -0,0 +1 @@ +export const foo: string = 'Hello, TypeScript!'; diff --git a/test/js/node/test/fixtures/typescript/mts/test-mts-node_modules.mts b/test/js/node/test/fixtures/typescript/mts/test-mts-node_modules.mts new file mode 100644 index 0000000000..8c49583f20 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/mts/test-mts-node_modules.mts @@ -0,0 +1,5 @@ +import { baz } from 'baz'; + +interface Foo {}; + +console.log(baz); diff --git a/test/js/node/test/fixtures/typescript/mts/test-ts-node_modules.mts b/test/js/node/test/fixtures/typescript/mts/test-ts-node_modules.mts new file mode 100644 index 0000000000..fe4f3b7434 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/mts/test-ts-node_modules.mts @@ -0,0 +1,5 @@ +import { bar } from 'bar'; + +interface Foo {}; + +console.log(bar); diff --git a/test/js/node/test/fixtures/typescript/ts/commonjs-logger.ts b/test/js/node/test/fixtures/typescript/ts/commonjs-logger.ts new file mode 100644 index 0000000000..91b171231e --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/commonjs-logger.ts @@ -0,0 +1,5 @@ +const logger = (): void => { }; + +module.exports = { + logger +} diff --git a/test/js/node/test/fixtures/typescript/ts/hook.ts b/test/js/node/test/fixtures/typescript/ts/hook.ts new file mode 100644 index 0000000000..e0dd46448b --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/hook.ts @@ -0,0 +1,11 @@ +import type { ResolveHook } from 'node:module'; + +// Pass through +export const resolve: ResolveHook = async function resolve(specifier, context, nextResolve) { + if(false){ + // https://github.com/nodejs/node/issues/54645 + // A bug in the typescript parsers swc causes + // the next line to not be parsed correctly + } + return nextResolve(specifier, context); +}; diff --git a/test/js/node/test/fixtures/typescript/ts/issue-54457.mjs b/test/js/node/test/fixtures/typescript/ts/issue-54457.mjs new file mode 100644 index 0000000000..7394101b61 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/issue-54457.mjs @@ -0,0 +1,4 @@ +// https://github.com/nodejs/node/issues/54457 +const { text } = await import('./test-require.ts'); + +console.log(text); diff --git a/test/js/node/test/fixtures/typescript/ts/module-logger.ts b/test/js/node/test/fixtures/typescript/ts/module-logger.ts new file mode 100644 index 0000000000..50aecfdf35 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/module-logger.ts @@ -0,0 +1 @@ +export const logger = (): void => { }; diff --git a/test/js/node/test/fixtures/typescript/ts/node_modules/bar/bar.ts b/test/js/node/test/fixtures/typescript/ts/node_modules/bar/bar.ts new file mode 100644 index 0000000000..7e3a197411 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/node_modules/bar/bar.ts @@ -0,0 +1,3 @@ +const bar: string = 'Hello, TypeScript!'; + +module.exports = { bar }; \ No newline at end of file diff --git a/test/js/node/test/fixtures/typescript/ts/node_modules/bar/package.json b/test/js/node/test/fixtures/typescript/ts/node_modules/bar/package.json new file mode 100644 index 0000000000..ff1ab7524e --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/node_modules/bar/package.json @@ -0,0 +1,13 @@ +{ + "name": "bar", + "version": "1.0.0", + "main": "bar.ts", + "devDependencies": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "description": "" +} diff --git a/test/js/node/test/fixtures/typescript/ts/node_modules/foo/foo.js b/test/js/node/test/fixtures/typescript/ts/node_modules/foo/foo.js new file mode 100644 index 0000000000..a4b27706c7 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/node_modules/foo/foo.js @@ -0,0 +1 @@ +export const foo = "Hello, TypeScript!" diff --git a/test/js/node/test/fixtures/typescript/ts/node_modules/foo/package.json b/test/js/node/test/fixtures/typescript/ts/node_modules/foo/package.json new file mode 100644 index 0000000000..7182125d8b --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/node_modules/foo/package.json @@ -0,0 +1,14 @@ +{ + "name": "foo", + "version": "1.0.0", + "type": "module", + "main": "foo.js", + "devDependencies": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "description": "" +} diff --git a/test/js/node/test/fixtures/typescript/ts/test-commonjs-parsing.ts b/test/js/node/test/fixtures/typescript/ts/test-commonjs-parsing.ts new file mode 100644 index 0000000000..bb2973190d --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-commonjs-parsing.ts @@ -0,0 +1,9 @@ +const util = require('node:util'); + +const text: string = 'Hello, TypeScript!'; + +console.log(util.styleText(['bold', 'red'], text)); + +module.exports = { + text +}; diff --git a/test/js/node/test/fixtures/typescript/ts/test-cts-typescript.cts b/test/js/node/test/fixtures/typescript/ts/test-cts-typescript.cts new file mode 100644 index 0000000000..45d056b9c9 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-cts-typescript.cts @@ -0,0 +1,5 @@ +const str: string = "Hello, TypeScript!"; +interface Foo { + bar: string; +} +console.log(str); diff --git a/test/js/node/test/fixtures/typescript/ts/test-empty-file.ts b/test/js/node/test/fixtures/typescript/ts/test-empty-file.ts new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-empty-file.ts @@ -0,0 +1 @@ + diff --git a/test/js/node/test/fixtures/typescript/ts/test-enums.ts b/test/js/node/test/fixtures/typescript/ts/test-enums.ts new file mode 100644 index 0000000000..52fc4cfebd --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-enums.ts @@ -0,0 +1,13 @@ +enum Color { + Red, + Green, + Blue, +} + +console.log(Color.Red); +console.log(Color.Green); +console.log(Color.Blue); + +console.log(Color[0]); +console.log(Color[1]); +console.log(Color[2]); diff --git a/test/js/node/test/fixtures/typescript/ts/test-experimental-decorators.ts b/test/js/node/test/fixtures/typescript/ts/test-experimental-decorators.ts new file mode 100644 index 0000000000..073ceb0fbb --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-experimental-decorators.ts @@ -0,0 +1,14 @@ +function sealed(constructor: Function) { + Object.seal(constructor); + Object.seal(constructor.prototype); +} + +@sealed +class BugReport { + type = "report"; + title: string; + + constructor(t: string) { + this.title = t; + } +} diff --git a/test/js/node/test/fixtures/typescript/ts/test-export-foo.ts b/test/js/node/test/fixtures/typescript/ts/test-export-foo.ts new file mode 100644 index 0000000000..3b94da93c4 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-export-foo.ts @@ -0,0 +1 @@ +export const foo: string = "Hello, TypeScript!"; diff --git a/test/js/node/test/fixtures/typescript/ts/test-get-callsite-explicit.ts b/test/js/node/test/fixtures/typescript/ts/test-get-callsite-explicit.ts new file mode 100644 index 0000000000..331495419a --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-get-callsite-explicit.ts @@ -0,0 +1,10 @@ +const { getCallSites } = require('node:util'); + +interface CallSite { + A; + B; +} + +const callSite = getCallSites({ sourceMap: false })[0]; + +console.log('mapCallSite: ', callSite); diff --git a/test/js/node/test/fixtures/typescript/ts/test-get-callsite.ts b/test/js/node/test/fixtures/typescript/ts/test-get-callsite.ts new file mode 100644 index 0000000000..e3186ec889 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-get-callsite.ts @@ -0,0 +1,10 @@ +const { getCallSites } = require('node:util'); + +interface CallSite { + A; + B; +} + +const callSite = getCallSites()[0]; + +console.log('getCallSite: ', callSite); diff --git a/test/js/node/test/fixtures/typescript/ts/test-import-foo.ts b/test/js/node/test/fixtures/typescript/ts/test-import-foo.ts new file mode 100644 index 0000000000..da66e19ef2 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-import-foo.ts @@ -0,0 +1,5 @@ +import { foo } from './test-export-foo.ts'; + +interface Foo {}; + +console.log(foo); diff --git a/test/js/node/test/fixtures/typescript/ts/test-import-fs.ts b/test/js/node/test/fixtures/typescript/ts/test-import-fs.ts new file mode 100644 index 0000000000..032a93fa52 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-import-fs.ts @@ -0,0 +1,2 @@ +import fs from 'fs'; +console.log('Hello, TypeScript!'); diff --git a/test/js/node/test/fixtures/typescript/ts/test-import-no-extension.ts b/test/js/node/test/fixtures/typescript/ts/test-import-no-extension.ts new file mode 100644 index 0000000000..738ceddbaa --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-import-no-extension.ts @@ -0,0 +1,5 @@ +import { foo } from './test-no-extensions'; + +interface Foo {}; + +console.log(foo); diff --git a/test/js/node/test/fixtures/typescript/ts/test-import-no-type-keyword.ts b/test/js/node/test/fixtures/typescript/ts/test-import-no-type-keyword.ts new file mode 100644 index 0000000000..278eb3e032 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-import-no-type-keyword.ts @@ -0,0 +1,7 @@ +import { MyType } from './test-types.d.ts'; + +const myVar: MyType = { + foo: 'Hello, TypeScript!' +}; + +console.log(myVar.foo); diff --git a/test/js/node/test/fixtures/typescript/ts/test-import-ts-node-modules.ts b/test/js/node/test/fixtures/typescript/ts/test-import-ts-node-modules.ts new file mode 100644 index 0000000000..864987c7cf --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-import-ts-node-modules.ts @@ -0,0 +1,5 @@ +import { bar } from 'bar'; + +interface Bar {}; + +console.log(bar); diff --git a/test/js/node/test/fixtures/typescript/ts/test-import-types.ts b/test/js/node/test/fixtures/typescript/ts/test-import-types.ts new file mode 100644 index 0000000000..ec32b31563 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-import-types.ts @@ -0,0 +1,7 @@ +import type { MyType } from './test-types.d.ts'; + +const myVar: MyType = { + foo: 'Hello, TypeScript!' +}; + +console.log(myVar.foo); diff --git a/test/js/node/test/fixtures/typescript/ts/test-invalid-syntax.ts b/test/js/node/test/fixtures/typescript/ts/test-invalid-syntax.ts new file mode 100644 index 0000000000..031bce938d --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-invalid-syntax.ts @@ -0,0 +1,3 @@ +function foo(): string { + await Promise.resolve(1); +} diff --git a/test/js/node/test/fixtures/typescript/ts/test-loader.ts b/test/js/node/test/fixtures/typescript/ts/test-loader.ts new file mode 100644 index 0000000000..8b957bf72f --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-loader.ts @@ -0,0 +1,4 @@ +import { register } from 'node:module'; +import * as fixtures from '../../../common/fixtures.mjs'; + +register(fixtures.fileURL('typescript/ts/hook.ts')); diff --git a/test/js/node/test/fixtures/typescript/ts/test-mock-module.ts b/test/js/node/test/fixtures/typescript/ts/test-mock-module.ts new file mode 100644 index 0000000000..adc5f5ce57 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-mock-module.ts @@ -0,0 +1,23 @@ +import { before, mock, test } from 'node:test'; +import { strictEqual } from 'node:assert'; + +const logger = mock.fn((s) => console.log(`Hello, ${s}!`)); + +before(async () => { + mock.module('./module-logger.ts', { + namedExports: { logger } + }); + mock.module('./commonjs-logger.ts', { + namedExports: { logger } + }); +}); + +test('logger', async () => { + const { logger: mockedModule } = await import('./module-logger.ts'); + mockedModule('TypeScript-Module'); + strictEqual(logger.mock.callCount(), 1); + + const { logger: mockedCommonjs } = await import('./commonjs-logger.ts'); + mockedCommonjs('TypeScript-CommonJS'); + strictEqual(logger.mock.callCount(), 2); +}); diff --git a/test/js/node/test/fixtures/typescript/ts/test-module-typescript.ts b/test/js/node/test/fixtures/typescript/ts/test-module-typescript.ts new file mode 100644 index 0000000000..145910853c --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-module-typescript.ts @@ -0,0 +1,5 @@ +import util from 'node:util'; + +export const text: string = 'Hello, TypeScript!'; + +console.log(util.styleText("red", text)); diff --git a/test/js/node/test/fixtures/typescript/ts/test-namespaces.ts b/test/js/node/test/fixtures/typescript/ts/test-namespaces.ts new file mode 100644 index 0000000000..eb4e4b3961 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-namespaces.ts @@ -0,0 +1,9 @@ +/// +namespace Validation { + const lettersRegexp = /^[A-Za-z]+$/; + export class LettersOnlyValidator { + isAcceptable(s: string) { + return lettersRegexp.test(s); + } + } +} diff --git a/test/js/node/test/fixtures/typescript/ts/test-no-extensions.ts b/test/js/node/test/fixtures/typescript/ts/test-no-extensions.ts new file mode 100644 index 0000000000..4ed5c6cfde --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-no-extensions.ts @@ -0,0 +1 @@ +export const foo: string = 'Hello, TypeScript!'; diff --git a/test/js/node/test/fixtures/typescript/ts/test-parameter-properties.ts b/test/js/node/test/fixtures/typescript/ts/test-parameter-properties.ts new file mode 100644 index 0000000000..5cf79f6f11 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-parameter-properties.ts @@ -0,0 +1,15 @@ +interface Bar { + name: string; + age: number; +} + +class Test { + constructor(private value: T) {} + + public getValue(): T { + return this.value; + } +} + +const foo = new Test({ age: 42, name: 'John Doe' }); +console.log(foo.getValue()); diff --git a/test/js/node/test/fixtures/typescript/ts/test-require-cts.ts b/test/js/node/test/fixtures/typescript/ts/test-require-cts.ts new file mode 100644 index 0000000000..46efff0616 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-require-cts.ts @@ -0,0 +1,5 @@ +const { foo } = require('../cts/test-cts-export-foo.cts'); + +interface Foo {}; + +console.log(foo); diff --git a/test/js/node/test/fixtures/typescript/ts/test-require-module.ts b/test/js/node/test/fixtures/typescript/ts/test-require-module.ts new file mode 100644 index 0000000000..52dc9d4c63 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-require-module.ts @@ -0,0 +1,3 @@ +const { foo } = require('../mts/test-mts-export-foo.mts'); + +console.log(foo); diff --git a/test/js/node/test/fixtures/typescript/ts/test-require-mts.ts b/test/js/node/test/fixtures/typescript/ts/test-require-mts.ts new file mode 100644 index 0000000000..2048760b78 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-require-mts.ts @@ -0,0 +1,5 @@ +const { foo } = require('../mts/test-mts-export-foo.mts'); + +interface Foo { }; + +console.log(foo); diff --git a/test/js/node/test/fixtures/typescript/ts/test-require.ts b/test/js/node/test/fixtures/typescript/ts/test-require.ts new file mode 100644 index 0000000000..a96db1a654 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-require.ts @@ -0,0 +1,7 @@ +const util = require('node:util'); + +const text = 'Hello, TypeScript!'; + +module.exports = { + text +}; diff --git a/test/js/node/test/fixtures/typescript/ts/test-simple.js b/test/js/node/test/fixtures/typescript/ts/test-simple.js new file mode 100644 index 0000000000..f738e60f7d --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-simple.js @@ -0,0 +1,2 @@ +const str = "Hello, TypeScript!"; +console.log(str); diff --git a/test/js/node/test/fixtures/typescript/ts/test-types.d.ts b/test/js/node/test/fixtures/typescript/ts/test-types.d.ts new file mode 100644 index 0000000000..d048d12d1f --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-types.d.ts @@ -0,0 +1,3 @@ +export type MyType = { + foo: string; +}; diff --git a/test/js/node/test/fixtures/typescript/ts/test-typescript-node-modules.ts b/test/js/node/test/fixtures/typescript/ts/test-typescript-node-modules.ts new file mode 100644 index 0000000000..8c16fd8873 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-typescript-node-modules.ts @@ -0,0 +1,3 @@ +import { foo } from 'foo'; + +console.log(foo); diff --git a/test/js/node/test/fixtures/typescript/ts/test-typescript.ts b/test/js/node/test/fixtures/typescript/ts/test-typescript.ts new file mode 100644 index 0000000000..41338c9845 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-typescript.ts @@ -0,0 +1,5 @@ +const str: string = "Hello, TypeScript!"; +interface Foo { + bar: string; +} +console.log(str); diff --git a/test/js/node/test/fixtures/typescript/ts/test-union-types.ts b/test/js/node/test/fixtures/typescript/ts/test-union-types.ts new file mode 100644 index 0000000000..baa8332d76 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-union-types.ts @@ -0,0 +1,53 @@ +// Use Some Union Types Together +const getTypescript = async () => { + return { + name: 'Hello, TypeScript!', + }; +}; + +type MyNameResult = Awaited>; +const myNameResult: MyNameResult = { + name: 'Hello, TypeScript!', +}; + +console.log(myNameResult); + +type RoleAttributes = + | { + role: 'admin'; + permission: 'all'; + } + | { + role: 'user'; + } + | { + role: 'manager'; + }; + +// Union Type: Extract +type AdminRole = Extract; +const adminRole: AdminRole = { + role: 'admin', + permission: 'all', +}; + +console.log(adminRole); + +type MyType = { + foo: string; + bar: number; + zoo: boolean; + metadata?: unknown; +}; + +// Union Type: Partial +type PartialType = Partial; + +const PartialTypeWithValues: PartialType = { + foo: 'Testing Partial Type', + bar: 42, + zoo: true, + metadata: undefined, +}; + +console.log(PartialTypeWithValues); diff --git a/test/js/node/test/fixtures/typescript/ts/test-whitespacing.ts b/test/js/node/test/fixtures/typescript/ts/test-whitespacing.ts new file mode 100644 index 0000000000..63bdd1648f --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/test-whitespacing.ts @@ -0,0 +1,5 @@ +interface Foo { + bar: string; +} + +throw new Error("Whitespacing"); diff --git a/test/js/node/test/fixtures/typescript/ts/transformation/test-decorator.ts b/test/js/node/test/fixtures/typescript/ts/transformation/test-decorator.ts new file mode 100644 index 0000000000..9590ee2591 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/transformation/test-decorator.ts @@ -0,0 +1,10 @@ +function greet(target: any, propertyKey: string, descriptor: PropertyDescriptor) { + descriptor.value = () => console.log('Hello, TypeScript!'); +} + +class Greeter { + @greet + sayHi() { } +} + +new Greeter().sayHi(); diff --git a/test/js/node/test/fixtures/typescript/ts/transformation/test-enum-stacktrace.ts b/test/js/node/test/fixtures/typescript/ts/transformation/test-enum-stacktrace.ts new file mode 100644 index 0000000000..de6a9eda0a --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/transformation/test-enum-stacktrace.ts @@ -0,0 +1,4 @@ +enum Foo { + A = "Hello, TypeScript!", +} +throw new Error(Foo.A); diff --git a/test/js/node/test/fixtures/typescript/ts/transformation/test-enum.ts b/test/js/node/test/fixtures/typescript/ts/transformation/test-enum.ts new file mode 100644 index 0000000000..2c874cdfae --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/transformation/test-enum.ts @@ -0,0 +1,4 @@ +enum Foo { + A = "Hello, TypeScript!", +} +console.log(Foo.A); diff --git a/test/js/node/test/fixtures/typescript/ts/transformation/test-legacy-module.ts b/test/js/node/test/fixtures/typescript/ts/transformation/test-legacy-module.ts new file mode 100644 index 0000000000..917adf23d8 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/transformation/test-legacy-module.ts @@ -0,0 +1,12 @@ +module Greeter { + export interface Person { + name: string; + } + + export function greet(person: Person): string { + return `Hello, ${person.name}!`; + } +} + +const user: Greeter.Person = { name: "TypeScript" }; +console.log(Greeter.greet(user)); diff --git a/test/js/node/test/fixtures/typescript/ts/transformation/test-modern-typescript.ts b/test/js/node/test/fixtures/typescript/ts/transformation/test-modern-typescript.ts new file mode 100644 index 0000000000..5f62bb1488 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/transformation/test-modern-typescript.ts @@ -0,0 +1,12 @@ +class Foo { + foo = "Hello, TypeScript!"; +} + +class Bar extends Foo { + get foo() { + return "I'm legacy and should not be called!" + } + set foo(v) { } +} + +console.log(new Bar().foo); diff --git a/test/js/node/test/fixtures/typescript/ts/transformation/test-namespace.ts b/test/js/node/test/fixtures/typescript/ts/transformation/test-namespace.ts new file mode 100644 index 0000000000..a69134cb6c --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/transformation/test-namespace.ts @@ -0,0 +1,7 @@ +namespace Greeting { + export function sayHello(name: string) { + return `Hello, ${name}!`; + } +} + +console.log(Greeting.sayHello("TypeScript!")); diff --git a/test/js/node/test/fixtures/typescript/ts/transformation/test-transformed-typescript.js b/test/js/node/test/fixtures/typescript/ts/transformation/test-transformed-typescript.js new file mode 100644 index 0000000000..074a070ba3 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/transformation/test-transformed-typescript.js @@ -0,0 +1,36 @@ +var Mathematics; +(function (Mathematics) { + let Operation; + (function (Operation) { + Operation[Operation["Add"] = 0] = "Add"; + Operation[Operation["Subtract"] = 1] = "Subtract"; + Operation[Operation["Multiply"] = 2] = "Multiply"; + Operation[Operation["Divide"] = 3] = "Divide"; + })(Operation = Mathematics.Operation || (Mathematics.Operation = {})); + class Calculator { + op; + constructor(op) { + this.op = op; + } + perform(a, b) { + switch (this.op) { + case 0: + return a + b; + case 1: + return a - b; + case 2: + return a * b; + case 3: + if (b === 0) throw new Error("Division by zero!"); + return a / b; + default: + throw new Error("Unknown operation"); + } + } + } + Mathematics.Calculator = Calculator; +})(Mathematics || (Mathematics = {})); +throw new Error("Stacktrace at line 28"); + + +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QtZmFpbGluZy1hcm02NC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO1VBQ1U7O2NBQ007Ozs7O09BQUEsd0JBQUEsMEJBQUE7SUFPTCxNQUFNOztRQUNULFlBQVksQUFBUSxFQUFhLENBQUU7aUJBQWYsS0FBQTtRQUFpQjtRQUVyQyxRQUFRLENBQVMsRUFBRSxDQUFTLEVBQVU7WUFDbEMsT0FBUSxJQUFJLENBQUMsRUFBRTtnQkFDWDtvQkFBb0IsT0FBTyxJQUFJO2dCQUMvQjtvQkFBeUIsT0FBTyxJQUFJO2dCQUNwQztvQkFBeUIsT0FBTyxJQUFJO2dCQUNwQztvQkFDSSxJQUFJLE1BQU0sR0FBRyxNQUFNLElBQUksTUFBTTtvQkFDN0IsT0FBTyxJQUFJO2dCQUNmO29CQUNJLE1BQU0sSUFBSSxNQUFNO1lBQ3hCO1FBQ0o7SUFDSjtnQkFmYSxhQUFBO0FBZ0JqQixHQXhCVSxnQkFBQTtBQTBCVixNQUFNLElBQUksTUFBTSJ9 diff --git a/test/js/node/test/fixtures/typescript/ts/transformation/test-unused-import.ts b/test/js/node/test/fixtures/typescript/ts/transformation/test-unused-import.ts new file mode 100644 index 0000000000..5390abeb96 --- /dev/null +++ b/test/js/node/test/fixtures/typescript/ts/transformation/test-unused-import.ts @@ -0,0 +1,3 @@ +// @ts-ignore +import { missing } from "."; +export { }; diff --git a/test/js/node/test/fixtures/tz-version.txt b/test/js/node/test/fixtures/tz-version.txt index 04fe674443..699e50d4d3 100644 --- a/test/js/node/test/fixtures/tz-version.txt +++ b/test/js/node/test/fixtures/tz-version.txt @@ -1 +1 @@ -2024a +2024b diff --git a/test/js/node/test/fixtures/warning_node_modules/new-buffer-cjs.js b/test/js/node/test/fixtures/warning_node_modules/new-buffer-cjs.js new file mode 100644 index 0000000000..be2877fa30 --- /dev/null +++ b/test/js/node/test/fixtures/warning_node_modules/new-buffer-cjs.js @@ -0,0 +1 @@ +require('new-buffer-cjs'); diff --git a/test/js/node/test/fixtures/warning_node_modules/new-buffer-esm.mjs b/test/js/node/test/fixtures/warning_node_modules/new-buffer-esm.mjs new file mode 100644 index 0000000000..9aa56f759f --- /dev/null +++ b/test/js/node/test/fixtures/warning_node_modules/new-buffer-esm.mjs @@ -0,0 +1 @@ +import 'new-buffer-esm' diff --git a/test/js/node/test/fixtures/warning_node_modules/node_modules/new-buffer-cjs/index.js b/test/js/node/test/fixtures/warning_node_modules/node_modules/new-buffer-cjs/index.js new file mode 100644 index 0000000000..514db554ed --- /dev/null +++ b/test/js/node/test/fixtures/warning_node_modules/node_modules/new-buffer-cjs/index.js @@ -0,0 +1 @@ +new Buffer(10); diff --git a/test/js/node/test/fixtures/warning_node_modules/node_modules/new-buffer-cjs/package.json b/test/js/node/test/fixtures/warning_node_modules/node_modules/new-buffer-cjs/package.json new file mode 100644 index 0000000000..f2c75cf8e4 --- /dev/null +++ b/test/js/node/test/fixtures/warning_node_modules/node_modules/new-buffer-cjs/package.json @@ -0,0 +1,3 @@ +{ + "main": "index.js" +} \ No newline at end of file diff --git a/test/js/node/test/fixtures/warning_node_modules/node_modules/new-buffer-esm/index.js b/test/js/node/test/fixtures/warning_node_modules/node_modules/new-buffer-esm/index.js new file mode 100644 index 0000000000..9dadaeb124 --- /dev/null +++ b/test/js/node/test/fixtures/warning_node_modules/node_modules/new-buffer-esm/index.js @@ -0,0 +1,2 @@ +import { Buffer } from 'node:buffer'; +new Buffer(10); diff --git a/test/js/node/test/fixtures/warning_node_modules/node_modules/new-buffer-esm/package.json b/test/js/node/test/fixtures/warning_node_modules/node_modules/new-buffer-esm/package.json new file mode 100644 index 0000000000..07fe062282 --- /dev/null +++ b/test/js/node/test/fixtures/warning_node_modules/node_modules/new-buffer-esm/package.json @@ -0,0 +1,4 @@ +{ + "main": "index.js", + "type": "module" +} \ No newline at end of file diff --git a/test/js/node/test/fixtures/worker-is-internal-thread.js b/test/js/node/test/fixtures/worker-is-internal-thread.js new file mode 100644 index 0000000000..7e3f1f4138 --- /dev/null +++ b/test/js/node/test/fixtures/worker-is-internal-thread.js @@ -0,0 +1,3 @@ +const { isInternalThread, parentPort } = require('node:worker_threads'); + +parentPort.postMessage(`isInternalThread: ${isInternalThread}`); \ No newline at end of file diff --git a/test/js/node/test/parallel/test-module-circular-dependency-warning.js b/test/js/node/test/parallel/test-module-circular-dependency-warning.js new file mode 100644 index 0000000000..8aed39f45e --- /dev/null +++ b/test/js/node/test/parallel/test-module-circular-dependency-warning.js @@ -0,0 +1,45 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const fixtures = require('../common/fixtures'); + +// common.expectWarning({ +// Warning: [ +// ["Accessing non-existent property 'missingPropB' " + +// 'of module exports inside circular dependency'], +// ["Accessing non-existent property 'Symbol(someSymbol)' " + +// 'of module exports inside circular dependency'], +// ["Accessing non-existent property 'missingPropModuleExportsB' " + +// 'of module exports inside circular dependency'], +// ] +// }); +const required = require(fixtures.path('cycles', 'warning-a.js')); +assert.strictEqual(Object.getPrototypeOf(required), Object.prototype); + +const requiredWithModuleExportsOverridden = + require(fixtures.path('cycles', 'warning-moduleexports-a.js')); +assert.strictEqual(Object.getPrototypeOf(requiredWithModuleExportsOverridden), + Object.prototype); + +// If module.exports is not a regular object, no warning should be emitted. +const classExport = + require(fixtures.path('cycles', 'warning-moduleexports-class-a.js')); +assert.strictEqual(Object.getPrototypeOf(classExport).name, 'Parent'); + +// If module.exports.__esModule is set, no warning should be emitted. +const esmTranspiledExport = + require(fixtures.path('cycles', 'warning-esm-transpiled-a.js')); +assert.strictEqual(esmTranspiledExport.__esModule, true); + +// If module.exports.__esModule is being accessed but is not present, e.g. +// because only the one of the files is a transpiled ES module, no warning +// should be emitted. +const halfTranspiledExport = + require(fixtures.path('cycles', 'warning-esm-half-transpiled-a.js')); +assert.strictEqual(halfTranspiledExport.__esModule, undefined); + +// No circular check is done to prevent triggering proxy traps, if +// module.exports is set to a proxy that contains a `getPrototypeOf` or +// `setPrototypeOf` trap. +require(fixtures.path('cycles', 'warning-skip-proxy-traps-a.js')); diff --git a/test/js/node/test/parallel/test-module-loading-error.js b/test/js/node/test/parallel/test-module-loading-error.js new file mode 100644 index 0000000000..d56e696942 --- /dev/null +++ b/test/js/node/test/parallel/test-module-loading-error.js @@ -0,0 +1,96 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const { execSync } = require('child_process'); + +const errorMessagesByPlatform = { + win32: ['is not a valid Win32 application'], + linux: ['file too short', 'Exec format error'], + sunos: ['unknown file type', 'not an ELF file'], + darwin: ['file too short', 'not a mach-o file'], + aix: ['Cannot load module', + 'Cannot run a file that does not have a valid format.', + 'Exec format error'], + ibmi: ['Cannot load module', + 'The module has too many section headers', + 'or the file has been truncated.'], +}; +// If we don't know a priori what the error would be, we accept anything. +const platform = common.isIBMi ? 'ibmi' : process.platform; +const errorMessages = errorMessagesByPlatform[platform] || ['']; + +// On Windows, error messages are MUI dependent +// Ref: https://github.com/nodejs/node/issues/13376 +let localeOk = true; +if (common.isWindows) { + const powerShellFindMUI = + 'powershell -NoProfile -ExecutionPolicy Unrestricted -c ' + + '"(Get-UICulture).TwoLetterISOLanguageName"'; + try { + // If MUI != 'en' we'll ignore the content of the message + localeOk = execSync(powerShellFindMUI).toString('utf8').trim() === 'en'; + } catch { + // It's only a best effort try to find the MUI + } +} + +assert.throws( + () => { require('../fixtures/module-loading-error.node'); }, + (e) => { + if (localeOk && !errorMessages.some((msg) => e.message.includes(msg))) + return false; + return e.name === 'Error'; + } +); + +const re = /^The "id" argument must be of type string\. Received /; +[1, false, null, undefined, {}].forEach((value) => { + assert.throws( + () => { require(value); }, + { + name: 'TypeError', + code: 'ERR_INVALID_ARG_TYPE', + message: re + }); +}); + + +assert.throws( + () => { require(''); }, + { + name: 'TypeError', + code: 'ERR_INVALID_ARG_VALUE', + message: 'The argument \'id\' must be a non-empty string. Received \'\'' + }); + +// Folder read operation succeeds in AIX. +// For libuv change, see https://github.com/libuv/libuv/pull/2025. +// https://github.com/nodejs/node/pull/48477#issuecomment-1604586650 +assert.throws( + () => { require('../fixtures/packages/is-dir'); }, + common.isAIX ? { code: 'ERR_INVALID_PACKAGE_CONFIG' } : { + code: 'MODULE_NOT_FOUND', + message: /Cannot find module '\.\.\/fixtures\/packages\/is-dir'/ + } +); diff --git a/test/js/node/test/parallel/test-module-main-fail.js b/test/js/node/test/parallel/test-module-main-fail.js new file mode 100644 index 0000000000..3b0ef4d2d5 --- /dev/null +++ b/test/js/node/test/parallel/test-module-main-fail.js @@ -0,0 +1,22 @@ +'use strict'; +require('../common'); +const assert = require('assert'); +const { execFileSync } = require('child_process'); + +const entryPoints = ['iDoNotExist', 'iDoNotExist.js', 'iDoNotExist.mjs']; +const node = process.argv[0]; + +for (const entryPoint of entryPoints) { + try { + execFileSync(node, [entryPoint], { stdio: 'pipe' }); + } catch (e) { + const error = e.toString(); + // assert.match(error, /MODULE_NOT_FOUND/); + // assert.match(error, /Cannot find module/); + assert.match(error, /not found/); + assert(error.includes(entryPoint)); + continue; + } + assert.fail('Executing node with inexistent entry point should ' + + `fail. Entry point: ${entryPoint}`); +} diff --git a/test/js/node/test/parallel/test-module-wrap.js b/test/js/node/test/parallel/test-module-wrap.js new file mode 100644 index 0000000000..367307e4a7 --- /dev/null +++ b/test/js/node/test/parallel/test-module-wrap.js @@ -0,0 +1,9 @@ +'use strict'; +require('../common'); +const fixtures = require('../common/fixtures'); +const { execFileSync } = require('child_process'); + +const cjsModuleWrapTest = fixtures.path('cjs-module-wrap.js'); +const node = process.execPath; + +execFileSync(node, [cjsModuleWrapTest], { stdio: 'pipe' }); diff --git a/test/js/node/test/parallel/test-module-wrapper.js b/test/js/node/test/parallel/test-module-wrapper.js new file mode 100644 index 0000000000..39e6d734f4 --- /dev/null +++ b/test/js/node/test/parallel/test-module-wrapper.js @@ -0,0 +1,9 @@ +'use strict'; +require('../common'); +const fixtures = require('../common/fixtures'); +const { execFileSync } = require('child_process'); + +const cjsModuleWrapTest = fixtures.path('cjs-module-wrapper.js'); +const node = process.execPath; + +execFileSync(node, [cjsModuleWrapTest], { stdio: 'pipe' }); diff --git a/test/js/node/test/parallel/test-require-invalid-main-no-exports.js b/test/js/node/test/parallel/test-require-invalid-main-no-exports.js new file mode 100644 index 0000000000..9be5c01054 --- /dev/null +++ b/test/js/node/test/parallel/test-require-invalid-main-no-exports.js @@ -0,0 +1,21 @@ +'use strict'; + +require('../common'); + +// Test that a nonexistent "main" entry in a package.json that also omits an +// "exports" entry will be ignored if it can be found in node_modules instead +// rather than throwing. +// +// Throwing is perhaps "correct" behavior, but it will break bluebird tests +// as of this writing. + +const assert = require('assert'); +const { spawnSync } = require('child_process'); +const fixtures = require('../common/fixtures'); + +const testFile = fixtures.path('package-main-enoent', 'test.js'); + +const { error, status, stderr } = spawnSync(process.execPath, [testFile]); + +assert.ifError(error); +assert.strictEqual(status, 0, stderr); diff --git a/test/js/node/test/parallel/test-require-node-prefix.js b/test/js/node/test/parallel/test-require-node-prefix.js new file mode 100644 index 0000000000..957cabf13a --- /dev/null +++ b/test/js/node/test/parallel/test-require-node-prefix.js @@ -0,0 +1,42 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); +const fs = require('fs'); + +const errUnknownBuiltinModuleRE = /^No such built-in module: /u; + +// For direct use of require expressions inside of CJS modules, +// all kinds of specifiers should work without issue. +{ + assert.strictEqual(require('fs'), fs); + assert.strictEqual(require('node:fs'), fs); + + assert.throws( + () => require('node:unknown'), + { + code: 'ERR_UNKNOWN_BUILTIN_MODULE', + message: errUnknownBuiltinModuleRE, + }, + ); + + assert.throws( + () => require('node:internal/test/binding'), + { + code: 'ERR_UNKNOWN_BUILTIN_MODULE', + message: errUnknownBuiltinModuleRE, + }, + ); +} + +// `node:`-prefixed `require(...)` calls bypass the require cache: +{ + const fakeModule = {}; + + require.cache.fs = { exports: fakeModule }; + + assert.strictEqual(require('fs'), fakeModule); + assert.strictEqual(require('node:fs'), fs); + + delete require.cache.fs; +}