mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
node:module compatibility pt 1 (#18106)
This commit is contained in:
@@ -2,3 +2,7 @@
|
||||
# https://github.com/oven-sh/bun/issues/16289
|
||||
[test]
|
||||
preload = ["./test/js/node/harness.ts", "./test/preload.ts"]
|
||||
|
||||
[install]
|
||||
# Node.js never auto-installs modules.
|
||||
auto = "disable"
|
||||
|
||||
@@ -262,7 +262,7 @@ async function runTests() {
|
||||
await runTest(title, async () => {
|
||||
const { ok, error, stdout } = await spawnBun(execPath, {
|
||||
cwd: cwd,
|
||||
args: [subcommand, "--config=./bunfig.node-test.toml", absoluteTestPath],
|
||||
args: [subcommand, "--config=" + join(import.meta.dirname, "../bunfig.node-test.toml"), absoluteTestPath],
|
||||
timeout: getNodeParallelTestTimeout(title),
|
||||
env: {
|
||||
FORCE_COLOR: "0",
|
||||
|
||||
@@ -2110,6 +2110,7 @@ static JSValue constructProcessConfigObject(VM& vm, JSObject* processObject)
|
||||
JSC::JSObject* variables = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 2);
|
||||
variables->putDirect(vm, JSC::Identifier::fromString(vm, "v8_enable_i8n_support"_s), JSC::jsNumber(1), 0);
|
||||
variables->putDirect(vm, JSC::Identifier::fromString(vm, "enable_lto"_s), JSC::jsBoolean(false), 0);
|
||||
variables->putDirect(vm, JSC::Identifier::fromString(vm, "node_module_version"_s), JSC::jsNumber(REPORTED_NODEJS_ABI_VERSION), 0);
|
||||
config->putDirect(vm, JSC::Identifier::fromString(vm, "target_defaults"_s), JSC::constructEmptyObject(globalObject), 0);
|
||||
config->putDirect(vm, JSC::Identifier::fromString(vm, "variables"_s), variables, 0);
|
||||
|
||||
|
||||
@@ -384,8 +384,8 @@ JSC_DEFINE_CUSTOM_GETTER(getterParent, (JSC::JSGlobalObject * globalObject, JSC:
|
||||
return JSValue::encode(jsUndefined());
|
||||
}
|
||||
|
||||
if (thisObject->m_overridenParent) {
|
||||
return JSValue::encode(thisObject->m_overridenParent.get());
|
||||
if (thisObject->m_overriddenParent) {
|
||||
return JSValue::encode(thisObject->m_overriddenParent.get());
|
||||
}
|
||||
|
||||
if (thisObject->m_parent) {
|
||||
@@ -400,7 +400,7 @@ JSC_DEFINE_CUSTOM_GETTER(getterParent, (JSC::JSGlobalObject * globalObject, JSC:
|
||||
auto id = idValue->value(globalObject);
|
||||
auto idStr = Bun::toString(id);
|
||||
if (Bun__isBunMain(globalObject, &idStr)) {
|
||||
thisObject->m_overridenParent.set(globalObject->vm(), thisObject, jsNull());
|
||||
thisObject->m_overriddenParent.set(globalObject->vm(), thisObject, jsNull());
|
||||
return JSValue::encode(jsNull());
|
||||
}
|
||||
}
|
||||
@@ -494,10 +494,10 @@ JSC_DEFINE_CUSTOM_SETTER(setterParent,
|
||||
|
||||
if (auto* parent = jsDynamicCast<JSCommonJSModule*>(decodedValue)) {
|
||||
thisObject->m_parent = parent;
|
||||
thisObject->m_overridenParent.clear();
|
||||
thisObject->m_overriddenParent.clear();
|
||||
} else {
|
||||
thisObject->m_parent = {};
|
||||
thisObject->m_overridenParent.set(globalObject->vm(), thisObject, JSValue::decode(value));
|
||||
thisObject->m_overriddenParent.set(globalObject->vm(), thisObject, JSValue::decode(value));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -726,10 +726,10 @@ JSCommonJSModule* JSCommonJSModule::create(
|
||||
if (auto* parentModule = jsDynamicCast<JSCommonJSModule*>(parent)) {
|
||||
out->m_parent = JSC::Weak<JSCommonJSModule>(parentModule);
|
||||
} else {
|
||||
out->m_overridenParent.set(vm, out, parent);
|
||||
out->m_overriddenParent.set(vm, out, parent);
|
||||
}
|
||||
} else if (parent) {
|
||||
out->m_overridenParent.set(vm, out, parent);
|
||||
out->m_overriddenParent.set(vm, out, parent);
|
||||
}
|
||||
|
||||
return out;
|
||||
@@ -1022,7 +1022,7 @@ void JSCommonJSModule::visitChildrenImpl(JSCell* cell, Visitor& visitor)
|
||||
visitor.appendHidden(thisObject->m_filename);
|
||||
visitor.appendHidden(thisObject->m_dirname);
|
||||
visitor.appendHidden(thisObject->m_paths);
|
||||
visitor.appendHidden(thisObject->m_overridenParent);
|
||||
visitor.appendHidden(thisObject->m_overriddenParent);
|
||||
}
|
||||
|
||||
DEFINE_VISIT_CHILDREN(JSCommonJSModule);
|
||||
@@ -1061,8 +1061,8 @@ void JSCommonJSModule::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer)
|
||||
}
|
||||
}
|
||||
|
||||
if (thisObject->m_overridenParent) {
|
||||
JSValue overridenParent = thisObject->m_overridenParent.get();
|
||||
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());
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
//
|
||||
// module.parent = parent;
|
||||
//
|
||||
mutable JSC::WriteBarrier<Unknown> m_overridenParent;
|
||||
mutable JSC::WriteBarrier<Unknown> m_overriddenParent;
|
||||
|
||||
// Not visited by the GC.
|
||||
// When the module is assigned a JSCommonJSModule parent, it is assigned to this field.
|
||||
|
||||
8
src/bun.js/bindings/NodeModuleModule.bind.ts
Normal file
8
src/bun.js/bindings/NodeModuleModule.bind.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { fn, t } from "bindgen";
|
||||
|
||||
export const _stat = fn({
|
||||
args: {
|
||||
str: t.UTF8String,
|
||||
},
|
||||
ret: t.i32,
|
||||
});
|
||||
@@ -64,3 +64,12 @@ fn findPathInner(
|
||||
);
|
||||
return errorable.unwrap() catch null;
|
||||
}
|
||||
|
||||
pub fn _stat(path: []const u8) i32 {
|
||||
const exists = bun.sys.existsAtType(.cwd(), path).unwrap() catch
|
||||
return -1; // Returns a negative integer for any other kind of strings.
|
||||
return switch (exists) {
|
||||
.file => 0, // Returns 0 for files.
|
||||
.directory => 1, // Returns 1 for directories.
|
||||
};
|
||||
}
|
||||
|
||||
@@ -86,9 +86,16 @@ namespace Bun {
|
||||
bool isBuiltinModule(const String& namePossiblyWithNodePrefix)
|
||||
{
|
||||
String name = namePossiblyWithNodePrefix;
|
||||
if (name.startsWith("node:"_s))
|
||||
if (name.startsWith("node:"_s)) {
|
||||
name = name.substringSharingImpl(5);
|
||||
|
||||
// bun doesn't have `node:test` as of writing, but this makes sure that
|
||||
// `node:module` is compatible (`test/parallel/test-module-isBuiltin.js`)
|
||||
if (name == "test"_s) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& builtinModule : builtinModuleNamesSortedLength) {
|
||||
if (name == builtinModule)
|
||||
return true;
|
||||
|
||||
@@ -1786,6 +1786,24 @@ pub const ModuleLoader = struct {
|
||||
};
|
||||
}
|
||||
|
||||
if (parse_result.empty) {
|
||||
const was_cjs = (loader == .js or loader == .ts) and brk: {
|
||||
const ext = std.fs.path.extension(parse_result.source.path.text);
|
||||
break :brk strings.eqlComptime(ext, ".cjs") or strings.eqlComptime(ext, ".cts");
|
||||
};
|
||||
if (was_cjs) {
|
||||
return .{
|
||||
.allocator = null,
|
||||
.source_code = bun.String.static("(function(){})"),
|
||||
.specifier = input_specifier,
|
||||
.source_url = input_specifier.createIfDifferent(path.text),
|
||||
.is_commonjs_module = true,
|
||||
.hash = 0,
|
||||
.tag = .javascript,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (cache.entry) |*entry| {
|
||||
jsc_vm.source_mappings.putMappings(parse_result.source, .{
|
||||
.list = .{ .items = @constCast(entry.sourcemap), .capacity = entry.sourcemap.len },
|
||||
|
||||
@@ -1,23 +1,21 @@
|
||||
#include "root.h"
|
||||
#include "headers-handwritten.h"
|
||||
#include "NodeModuleModule.h"
|
||||
|
||||
#include <JavaScriptCore/JSCInlines.h>
|
||||
|
||||
#include <JavaScriptCore/VM.h>
|
||||
|
||||
#include <JavaScriptCore/JSString.h>
|
||||
|
||||
#include "headers-handwritten.h"
|
||||
#include <JavaScriptCore/FunctionPrototype.h>
|
||||
#include <JavaScriptCore/LazyPropertyInlines.h>
|
||||
#include <JavaScriptCore/VMTrapsInlines.h>
|
||||
|
||||
#include "PathInlines.h"
|
||||
#include "ZigGlobalObject.h"
|
||||
#include "headers.h"
|
||||
#include <JavaScriptCore/FunctionPrototype.h>
|
||||
|
||||
#include "NodeModuleModule.h"
|
||||
|
||||
#include "ErrorCode.h"
|
||||
#include <JavaScriptCore/LazyPropertyInlines.h>
|
||||
#include <JavaScriptCore/VMTrapsInlines.h>
|
||||
|
||||
#include "GeneratedNodeModuleModule.h"
|
||||
|
||||
namespace Bun {
|
||||
|
||||
using namespace JSC;
|
||||
@@ -237,20 +235,22 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionNodeModuleCreateRequire,
|
||||
"createRequire() requires at least one argument"_s);
|
||||
}
|
||||
|
||||
auto val = callFrame->uncheckedArgument(0).toWTFString(globalObject);
|
||||
auto argument = callFrame->uncheckedArgument(0);
|
||||
auto val = argument.toWTFString(globalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
|
||||
if (val.startsWith("file://"_s)) {
|
||||
if (!isAbsolutePath(val)) {
|
||||
WTF::URL url(val);
|
||||
if (!url.isValid()) {
|
||||
throwTypeError(globalObject, scope,
|
||||
makeString("createRequire() was given an invalid URL '"_s,
|
||||
url.string(), "'"_s));
|
||||
ERR::INVALID_ARG_VALUE(scope, globalObject,
|
||||
"filename"_s, argument,
|
||||
"must be a file URL object, file URL string, or absolute path string"_s);
|
||||
RELEASE_AND_RETURN(scope, JSValue::encode({}));
|
||||
}
|
||||
if (!url.protocolIsFile()) {
|
||||
throwTypeError(globalObject, scope,
|
||||
"createRequire() does not support non-file URLs"_s);
|
||||
ERR::INVALID_ARG_VALUE(scope, globalObject,
|
||||
"filename"_s, argument,
|
||||
"must be a file URL object, file URL string, or absolute path string"_s);
|
||||
RELEASE_AND_RETURN(scope, JSValue::encode({}));
|
||||
}
|
||||
val = url.fileSystemPath();
|
||||
@@ -708,6 +708,7 @@ _pathCache getPathCacheObject PropertyCallback
|
||||
_preloadModules jsFunctionPreloadModules Function 0
|
||||
_resolveFilename nodeModuleResolveFilename CustomAccessor
|
||||
_resolveLookupPaths jsFunctionResolveLookupPaths Function 2
|
||||
_stat &Generated::NodeModuleModule::js_stat Function 1
|
||||
builtinModules getBuiltinModulesObject PropertyCallback
|
||||
constants getConstantsObject PropertyCallback
|
||||
createRequire jsFunctionNodeModuleCreateRequire Function 1
|
||||
|
||||
@@ -354,7 +354,7 @@ pub const Bunfig = struct {
|
||||
}
|
||||
}
|
||||
|
||||
if (comptime cmd.isNPMRelated() or cmd == .RunCommand or cmd == .AutoCommand) {
|
||||
if (comptime cmd.isNPMRelated() or cmd == .RunCommand or cmd == .AutoCommand or cmd == .TestCommand) {
|
||||
if (json.getObject("install")) |install_obj| {
|
||||
var install: *Api.BunInstall = this.ctx.install orelse brk: {
|
||||
const install = try this.allocator.create(Api.BunInstall);
|
||||
|
||||
@@ -877,6 +877,13 @@ pub const Resolver = struct {
|
||||
// defer r.mutex.unlock();
|
||||
errdefer (r.flushDebugLogs(.fail) catch {});
|
||||
|
||||
// A path with a null byte cannot exist on the filesystem. Continuing
|
||||
// anyways would cause assertion failures.
|
||||
if (bun.strings.indexOfChar(import_path, 0) != null) {
|
||||
r.flushDebugLogs(.fail) catch {};
|
||||
return .{ .not_found = {} };
|
||||
}
|
||||
|
||||
var tmp = r.resolveWithoutSymlinks(source_dir_normalized, import_path, kind, global_cache);
|
||||
|
||||
// Fragments in URLs in CSS imports are technically expected to work
|
||||
@@ -1108,6 +1115,24 @@ pub const Resolver = struct {
|
||||
// Treating these paths as absolute paths on all platforms means Windows
|
||||
// users will not be able to accidentally make use of these paths.
|
||||
if (std.fs.path.isAbsolute(import_path)) {
|
||||
// Collapse relative directory specifiers if they exist. Extremely
|
||||
// loose check to avoid always doing this copy, but avoid spending
|
||||
// too much time on the check.
|
||||
if (bun.strings.indexOf(import_path, "..") != null) {
|
||||
const platform = bun.path.Platform.auto;
|
||||
const ends_with_dir = platform.isSeparator(import_path[import_path.len - 1]) or
|
||||
(import_path.len > 3 and
|
||||
platform.isSeparator(import_path[import_path.len - 3]) and
|
||||
import_path[import_path.len - 2] == '.' and
|
||||
import_path[import_path.len - 1] == '.');
|
||||
const buf = bufs(.relative_abs_path);
|
||||
import_path = r.fs.absBuf(&.{import_path}, buf);
|
||||
if (ends_with_dir) {
|
||||
buf[import_path.len] = platform.separator();
|
||||
import_path.len += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (r.debug_logs) |*debug| {
|
||||
debug.addNoteFmt("The import \"{s}\" is being treated as an absolute path", .{import_path});
|
||||
}
|
||||
@@ -3380,89 +3405,65 @@ pub const Resolver = struct {
|
||||
|
||||
const in_str = try argument.toBunString(globalThis);
|
||||
defer in_str.deref();
|
||||
const r = &globalThis.bunVM().transpiler.resolver;
|
||||
return nodeModulePathsJSValue(r, in_str, globalThis);
|
||||
return nodeModulePathsJSValue(in_str, globalThis);
|
||||
}
|
||||
|
||||
pub export fn Resolver__propForRequireMainPaths(globalThis: *bun.JSC.JSGlobalObject) callconv(.C) JSC.JSValue {
|
||||
bun.JSC.markBinding(@src());
|
||||
|
||||
const in_str = bun.String.init(".");
|
||||
const r = &globalThis.bunVM().transpiler.resolver;
|
||||
return nodeModulePathsJSValue(r, in_str, globalThis);
|
||||
return nodeModulePathsJSValue(in_str, globalThis);
|
||||
}
|
||||
|
||||
pub fn nodeModulePathsJSValue(
|
||||
r: *ThisResolver,
|
||||
in_str: bun.String,
|
||||
globalObject: *bun.JSC.JSGlobalObject,
|
||||
) bun.JSC.JSValue {
|
||||
var list = std.ArrayList(bun.String).init(bun.default_allocator);
|
||||
defer list.deinit();
|
||||
|
||||
const sliced = in_str.toUTF8(bun.default_allocator);
|
||||
defer sliced.deinit();
|
||||
|
||||
const str = brk: {
|
||||
if (std.fs.path.isAbsolute(sliced.slice())) {
|
||||
if (comptime Environment.isWindows) {
|
||||
const dir_path_buf = bufs(.node_modules_paths_buf);
|
||||
var normalizer = bun.path.PosixToWinNormalizer{};
|
||||
const normalized = normalizer.resolveCWD(sliced.slice()) catch {
|
||||
@panic("Failed to get cwd for _nodeModulesPaths");
|
||||
};
|
||||
break :brk bun.path.normalizeBuf(normalized, dir_path_buf, .windows);
|
||||
}
|
||||
break :brk sliced.slice();
|
||||
}
|
||||
const dir_path_buf = bufs(.node_modules_paths_buf);
|
||||
break :brk bun.path.joinStringBuf(dir_path_buf, &[_]string{ r.fs.top_level_dir, sliced.slice() }, .auto);
|
||||
};
|
||||
pub fn nodeModulePathsJSValue(in_str: bun.String, globalObject: *bun.JSC.JSGlobalObject) bun.JSC.JSValue {
|
||||
var arena = std.heap.ArenaAllocator.init(bun.default_allocator);
|
||||
defer arena.deinit();
|
||||
var stack_fallback_allocator = std.heap.stackFallback(1024, arena.allocator());
|
||||
const alloc = stack_fallback_allocator.get();
|
||||
|
||||
if (r.readDirInfo(str) catch null) |result| {
|
||||
var dir_info = result;
|
||||
var list = std.ArrayList(bun.String).init(alloc);
|
||||
defer list.deinit();
|
||||
|
||||
while (true) {
|
||||
const path_without_trailing_slash = strings.withoutTrailingSlash(dir_info.abs_path);
|
||||
const path_parts = brk: {
|
||||
if (path_without_trailing_slash.len == 1 and path_without_trailing_slash[0] == '/') {
|
||||
break :brk [2]string{ "", std.fs.path.sep_str ++ "node_modules" };
|
||||
}
|
||||
const sliced = in_str.toUTF8(bun.default_allocator);
|
||||
defer sliced.deinit();
|
||||
const buf = bufs(.node_modules_paths_buf);
|
||||
|
||||
break :brk [2]string{ path_without_trailing_slash, std.fs.path.sep_str ++ "node_modules" };
|
||||
const full_path = bun.path.joinAbsStringBuf(
|
||||
bun.fs.FileSystem.instance.top_level_dir,
|
||||
buf,
|
||||
&.{sliced.slice()},
|
||||
.auto,
|
||||
);
|
||||
const root_index = switch (bun.Environment.os) {
|
||||
.windows => bun.path.windowsFilesystemRoot(full_path).len,
|
||||
else => 1,
|
||||
};
|
||||
const nodemodules_path = bun.strings.concat(alloc, &path_parts) catch unreachable;
|
||||
bun.path.posixToPlatformInPlace(u8, nodemodules_path);
|
||||
list.append(bun.String.createUTF8(nodemodules_path)) catch unreachable;
|
||||
dir_info = (r.readDirInfo(std.fs.path.dirname(path_without_trailing_slash) orelse break) catch null) orelse break;
|
||||
}
|
||||
} else {
|
||||
// does not exist
|
||||
const full_path = std.fs.path.resolve(r.allocator, &[1][]const u8{str}) catch unreachable;
|
||||
var path = strings.withoutTrailingSlash(full_path);
|
||||
while (true) {
|
||||
const path_without_trailing_slash = strings.withoutTrailingSlash(path);
|
||||
var root_path: []const u8 = full_path[0..root_index];
|
||||
if (full_path.len > root_path.len) {
|
||||
var it = std.mem.splitBackwardsScalar(u8, full_path[root_index..], std.fs.path.sep);
|
||||
while (it.next()) |part| {
|
||||
if (strings.eqlComptime(part, "node_modules"))
|
||||
continue;
|
||||
|
||||
list.append(
|
||||
bun.String.createUTF8(
|
||||
bun.strings.concat(
|
||||
alloc,
|
||||
&[_]string{
|
||||
path_without_trailing_slash,
|
||||
std.fs.path.sep_str ++ "node_modules",
|
||||
list.append(bun.String.createFormat(
|
||||
"{s}{s}" ++ std.fs.path.sep_str ++ "node_modules",
|
||||
.{
|
||||
root_path,
|
||||
it.buffer[0 .. (if (it.index) |i| i + 1 else 0) + part.len],
|
||||
},
|
||||
) catch unreachable,
|
||||
),
|
||||
) catch unreachable;
|
||||
) catch bun.outOfMemory()) catch bun.outOfMemory();
|
||||
}
|
||||
}
|
||||
|
||||
path = path[0 .. strings.lastIndexOfChar(path, std.fs.path.sep) orelse break];
|
||||
}
|
||||
while (root_path.len > 0 and bun.path.Platform.auto.isSeparator(root_path[root_path.len - 1])) {
|
||||
root_path.len -= 1;
|
||||
}
|
||||
|
||||
list.append(bun.String.createFormat(
|
||||
"{s}" ++ std.fs.path.sep_str ++ "node_modules",
|
||||
.{root_path},
|
||||
) catch bun.outOfMemory()) catch bun.outOfMemory();
|
||||
|
||||
return bun.String.toJSArray(globalObject, list.items);
|
||||
}
|
||||
|
||||
|
||||
@@ -3367,7 +3367,7 @@ pub fn existsAtType(fd: bun.FileDescriptor, subpath: anytype) Maybe(ExistsAtType
|
||||
if (std.meta.sentinel(@TypeOf(subpath)) == null) {
|
||||
const path_buf = bun.PathBufferPool.get();
|
||||
defer bun.PathBufferPool.put(path_buf);
|
||||
@memcpy(path_buf, subpath);
|
||||
@memcpy(path_buf[0..subpath.len], subpath);
|
||||
path_buf[subpath.len] = 0;
|
||||
const slice: [:0]const u8 = @ptrCast(path_buf);
|
||||
return existsAtType(fd, slice);
|
||||
|
||||
@@ -308,6 +308,7 @@ it("process.config", () => {
|
||||
expect(process.config).toEqual({
|
||||
variables: {
|
||||
enable_lto: false,
|
||||
node_module_version: expect.any(Number),
|
||||
v8_enable_i8n_support: 1,
|
||||
},
|
||||
target_defaults: {},
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
import { spawn } from "child_process";
|
||||
|
||||
const localDir = path.resolve(import.meta.dirname, "./parallel");
|
||||
const upstreamDir = path.resolve(import.meta.dirname, "../../../node.js/upstream/test/parallel");
|
||||
|
||||
const localFiles = fs.readdirSync(localDir);
|
||||
const upstreamFiles = fs.readdirSync(upstreamDir);
|
||||
|
||||
const newFiles = upstreamFiles.filter((file) => !localFiles.includes(file));
|
||||
|
||||
process.on('SIGTERM', () => {
|
||||
console.log("SIGTERM received");
|
||||
});
|
||||
process.on('SIGINT', () => {
|
||||
console.log("SIGINT received");
|
||||
});
|
||||
|
||||
const stdin = process.stdin;
|
||||
if (stdin.isTTY) {
|
||||
stdin.setRawMode(true);
|
||||
stdin.on('data', (data) => {
|
||||
if (data[0] === 0x03) {
|
||||
stdin.setRawMode(false);
|
||||
console.log("Cancelled");
|
||||
process.exit(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
process.on('exit', () => {
|
||||
if (stdin.isTTY) {
|
||||
stdin.setRawMode(false);
|
||||
}
|
||||
});
|
||||
|
||||
for (const file of newFiles) {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
// Run with a timeout of 5 seconds
|
||||
const proc = spawn("bun-debug", ["run", path.join(upstreamDir, file)], {
|
||||
timeout: 5000,
|
||||
stdio: "inherit",
|
||||
env: {
|
||||
...process.env,
|
||||
BUN_DEBUG_QUIET_LOGS: "1",
|
||||
},
|
||||
});
|
||||
|
||||
proc.on("error", (err) => {
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
proc.on("exit", (code) => {
|
||||
if (code === 0) {
|
||||
console.log(`New Pass: ${file}`);
|
||||
fs.appendFileSync("new-passes.txt", file + "\n");
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -5,10 +5,10 @@ const dgram = require('dgram');
|
||||
const dns = require('dns');
|
||||
|
||||
if (typeof Bun !== 'undefined') {
|
||||
if (process.platform === 'win32' && require('harness').isCI) {
|
||||
if (process.platform === 'win32' && require('../../../../harness').isCI) {
|
||||
// TODO(@heimskr): This test mysteriously takes forever in Windows in CI
|
||||
// possibly due to UDP keeping the event loop alive longer than it should.
|
||||
process.exit(0);
|
||||
common.skip('Windows CI is flaky');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
32
test/js/node/test/parallel/test-module-create-require.js
Normal file
32
test/js/node/test/parallel/test-module-create-require.js
Normal file
@@ -0,0 +1,32 @@
|
||||
'use strict';
|
||||
|
||||
require('../common');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const assert = require('assert');
|
||||
|
||||
const { createRequire } = require('module');
|
||||
|
||||
const u = fixtures.fileURL('fake.js');
|
||||
|
||||
const reqToo = createRequire(u);
|
||||
assert.deepStrictEqual(reqToo('./experimental'), { ofLife: 42 });
|
||||
|
||||
assert.throws(() => {
|
||||
createRequire('https://github.com/nodejs/node/pull/27405/');
|
||||
}, {
|
||||
code: 'ERR_INVALID_ARG_VALUE'
|
||||
});
|
||||
|
||||
assert.throws(() => {
|
||||
createRequire('../');
|
||||
}, {
|
||||
code: 'ERR_INVALID_ARG_VALUE'
|
||||
});
|
||||
|
||||
assert.throws(() => {
|
||||
createRequire({});
|
||||
}, {
|
||||
code: 'ERR_INVALID_ARG_VALUE',
|
||||
message: 'The argument \'filename\' must be a file URL object, file URL ' +
|
||||
'string, or absolute path string. Received {}'
|
||||
});
|
||||
16
test/js/node/test/parallel/test-module-isBuiltin.js
Normal file
16
test/js/node/test/parallel/test-module-isBuiltin.js
Normal file
@@ -0,0 +1,16 @@
|
||||
'use strict';
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
const { isBuiltin } = require('module');
|
||||
|
||||
// Includes modules in lib/ (even deprecated ones)
|
||||
assert(isBuiltin('http'));
|
||||
assert(isBuiltin('sys'));
|
||||
assert(isBuiltin('node:fs'));
|
||||
assert(isBuiltin('node:test'));
|
||||
|
||||
// Does not include internal modules
|
||||
assert(!isBuiltin('internal/errors'));
|
||||
assert(!isBuiltin('test'));
|
||||
assert(!isBuiltin(''));
|
||||
assert(!isBuiltin(undefined));
|
||||
10
test/js/node/test/parallel/test-module-loading-deprecated.js
Normal file
10
test/js/node/test/parallel/test-module-loading-deprecated.js
Normal file
@@ -0,0 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
// common.expectWarning('DeprecationWarning', {
|
||||
// DEP0128: /^Invalid 'main' field in '.+main[/\\]package\.json' of 'doesnotexist\.js'\..+module author/
|
||||
// });
|
||||
|
||||
assert.strictEqual(require('../fixtures/packages/missing-main').ok, 'ok');
|
||||
127
test/js/node/test/parallel/test-module-nodemodulepaths.js
Normal file
127
test/js/node/test/parallel/test-module-nodemodulepaths.js
Normal file
@@ -0,0 +1,127 @@
|
||||
// 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 _module = require('module');
|
||||
|
||||
const cases = {
|
||||
'WIN': [{
|
||||
file: 'C:\\Users\\hefangshi\\AppData\\Roaming\
|
||||
\\npm\\node_modules\\npm\\node_modules\\minimatch',
|
||||
expect: [
|
||||
'C:\\Users\\hefangshi\\AppData\\Roaming\
|
||||
\\npm\\node_modules\\npm\\node_modules\\minimatch\\node_modules',
|
||||
'C:\\Users\\hefangshi\\AppData\\Roaming\
|
||||
\\npm\\node_modules\\npm\\node_modules',
|
||||
'C:\\Users\\hefangshi\\AppData\\Roaming\\npm\\node_modules',
|
||||
'C:\\Users\\hefangshi\\AppData\\Roaming\\node_modules',
|
||||
'C:\\Users\\hefangshi\\AppData\\node_modules',
|
||||
'C:\\Users\\hefangshi\\node_modules',
|
||||
'C:\\Users\\node_modules',
|
||||
'C:\\node_modules',
|
||||
]
|
||||
}, {
|
||||
file: 'C:\\Users\\Rocko Artischocko\\node_stuff\\foo',
|
||||
expect: [
|
||||
'C:\\Users\\Rocko Artischocko\\node_stuff\\foo\\node_modules',
|
||||
'C:\\Users\\Rocko Artischocko\\node_stuff\\node_modules',
|
||||
'C:\\Users\\Rocko Artischocko\\node_modules',
|
||||
'C:\\Users\\node_modules',
|
||||
'C:\\node_modules',
|
||||
]
|
||||
}, {
|
||||
file: 'C:\\Users\\Rocko Artischocko\\node_stuff\\foo_node_modules',
|
||||
expect: [
|
||||
'C:\\Users\\Rocko \
|
||||
Artischocko\\node_stuff\\foo_node_modules\\node_modules',
|
||||
'C:\\Users\\Rocko Artischocko\\node_stuff\\node_modules',
|
||||
'C:\\Users\\Rocko Artischocko\\node_modules',
|
||||
'C:\\Users\\node_modules',
|
||||
'C:\\node_modules',
|
||||
]
|
||||
}, {
|
||||
file: 'C:\\node_modules',
|
||||
expect: [
|
||||
'C:\\node_modules',
|
||||
]
|
||||
}, {
|
||||
file: 'C:\\',
|
||||
expect: [
|
||||
'C:\\node_modules',
|
||||
]
|
||||
}],
|
||||
'POSIX': [{
|
||||
file: '/usr/lib/node_modules/npm/node_modules/\
|
||||
node-gyp/node_modules/glob/node_modules/minimatch',
|
||||
expect: [
|
||||
'/usr/lib/node_modules/npm/node_modules/\
|
||||
node-gyp/node_modules/glob/node_modules/minimatch/node_modules',
|
||||
'/usr/lib/node_modules/npm/node_modules/\
|
||||
node-gyp/node_modules/glob/node_modules',
|
||||
'/usr/lib/node_modules/npm/node_modules/node-gyp/node_modules',
|
||||
'/usr/lib/node_modules/npm/node_modules',
|
||||
'/usr/lib/node_modules',
|
||||
'/usr/node_modules',
|
||||
'/node_modules',
|
||||
]
|
||||
}, {
|
||||
file: '/usr/test/lib/node_modules/npm/foo',
|
||||
expect: [
|
||||
'/usr/test/lib/node_modules/npm/foo/node_modules',
|
||||
'/usr/test/lib/node_modules/npm/node_modules',
|
||||
'/usr/test/lib/node_modules',
|
||||
'/usr/test/node_modules',
|
||||
'/usr/node_modules',
|
||||
'/node_modules',
|
||||
]
|
||||
}, {
|
||||
file: '/usr/test/lib/node_modules/npm/foo_node_modules',
|
||||
expect: [
|
||||
'/usr/test/lib/node_modules/npm/foo_node_modules/node_modules',
|
||||
'/usr/test/lib/node_modules/npm/node_modules',
|
||||
'/usr/test/lib/node_modules',
|
||||
'/usr/test/node_modules',
|
||||
'/usr/node_modules',
|
||||
'/node_modules',
|
||||
]
|
||||
}, {
|
||||
file: '/node_modules',
|
||||
expect: [
|
||||
'/node_modules',
|
||||
]
|
||||
}, {
|
||||
file: '/',
|
||||
expect: [
|
||||
'/node_modules',
|
||||
]
|
||||
}]
|
||||
};
|
||||
|
||||
const platformCases = common.isWindows ? cases.WIN : cases.POSIX;
|
||||
platformCases.forEach((c) => {
|
||||
const paths = _module._nodeModulePaths(c.file);
|
||||
assert.deepStrictEqual(
|
||||
c.expect, paths,
|
||||
`case ${c.file} failed, actual paths is ${JSON.stringify(paths)}`);
|
||||
});
|
||||
14
test/js/node/test/parallel/test-module-parent-deprecation.js
Normal file
14
test/js/node/test/parallel/test-module-parent-deprecation.js
Normal file
@@ -0,0 +1,14 @@
|
||||
// Flags: --pending-deprecation
|
||||
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
// common.expectWarning(
|
||||
// 'DeprecationWarning',
|
||||
// 'module.parent is deprecated due to accuracy issues. Please use ' +
|
||||
// 'require.main to find program entry point instead.',
|
||||
// 'DEP0144'
|
||||
// );
|
||||
|
||||
assert.strictEqual(module.parent, null);
|
||||
@@ -0,0 +1,13 @@
|
||||
// Flags: --pending-deprecation
|
||||
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
|
||||
// common.expectWarning(
|
||||
// 'DeprecationWarning',
|
||||
// 'module.parent is deprecated due to accuracy issues. Please use ' +
|
||||
// 'require.main to find program entry point instead.',
|
||||
// 'DEP0144'
|
||||
// );
|
||||
|
||||
module.parent = undefined;
|
||||
24
test/js/node/test/parallel/test-module-stat.js
Normal file
24
test/js/node/test/parallel/test-module-stat.js
Normal file
@@ -0,0 +1,24 @@
|
||||
'use strict';
|
||||
require('../common');
|
||||
|
||||
// This tests Module._stat.
|
||||
|
||||
const Module = require('module');
|
||||
const fs = require('fs');
|
||||
const tmpdir = require('../common/tmpdir');
|
||||
const { ok, strictEqual } = require('assert');
|
||||
|
||||
const directory = tmpdir.resolve('directory');
|
||||
const doesNotExist = tmpdir.resolve('does-not-exist');
|
||||
const file = tmpdir.resolve('file.js');
|
||||
|
||||
tmpdir.refresh();
|
||||
fs.writeFileSync(file, "module.exports = { a: 'b' }");
|
||||
fs.mkdirSync(directory);
|
||||
|
||||
strictEqual(Module._stat(directory), 1); // Returns 1 for directories.
|
||||
strictEqual(Module._stat(file), 0); // Returns 0 for files.
|
||||
ok(Module._stat(doesNotExist) < 0); // Returns a negative integer for any other kind of strings.
|
||||
|
||||
// TODO(RaisinTen): Add tests that make sure that Module._stat() does not crash when called
|
||||
// with a non-string data type. It crashes currently.
|
||||
10
test/js/node/test/parallel/test-module-version.js
Normal file
10
test/js/node/test/parallel/test-module-version.js
Normal file
@@ -0,0 +1,10 @@
|
||||
'use strict';
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
// check for existence
|
||||
assert(Object.hasOwn(process.config.variables, 'node_module_version'));
|
||||
|
||||
// Ensure that `node_module_version` is an Integer > 0
|
||||
assert(Number.isInteger(process.config.variables.node_module_version));
|
||||
assert(process.config.variables.node_module_version > 0);
|
||||
34
test/js/node/test/parallel/test-require-enoent-dir.js
Normal file
34
test/js/node/test/parallel/test-require-enoent-dir.js
Normal file
@@ -0,0 +1,34 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const tmpdir = require('../common/tmpdir');
|
||||
const assert = require('assert');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
tmpdir.refresh();
|
||||
|
||||
const fooPath = tmpdir.resolve('foo.cjs');
|
||||
fs.writeFileSync(fooPath, '');
|
||||
|
||||
const dirPath = tmpdir.resolve('delete_me');
|
||||
fs.mkdirSync(dirPath, {
|
||||
recursive: true,
|
||||
});
|
||||
|
||||
const barPath = path.join(dirPath, 'bar.cjs');
|
||||
fs.writeFileSync(
|
||||
barPath,
|
||||
`
|
||||
module.exports = () => require('../foo.cjs').call()
|
||||
`
|
||||
);
|
||||
|
||||
const foo = require(fooPath);
|
||||
console.log('fooPath', fooPath, foo);
|
||||
const unique = Symbol('unique');
|
||||
foo.call = common.mustCall(() => unique);
|
||||
const bar = require(barPath);
|
||||
|
||||
fs.rmSync(dirPath, { recursive: true });
|
||||
assert.strict.equal(bar(), unique);
|
||||
@@ -0,0 +1,30 @@
|
||||
'use strict';
|
||||
// Fixes regression from v4
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const path = require('path');
|
||||
|
||||
const fixturesRequire = require(
|
||||
fixtures.path('module-extension-over-directory', 'inner'));
|
||||
|
||||
assert.strictEqual(
|
||||
fixturesRequire,
|
||||
require(fixtures.path('module-extension-over-directory', 'inner.js')),
|
||||
'test-require-extension-over-directory failed to import fixture' +
|
||||
' requirements'
|
||||
);
|
||||
|
||||
const fakePath = [
|
||||
fixtures.path('module-extension-over-directory', 'inner'),
|
||||
'fake',
|
||||
'..',
|
||||
].join(path.sep);
|
||||
const fixturesRequireDir = require(fakePath);
|
||||
|
||||
assert.strictEqual(
|
||||
fixturesRequireDir,
|
||||
require(fixtures.path('module-extension-over-directory', 'inner/')),
|
||||
'test-require-extension-over-directory failed to import fixture' +
|
||||
' requirements'
|
||||
);
|
||||
@@ -0,0 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
// Should be an invalid package path.
|
||||
assert.throws(() => require('package.json'),
|
||||
{ code: 'MODULE_NOT_FOUND' }
|
||||
);
|
||||
11
test/js/node/test/parallel/test-require-nul.js
Normal file
11
test/js/node/test/parallel/test-require-nul.js
Normal file
@@ -0,0 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
// Nul bytes should throw, not abort.
|
||||
/* eslint-disable no-control-regex */
|
||||
assert.throws(() => require('\u0000ab'), /'\u0000ab'/);
|
||||
assert.throws(() => require('a\u0000b'), /'a\u0000b'/);
|
||||
assert.throws(() => require('ab\u0000'), /'ab\u0000'/);
|
||||
/* eslint-enable no-control-regex */
|
||||
5
test/js/node/test/tsconfig.json
Normal file
5
test/js/node/test/tsconfig.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": null,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user