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
|
# https://github.com/oven-sh/bun/issues/16289
|
||||||
[test]
|
[test]
|
||||||
preload = ["./test/js/node/harness.ts", "./test/preload.ts"]
|
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 () => {
|
await runTest(title, async () => {
|
||||||
const { ok, error, stdout } = await spawnBun(execPath, {
|
const { ok, error, stdout } = await spawnBun(execPath, {
|
||||||
cwd: cwd,
|
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),
|
timeout: getNodeParallelTestTimeout(title),
|
||||||
env: {
|
env: {
|
||||||
FORCE_COLOR: "0",
|
FORCE_COLOR: "0",
|
||||||
|
|||||||
@@ -2110,6 +2110,7 @@ static JSValue constructProcessConfigObject(VM& vm, JSObject* processObject)
|
|||||||
JSC::JSObject* variables = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 2);
|
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, "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, "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, "target_defaults"_s), JSC::constructEmptyObject(globalObject), 0);
|
||||||
config->putDirect(vm, JSC::Identifier::fromString(vm, "variables"_s), variables, 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());
|
return JSValue::encode(jsUndefined());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thisObject->m_overridenParent) {
|
if (thisObject->m_overriddenParent) {
|
||||||
return JSValue::encode(thisObject->m_overridenParent.get());
|
return JSValue::encode(thisObject->m_overriddenParent.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thisObject->m_parent) {
|
if (thisObject->m_parent) {
|
||||||
@@ -400,7 +400,7 @@ JSC_DEFINE_CUSTOM_GETTER(getterParent, (JSC::JSGlobalObject * globalObject, JSC:
|
|||||||
auto id = idValue->value(globalObject);
|
auto id = idValue->value(globalObject);
|
||||||
auto idStr = Bun::toString(id);
|
auto idStr = Bun::toString(id);
|
||||||
if (Bun__isBunMain(globalObject, &idStr)) {
|
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());
|
return JSValue::encode(jsNull());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -494,10 +494,10 @@ JSC_DEFINE_CUSTOM_SETTER(setterParent,
|
|||||||
|
|
||||||
if (auto* parent = jsDynamicCast<JSCommonJSModule*>(decodedValue)) {
|
if (auto* parent = jsDynamicCast<JSCommonJSModule*>(decodedValue)) {
|
||||||
thisObject->m_parent = parent;
|
thisObject->m_parent = parent;
|
||||||
thisObject->m_overridenParent.clear();
|
thisObject->m_overriddenParent.clear();
|
||||||
} else {
|
} else {
|
||||||
thisObject->m_parent = {};
|
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;
|
return true;
|
||||||
@@ -726,10 +726,10 @@ JSCommonJSModule* JSCommonJSModule::create(
|
|||||||
if (auto* parentModule = jsDynamicCast<JSCommonJSModule*>(parent)) {
|
if (auto* parentModule = jsDynamicCast<JSCommonJSModule*>(parent)) {
|
||||||
out->m_parent = JSC::Weak<JSCommonJSModule>(parentModule);
|
out->m_parent = JSC::Weak<JSCommonJSModule>(parentModule);
|
||||||
} else {
|
} else {
|
||||||
out->m_overridenParent.set(vm, out, parent);
|
out->m_overriddenParent.set(vm, out, parent);
|
||||||
}
|
}
|
||||||
} else if (parent) {
|
} else if (parent) {
|
||||||
out->m_overridenParent.set(vm, out, parent);
|
out->m_overriddenParent.set(vm, out, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
@@ -1022,7 +1022,7 @@ void JSCommonJSModule::visitChildrenImpl(JSCell* cell, Visitor& visitor)
|
|||||||
visitor.appendHidden(thisObject->m_filename);
|
visitor.appendHidden(thisObject->m_filename);
|
||||||
visitor.appendHidden(thisObject->m_dirname);
|
visitor.appendHidden(thisObject->m_dirname);
|
||||||
visitor.appendHidden(thisObject->m_paths);
|
visitor.appendHidden(thisObject->m_paths);
|
||||||
visitor.appendHidden(thisObject->m_overridenParent);
|
visitor.appendHidden(thisObject->m_overriddenParent);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_VISIT_CHILDREN(JSCommonJSModule);
|
DEFINE_VISIT_CHILDREN(JSCommonJSModule);
|
||||||
@@ -1061,8 +1061,8 @@ void JSCommonJSModule::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thisObject->m_overridenParent) {
|
if (thisObject->m_overriddenParent) {
|
||||||
JSValue overridenParent = thisObject->m_overridenParent.get();
|
JSValue overridenParent = thisObject->m_overriddenParent.get();
|
||||||
if (overridenParent.isCell()) {
|
if (overridenParent.isCell()) {
|
||||||
const Identifier overridenParentIdentifier = Identifier::fromString(vm, "parent"_s);
|
const Identifier overridenParentIdentifier = Identifier::fromString(vm, "parent"_s);
|
||||||
analyzer.analyzePropertyNameEdge(cell, overridenParent.asCell(), overridenParentIdentifier.impl());
|
analyzer.analyzePropertyNameEdge(cell, overridenParent.asCell(), overridenParentIdentifier.impl());
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public:
|
|||||||
//
|
//
|
||||||
// module.parent = parent;
|
// module.parent = parent;
|
||||||
//
|
//
|
||||||
mutable JSC::WriteBarrier<Unknown> m_overridenParent;
|
mutable JSC::WriteBarrier<Unknown> m_overriddenParent;
|
||||||
|
|
||||||
// Not visited by the GC.
|
// Not visited by the GC.
|
||||||
// When the module is assigned a JSCommonJSModule parent, it is assigned to this field.
|
// 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;
|
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)
|
bool isBuiltinModule(const String& namePossiblyWithNodePrefix)
|
||||||
{
|
{
|
||||||
String name = namePossiblyWithNodePrefix;
|
String name = namePossiblyWithNodePrefix;
|
||||||
if (name.startsWith("node:"_s))
|
if (name.startsWith("node:"_s)) {
|
||||||
name = name.substringSharingImpl(5);
|
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) {
|
for (auto& builtinModule : builtinModuleNamesSortedLength) {
|
||||||
if (name == builtinModule)
|
if (name == builtinModule)
|
||||||
return true;
|
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| {
|
if (cache.entry) |*entry| {
|
||||||
jsc_vm.source_mappings.putMappings(parse_result.source, .{
|
jsc_vm.source_mappings.putMappings(parse_result.source, .{
|
||||||
.list = .{ .items = @constCast(entry.sourcemap), .capacity = entry.sourcemap.len },
|
.list = .{ .items = @constCast(entry.sourcemap), .capacity = entry.sourcemap.len },
|
||||||
|
|||||||
@@ -1,23 +1,21 @@
|
|||||||
#include "root.h"
|
#include "root.h"
|
||||||
|
#include "headers-handwritten.h"
|
||||||
|
#include "NodeModuleModule.h"
|
||||||
|
|
||||||
#include <JavaScriptCore/JSCInlines.h>
|
#include <JavaScriptCore/JSCInlines.h>
|
||||||
|
|
||||||
#include <JavaScriptCore/VM.h>
|
#include <JavaScriptCore/VM.h>
|
||||||
|
|
||||||
#include <JavaScriptCore/JSString.h>
|
#include <JavaScriptCore/JSString.h>
|
||||||
|
#include <JavaScriptCore/FunctionPrototype.h>
|
||||||
#include "headers-handwritten.h"
|
#include <JavaScriptCore/LazyPropertyInlines.h>
|
||||||
|
#include <JavaScriptCore/VMTrapsInlines.h>
|
||||||
|
|
||||||
#include "PathInlines.h"
|
#include "PathInlines.h"
|
||||||
#include "ZigGlobalObject.h"
|
#include "ZigGlobalObject.h"
|
||||||
#include "headers.h"
|
#include "headers.h"
|
||||||
#include <JavaScriptCore/FunctionPrototype.h>
|
|
||||||
|
|
||||||
#include "NodeModuleModule.h"
|
|
||||||
|
|
||||||
#include "ErrorCode.h"
|
#include "ErrorCode.h"
|
||||||
#include <JavaScriptCore/LazyPropertyInlines.h>
|
|
||||||
#include <JavaScriptCore/VMTrapsInlines.h>
|
#include "GeneratedNodeModuleModule.h"
|
||||||
|
|
||||||
namespace Bun {
|
namespace Bun {
|
||||||
|
|
||||||
using namespace JSC;
|
using namespace JSC;
|
||||||
@@ -237,20 +235,22 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionNodeModuleCreateRequire,
|
|||||||
"createRequire() requires at least one argument"_s);
|
"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, {});
|
RETURN_IF_EXCEPTION(scope, {});
|
||||||
|
|
||||||
if (val.startsWith("file://"_s)) {
|
if (!isAbsolutePath(val)) {
|
||||||
WTF::URL url(val);
|
WTF::URL url(val);
|
||||||
if (!url.isValid()) {
|
if (!url.isValid()) {
|
||||||
throwTypeError(globalObject, scope,
|
ERR::INVALID_ARG_VALUE(scope, globalObject,
|
||||||
makeString("createRequire() was given an invalid URL '"_s,
|
"filename"_s, argument,
|
||||||
url.string(), "'"_s));
|
"must be a file URL object, file URL string, or absolute path string"_s);
|
||||||
RELEASE_AND_RETURN(scope, JSValue::encode({}));
|
RELEASE_AND_RETURN(scope, JSValue::encode({}));
|
||||||
}
|
}
|
||||||
if (!url.protocolIsFile()) {
|
if (!url.protocolIsFile()) {
|
||||||
throwTypeError(globalObject, scope,
|
ERR::INVALID_ARG_VALUE(scope, globalObject,
|
||||||
"createRequire() does not support non-file URLs"_s);
|
"filename"_s, argument,
|
||||||
|
"must be a file URL object, file URL string, or absolute path string"_s);
|
||||||
RELEASE_AND_RETURN(scope, JSValue::encode({}));
|
RELEASE_AND_RETURN(scope, JSValue::encode({}));
|
||||||
}
|
}
|
||||||
val = url.fileSystemPath();
|
val = url.fileSystemPath();
|
||||||
@@ -708,6 +708,7 @@ _pathCache getPathCacheObject PropertyCallback
|
|||||||
_preloadModules jsFunctionPreloadModules Function 0
|
_preloadModules jsFunctionPreloadModules Function 0
|
||||||
_resolveFilename nodeModuleResolveFilename CustomAccessor
|
_resolveFilename nodeModuleResolveFilename CustomAccessor
|
||||||
_resolveLookupPaths jsFunctionResolveLookupPaths Function 2
|
_resolveLookupPaths jsFunctionResolveLookupPaths Function 2
|
||||||
|
_stat &Generated::NodeModuleModule::js_stat Function 1
|
||||||
builtinModules getBuiltinModulesObject PropertyCallback
|
builtinModules getBuiltinModulesObject PropertyCallback
|
||||||
constants getConstantsObject PropertyCallback
|
constants getConstantsObject PropertyCallback
|
||||||
createRequire jsFunctionNodeModuleCreateRequire Function 1
|
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| {
|
if (json.getObject("install")) |install_obj| {
|
||||||
var install: *Api.BunInstall = this.ctx.install orelse brk: {
|
var install: *Api.BunInstall = this.ctx.install orelse brk: {
|
||||||
const install = try this.allocator.create(Api.BunInstall);
|
const install = try this.allocator.create(Api.BunInstall);
|
||||||
|
|||||||
@@ -877,6 +877,13 @@ pub const Resolver = struct {
|
|||||||
// defer r.mutex.unlock();
|
// defer r.mutex.unlock();
|
||||||
errdefer (r.flushDebugLogs(.fail) catch {});
|
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);
|
var tmp = r.resolveWithoutSymlinks(source_dir_normalized, import_path, kind, global_cache);
|
||||||
|
|
||||||
// Fragments in URLs in CSS imports are technically expected to work
|
// 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
|
// Treating these paths as absolute paths on all platforms means Windows
|
||||||
// users will not be able to accidentally make use of these paths.
|
// users will not be able to accidentally make use of these paths.
|
||||||
if (std.fs.path.isAbsolute(import_path)) {
|
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| {
|
if (r.debug_logs) |*debug| {
|
||||||
debug.addNoteFmt("The import \"{s}\" is being treated as an absolute path", .{import_path});
|
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);
|
const in_str = try argument.toBunString(globalThis);
|
||||||
defer in_str.deref();
|
defer in_str.deref();
|
||||||
const r = &globalThis.bunVM().transpiler.resolver;
|
return nodeModulePathsJSValue(in_str, globalThis);
|
||||||
return nodeModulePathsJSValue(r, in_str, globalThis);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub export fn Resolver__propForRequireMainPaths(globalThis: *bun.JSC.JSGlobalObject) callconv(.C) JSC.JSValue {
|
pub export fn Resolver__propForRequireMainPaths(globalThis: *bun.JSC.JSGlobalObject) callconv(.C) JSC.JSValue {
|
||||||
bun.JSC.markBinding(@src());
|
bun.JSC.markBinding(@src());
|
||||||
|
|
||||||
const in_str = bun.String.init(".");
|
const in_str = bun.String.init(".");
|
||||||
const r = &globalThis.bunVM().transpiler.resolver;
|
return nodeModulePathsJSValue(in_str, globalThis);
|
||||||
return nodeModulePathsJSValue(r, in_str, globalThis);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn nodeModulePathsJSValue(
|
pub fn nodeModulePathsJSValue(in_str: bun.String, globalObject: *bun.JSC.JSGlobalObject) bun.JSC.JSValue {
|
||||||
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);
|
|
||||||
};
|
|
||||||
var arena = std.heap.ArenaAllocator.init(bun.default_allocator);
|
var arena = std.heap.ArenaAllocator.init(bun.default_allocator);
|
||||||
defer arena.deinit();
|
defer arena.deinit();
|
||||||
var stack_fallback_allocator = std.heap.stackFallback(1024, arena.allocator());
|
var stack_fallback_allocator = std.heap.stackFallback(1024, arena.allocator());
|
||||||
const alloc = stack_fallback_allocator.get();
|
const alloc = stack_fallback_allocator.get();
|
||||||
|
|
||||||
if (r.readDirInfo(str) catch null) |result| {
|
var list = std.ArrayList(bun.String).init(alloc);
|
||||||
var dir_info = result;
|
defer list.deinit();
|
||||||
|
|
||||||
while (true) {
|
const sliced = in_str.toUTF8(bun.default_allocator);
|
||||||
const path_without_trailing_slash = strings.withoutTrailingSlash(dir_info.abs_path);
|
defer sliced.deinit();
|
||||||
const path_parts = brk: {
|
const buf = bufs(.node_modules_paths_buf);
|
||||||
if (path_without_trailing_slash.len == 1 and path_without_trailing_slash[0] == '/') {
|
|
||||||
break :brk [2]string{ "", std.fs.path.sep_str ++ "node_modules" };
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
||||||
const nodemodules_path = bun.strings.concat(alloc, &path_parts) catch unreachable;
|
buf,
|
||||||
bun.path.posixToPlatformInPlace(u8, nodemodules_path);
|
&.{sliced.slice()},
|
||||||
list.append(bun.String.createUTF8(nodemodules_path)) catch unreachable;
|
.auto,
|
||||||
dir_info = (r.readDirInfo(std.fs.path.dirname(path_without_trailing_slash) orelse break) catch null) orelse break;
|
);
|
||||||
}
|
const root_index = switch (bun.Environment.os) {
|
||||||
} else {
|
.windows => bun.path.windowsFilesystemRoot(full_path).len,
|
||||||
// does not exist
|
else => 1,
|
||||||
const full_path = std.fs.path.resolve(r.allocator, &[1][]const u8{str}) catch unreachable;
|
};
|
||||||
var path = strings.withoutTrailingSlash(full_path);
|
var root_path: []const u8 = full_path[0..root_index];
|
||||||
while (true) {
|
if (full_path.len > root_path.len) {
|
||||||
const path_without_trailing_slash = strings.withoutTrailingSlash(path);
|
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(
|
list.append(bun.String.createFormat(
|
||||||
bun.String.createUTF8(
|
"{s}{s}" ++ std.fs.path.sep_str ++ "node_modules",
|
||||||
bun.strings.concat(
|
.{
|
||||||
alloc,
|
root_path,
|
||||||
&[_]string{
|
it.buffer[0 .. (if (it.index) |i| i + 1 else 0) + part.len],
|
||||||
path_without_trailing_slash,
|
},
|
||||||
std.fs.path.sep_str ++ "node_modules",
|
) catch bun.outOfMemory()) catch bun.outOfMemory();
|
||||||
},
|
|
||||||
) catch unreachable,
|
|
||||||
),
|
|
||||||
) catch unreachable;
|
|
||||||
|
|
||||||
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);
|
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) {
|
if (std.meta.sentinel(@TypeOf(subpath)) == null) {
|
||||||
const path_buf = bun.PathBufferPool.get();
|
const path_buf = bun.PathBufferPool.get();
|
||||||
defer bun.PathBufferPool.put(path_buf);
|
defer bun.PathBufferPool.put(path_buf);
|
||||||
@memcpy(path_buf, subpath);
|
@memcpy(path_buf[0..subpath.len], subpath);
|
||||||
path_buf[subpath.len] = 0;
|
path_buf[subpath.len] = 0;
|
||||||
const slice: [:0]const u8 = @ptrCast(path_buf);
|
const slice: [:0]const u8 = @ptrCast(path_buf);
|
||||||
return existsAtType(fd, slice);
|
return existsAtType(fd, slice);
|
||||||
|
|||||||
@@ -308,6 +308,7 @@ it("process.config", () => {
|
|||||||
expect(process.config).toEqual({
|
expect(process.config).toEqual({
|
||||||
variables: {
|
variables: {
|
||||||
enable_lto: false,
|
enable_lto: false,
|
||||||
|
node_module_version: expect.any(Number),
|
||||||
v8_enable_i8n_support: 1,
|
v8_enable_i8n_support: 1,
|
||||||
},
|
},
|
||||||
target_defaults: {},
|
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');
|
const dns = require('dns');
|
||||||
|
|
||||||
if (typeof Bun !== 'undefined') {
|
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
|
// TODO(@heimskr): This test mysteriously takes forever in Windows in CI
|
||||||
// possibly due to UDP keeping the event loop alive longer than it should.
|
// 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