aboutsummaryrefslogtreecommitdiff
path: root/src/js/builtins/ImportMetaObject.ts
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/js/builtins/ImportMetaObject.ts214
1 files changed, 86 insertions, 128 deletions
diff --git a/src/js/builtins/ImportMetaObject.ts b/src/js/builtins/ImportMetaObject.ts
index 7fc8b5fe8..934a37881 100644
--- a/src/js/builtins/ImportMetaObject.ts
+++ b/src/js/builtins/ImportMetaObject.ts
@@ -8,9 +8,9 @@ export function loadCJS2ESM(this: ImportMetaObject, resolvedSpecifier: string) {
// we need to explicitly check because state could be $ModuleFetch
// it will throw this error if we do not:
// $throwTypeError("Requested module is already fetched.");
- var entry = loader.registry.$get(key);
+ var entry = loader.registry.$get(key)!;
- if (!entry || !entry.state || entry.state <= $ModuleFetch) {
+ if ((entry?.state ?? 0) <= $ModuleFetch) {
$fulfillModuleSync(key);
entry = loader.registry.$get(key)!;
}
@@ -24,14 +24,14 @@ export function loadCJS2ESM(this: ImportMetaObject, resolvedSpecifier: string) {
// so we just pull it out of the promise here once again
// But, this time we do it a little more carefully because this is a JSC function call and not bun source code
var moduleRecordPromise = loader.parseModule(key, sourceCodeObject);
- var module = entry.module;
- if (!module && moduleRecordPromise && $isPromise(moduleRecordPromise)) {
+ var mod = entry.module;
+ if (moduleRecordPromise && $isPromise(moduleRecordPromise)) {
var reactionsOrResult = $getPromiseInternalField(moduleRecordPromise, $promiseFieldReactionsOrResult);
var flags = $getPromiseInternalField(moduleRecordPromise, $promiseFieldFlags);
var state = flags & $promiseStateMask;
// this branch should never happen, but just to be safe
if (state === $promiseStatePending || (reactionsOrResult && $isPromise(reactionsOrResult))) {
- throw new TypeError(`require() async module "${key}" is unsupported`);
+ throw new TypeError(`require() async module "${key}" is unsupported. use "await import()" instead.`);
} else if (state === $promiseStateRejected) {
if (!reactionsOrResult?.message) {
throw new TypeError(
@@ -43,15 +43,15 @@ export function loadCJS2ESM(this: ImportMetaObject, resolvedSpecifier: string) {
throw reactionsOrResult;
}
- entry.module = module = reactionsOrResult;
- } else if (moduleRecordPromise && !module) {
- entry.module = module = moduleRecordPromise as LoaderModule;
+ entry.module = mod = reactionsOrResult;
+ } else if (moduleRecordPromise && !mod) {
+ entry.module = mod = moduleRecordPromise as LoaderModule;
}
// This is very similar to "requestInstantiate" in ModuleLoader.js in JavaScriptCore.
$setStateToMax(entry, $ModuleLink);
- var dependenciesMap = module.dependenciesMap;
- var requestedModules = loader.requestedModules(module);
+ var dependenciesMap = mod.dependenciesMap;
+ var requestedModules = loader.requestedModules(mod);
var dependencies = $newArrayWithSize<string>(requestedModules.length);
for (var i = 0, length = requestedModules.length; i < length; ++i) {
var depName = requestedModules[i];
@@ -59,6 +59,7 @@ export function loadCJS2ESM(this: ImportMetaObject, resolvedSpecifier: string) {
// we don't need to run the resolver a 2nd time
var depKey = depName[0] === "/" ? depName : loader.resolve(depName, key);
var depEntry = loader.ensureRegistered(depKey);
+
if (depEntry.state < $ModuleLink) {
queue.push(depKey);
}
@@ -81,7 +82,9 @@ export function loadCJS2ESM(this: ImportMetaObject, resolvedSpecifier: string) {
if (linkAndEvaluateResult && $isPromise(linkAndEvaluateResult)) {
// if you use top-level await, or any dependencies use top-level await, then we throw here
// this means the module will still actually load eventually, but that's okay.
- throw new TypeError(`require() async module \"${resolvedSpecifier}\" is unsupported`);
+ throw new TypeError(
+ `require() async module \"${resolvedSpecifier}\" is unsupported. use "await import()" instead.`,
+ );
}
return loader.registry.$get(resolvedSpecifier);
@@ -104,158 +107,113 @@ export function requireESM(this: ImportMetaObject, resolved) {
return;
}
- var commonJS = exports.default;
- var cjs = commonJS?.[$commonJSSymbol];
- if (cjs === 0) {
- return commonJS;
- } else if (cjs && $isCallable(commonJS)) {
- return commonJS();
- }
-
return exports;
}
-export function internalRequire(this: ImportMetaObject, resolved) {
- var cached = $requireMap.$get(resolved);
- const last5 = resolved.substring(resolved.length - 5);
+export function internalRequire(this: ImportMetaObject, id) {
+ var cached = $requireMap.$get(id);
+ const last5 = id.substring(id.length - 5);
if (cached) {
- if (last5 === ".node") {
- return cached.exports;
- }
- return cached;
+ return cached.exports;
}
// TODO: remove this hardcoding
if (last5 === ".json") {
var fs = (globalThis[Symbol.for("_fs")] ||= Bun.fs());
- var exports = JSON.parse(fs.readFileSync(resolved, "utf8"));
- $requireMap.$set(resolved, exports);
+ var exports = JSON.parse(fs.readFileSync(id, "utf8"));
+ $requireMap.$set(id, $createCommonJSModule(id, exports, true));
return exports;
} else if (last5 === ".node") {
- var module = { exports: {} };
- process.dlopen(module, resolved);
- $requireMap.$set(resolved, module);
+ const module = $createCommonJSModule(id, {}, true);
+ process.dlopen(module, id);
+ $requireMap.$set(id, module);
return module.exports;
} else if (last5 === ".toml") {
var fs = (globalThis[Symbol.for("_fs")] ||= Bun.fs());
- var exports = Bun.TOML.parse(fs.readFileSync(resolved, "utf8"));
- $requireMap.$set(resolved, exports);
+ var exports = Bun.TOML.parse(fs.readFileSync(id, "utf8"));
+ $requireMap.$set(id, $createCommonJSModule(id, exports, true));
return exports;
} else {
- var exports = $requireESM(resolved);
- const cachedExports = $requireMap.$get(resolved);
- if (cachedExports) {
- return cachedExports;
+ var exports = $requireESM(id);
+ const cachedModule = $requireMap.$get(id);
+ if (cachedModule) {
+ return cachedModule.exports;
}
-
- $requireMap.$set(resolved, exports);
+ var defaultExport = exports?.default;
+ if (defaultExport?.[$commonJSSymbol] === 0) {
+ exports = defaultExport;
+ }
+ $requireMap.$set(id, $createCommonJSModule(id, exports, true));
return exports;
}
}
export function createRequireCache() {
- class Module {
- id;
- parent;
- filename;
- children = [];
- paths = [];
-
- constructor(filename) {
- this.id = filename;
- // TODO: windows
- const lastSlash = filename.lastIndexOf("/");
- if (lastSlash !== -1 && filename.length > lastSlash + 1) {
- this.filename = filename.substring(lastSlash + 1);
- } else {
- this.filename = filename;
+ var moduleMap = new Map();
+ var inner = {};
+ return new Proxy(inner, {
+ get(target, key: string) {
+ const entry = $requireMap.$get(key);
+ if (entry) return entry;
+
+ const esm = Loader.registry.$get(key);
+ if (esm?.evaluated) {
+ const namespace = Loader.getModuleNamespaceObject(esm.module);
+ const exports =
+ namespace[$commonJSSymbol] === 0 || namespace.default?.[$commonJSSymbol] ? namespace.default : namespace;
+ const mod = $createCommonJSModule(key, exports, true);
+ $requireMap.$set(key, mod);
+ return mod;
}
- }
- get loaded() {
+ return inner[key];
+ },
+ set(target, key: string, value) {
+ $requireMap.$set(key, value);
return true;
- }
-
- require(path) {
- return $internalRequire($resolveSync(path, this.id));
- }
-
- get exports() {
- return $requireMap.$get(this.id) ?? {};
- }
+ },
- set exports(value) {
- $requireMap.$set(this.id, value);
- }
- }
+ has(target, key: string) {
+ return $requireMap.$has(key) || Loader.registry.$has(key);
+ },
- var moduleMap = new Map();
+ deleteProperty(target, key: string) {
+ moduleMap.$delete(key);
+ $requireMap.$delete(key);
+ Loader.registry.$delete(key);
+ return true;
+ },
- return new Proxy(
- {},
- {
- get(target, key: string) {
- const entry = $requireMap.$get(key);
- if (entry) {
- var mod = moduleMap.$get(key);
- if (!mod) {
- mod = new Module(key);
- moduleMap.$set(key, mod);
- }
- return mod;
- }
- },
- set(target, key: string, value) {
- if (!moduleMap.$has(key)) {
- moduleMap.$set(key, new Module(key));
+ ownKeys(target) {
+ var array = [...$requireMap.$keys()];
+ const registryKeys = [...Loader.registry.$keys()];
+ for (const key of registryKeys) {
+ if (!array.includes(key)) {
+ $arrayPush(array, key);
}
+ }
- $requireMap.$set(key, value?.exports);
-
- return true;
- },
-
- has(target, key: string) {
- return $requireMap.$has(key);
- },
-
- deleteProperty(target, key: string) {
- moduleMap.$delete(key);
- $requireMap.$delete(key);
- Loader.registry.$delete(key);
- return true;
- },
-
- ownKeys(target) {
- return [...$requireMap.$keys()];
- },
+ return array;
+ },
- // In Node, require.cache has a null prototype
- getPrototypeOf(target) {
- return null;
- },
+ // In Node, require.cache has a null prototype
+ getPrototypeOf(target) {
+ return null;
+ },
- getOwnPropertyDescriptor(target, key: string) {
- if ($requireMap.$has(key)) {
- return {
- configurable: true,
- enumerable: true,
- };
- }
- },
+ getOwnPropertyDescriptor(target, key: string) {
+ if ($requireMap.$has(key) || Loader.registry.$has(key)) {
+ return {
+ configurable: true,
+ enumerable: true,
+ };
+ }
},
- );
+ });
}
-$sloppy;
-export function require(this: ImportMetaObject, name) {
- var from = this?.path ?? arguments.callee.path;
-
- if (typeof name !== "string") {
- throw new TypeError("require(name) must be a string");
- }
-
- return $internalRequire($resolveSync(name, from));
+export function require(this: string, name) {
+ return $internalRequire($resolveSync(name, $toString(this), false));
}
$getter;