summaryrefslogtreecommitdiff
path: root/ext/node/02_require.js
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2022-08-20 11:31:33 -0400
committerGitHub <noreply@github.com>2022-08-20 11:31:33 -0400
commit87f80ff6be5e2a132b583a9c380fff5db3cb2b07 (patch)
treeb2c43c9004b9ada204f3b5db7c221fa6322f026a /ext/node/02_require.js
parent1ffbd561642d05a05e18ada764d50581dea779ef (diff)
feat(unstable): initial support for npm specifiers (#15484)
Co-authored-by: Bartek IwaƄczuk <biwanczuk@gmail.com>
Diffstat (limited to 'ext/node/02_require.js')
-rw-r--r--ext/node/02_require.js886
1 files changed, 886 insertions, 0 deletions
diff --git a/ext/node/02_require.js b/ext/node/02_require.js
new file mode 100644
index 000000000..1fcd0167c
--- /dev/null
+++ b/ext/node/02_require.js
@@ -0,0 +1,886 @@
+// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
+
+// deno-lint-ignore-file
+
+"use strict";
+
+((window) => {
+ const {
+ ArrayIsArray,
+ ArrayPrototypeIncludes,
+ ArrayPrototypeIndexOf,
+ ArrayPrototypeJoin,
+ ArrayPrototypePush,
+ ArrayPrototypeSlice,
+ ArrayPrototypeSplice,
+ FunctionPrototypeBind,
+ ObjectGetOwnPropertyDescriptor,
+ ObjectGetPrototypeOf,
+ ObjectPrototypeHasOwnProperty,
+ ObjectSetPrototypeOf,
+ ObjectKeys,
+ ObjectPrototype,
+ ObjectCreate,
+ SafeMap,
+ SafeWeakMap,
+ JSONParse,
+ StringPrototypeEndsWith,
+ StringPrototypeIndexOf,
+ StringPrototypeMatch,
+ StringPrototypeSlice,
+ StringPrototypeStartsWith,
+ StringPrototypeCharCodeAt,
+ RegExpPrototypeTest,
+ } = window.__bootstrap.primordials;
+ const core = window.Deno.core;
+ const ops = core.ops;
+ const { node } = window.__bootstrap.internals;
+
+ // Map used to store CJS parsing data.
+ const cjsParseCache = new SafeWeakMap();
+
+ function pathDirname(filepath) {
+ return ops.op_require_path_dirname(filepath);
+ }
+
+ function pathResolve(...args) {
+ return ops.op_require_path_resolve(args);
+ }
+
+ function assert(cond) {
+ if (!cond) {
+ throw Error("assert");
+ }
+ }
+
+ const nativeModulePolyfill = new SafeMap();
+
+ const relativeResolveCache = ObjectCreate(null);
+ let requireDepth = 0;
+ let statCache = null;
+ let isPreloading = false;
+ let mainModule = null;
+
+ function stat(filename) {
+ // TODO: required only on windows
+ // filename = path.toNamespacedPath(filename);
+ if (statCache !== null) {
+ const result = statCache.get(filename);
+ if (result !== undefined) {
+ return result;
+ }
+ }
+ const result = ops.op_require_stat(filename);
+ if (statCache !== null && result >= 0) {
+ statCache.set(filename, result);
+ }
+
+ return result;
+ }
+
+ function updateChildren(parent, child, scan) {
+ if (!parent) {
+ return;
+ }
+
+ const children = parent.children;
+ if (children && !(scan && ArrayPrototypeIncludes(children, child))) {
+ ArrayPrototypePush(children, child);
+ }
+ }
+
+ function tryFile(requestPath, _isMain) {
+ const rc = stat(requestPath);
+ if (rc !== 0) return;
+ return toRealPath(requestPath);
+ }
+
+ function tryPackage(requestPath, exts, isMain, originalPath) {
+ const pkg = core.ops.op_require_read_package_scope(requestPath).main;
+ if (!pkg) {
+ return tryExtensions(
+ pathResolve(requestPath, "index"),
+ exts,
+ isMain,
+ );
+ }
+
+ const filename = pathResolve(requestPath, pkg);
+ let actual = tryFile(filename, isMain) ||
+ tryExtensions(filename, exts, isMain) ||
+ tryExtensions(
+ pathResolve(filename, "index"),
+ exts,
+ isMain,
+ );
+ if (actual === false) {
+ actual = tryExtensions(
+ pathResolve(requestPath, "index"),
+ exts,
+ isMain,
+ );
+ if (!actual) {
+ // eslint-disable-next-line no-restricted-syntax
+ const err = new Error(
+ `Cannot find module '${filename}'. ` +
+ 'Please verify that the package.json has a valid "main" entry',
+ );
+ err.code = "MODULE_NOT_FOUND";
+ err.path = pathResolve(
+ requestPath,
+ "package.json",
+ );
+ err.requestPath = originalPath;
+ throw err;
+ } else {
+ const jsonPath = pathResolve(
+ requestPath,
+ "package.json",
+ );
+ node.globalThis.process.emitWarning(
+ `Invalid 'main' field in '${jsonPath}' of '${pkg}'. ` +
+ "Please either fix that or report it to the module author",
+ "DeprecationWarning",
+ "DEP0128",
+ );
+ }
+ }
+ return actual;
+ }
+
+ const realpathCache = new SafeMap();
+ function toRealPath(requestPath) {
+ const maybeCached = realpathCache.get(requestPath);
+ if (maybeCached) {
+ return maybeCached;
+ }
+ const rp = ops.op_require_real_path(requestPath);
+ realpathCache.set(requestPath, rp);
+ return rp;
+ }
+
+ function tryExtensions(p, exts, isMain) {
+ for (let i = 0; i < exts.length; i++) {
+ const filename = tryFile(p + exts[i], isMain);
+
+ if (filename) {
+ return filename;
+ }
+ }
+ return false;
+ }
+
+ // Find the longest (possibly multi-dot) extension registered in
+ // Module._extensions
+ function findLongestRegisteredExtension(filename) {
+ const name = ops.op_require_path_basename(filename);
+ let currentExtension;
+ let index;
+ let startIndex = 0;
+ while ((index = StringPrototypeIndexOf(name, ".", startIndex)) !== -1) {
+ startIndex = index + 1;
+ if (index === 0) continue; // Skip dotfiles like .gitignore
+ currentExtension = StringPrototypeSlice(name, index);
+ if (Module._extensions[currentExtension]) {
+ return currentExtension;
+ }
+ }
+ return ".js";
+ }
+
+ function getExportsForCircularRequire(module) {
+ if (
+ module.exports &&
+ ObjectGetPrototypeOf(module.exports) === ObjectPrototype &&
+ // Exclude transpiled ES6 modules / TypeScript code because those may
+ // employ unusual patterns for accessing 'module.exports'. That should
+ // be okay because ES6 modules have a different approach to circular
+ // dependencies anyway.
+ !module.exports.__esModule
+ ) {
+ // This is later unset once the module is done loading.
+ ObjectSetPrototypeOf(
+ module.exports,
+ CircularRequirePrototypeWarningProxy,
+ );
+ }
+
+ return module.exports;
+ }
+
+ function emitCircularRequireWarning(prop) {
+ node.globalThis.process.emitWarning(
+ `Accessing non-existent property '${String(prop)}' of module exports ` +
+ "inside circular dependency",
+ );
+ }
+
+ // A Proxy that can be used as the prototype of a module.exports object and
+ // warns when non-existent properties are accessed.
+ const CircularRequirePrototypeWarningProxy = new Proxy({}, {
+ get(target, prop) {
+ // Allow __esModule access in any case because it is used in the output
+ // of transpiled code to determine whether something comes from an
+ // ES module, and is not used as a regular key of `module.exports`.
+ if (prop in target || prop === "__esModule") return target[prop];
+ emitCircularRequireWarning(prop);
+ return undefined;
+ },
+
+ getOwnPropertyDescriptor(target, prop) {
+ if (
+ ObjectPrototypeHasOwnProperty(target, prop) || prop === "__esModule"
+ ) {
+ return ObjectGetOwnPropertyDescriptor(target, prop);
+ }
+ emitCircularRequireWarning(prop);
+ return undefined;
+ },
+ });
+
+ const moduleParentCache = new SafeWeakMap();
+ function Module(id = "", parent) {
+ this.id = id;
+ this.path = pathDirname(id);
+ this.exports = {};
+ moduleParentCache.set(this, parent);
+ updateChildren(parent, this, false);
+ this.filename = null;
+ this.loaded = false;
+ this.children = [];
+ }
+
+ Module.builtinModules = node.builtinModules;
+
+ Module._extensions = Object.create(null);
+ Module._cache = Object.create(null);
+ Module._pathCache = Object.create(null);
+ let modulePaths = [];
+ Module.globalPaths = modulePaths;
+
+ const CHAR_FORWARD_SLASH = 47;
+ const TRAILING_SLASH_REGEX = /(?:^|\/)\.?\.$/;
+ const encodedSepRegEx = /%2F|%2C/i;
+
+ function finalizeEsmResolution(
+ resolved,
+ parentPath,
+ pkgPath,
+ ) {
+ if (RegExpPrototypeTest(encodedSepRegEx, resolved)) {
+ throw new ERR_INVALID_MODULE_SPECIFIER(
+ resolved,
+ 'must not include encoded "/" or "\\" characters',
+ parentPath,
+ );
+ }
+ // const filename = fileURLToPath(resolved);
+ const filename = resolved;
+ const actual = tryFile(filename, false);
+ if (actual) {
+ return actual;
+ }
+ throw new ERR_MODULE_NOT_FOUND(
+ filename,
+ path.resolve(pkgPath, "package.json"),
+ );
+ }
+
+ // This only applies to requests of a specific form:
+ // 1. name/.*
+ // 2. @scope/name/.*
+ const EXPORTS_PATTERN = /^((?:@[^/\\%]+\/)?[^./\\%][^/\\%]*)(\/.*)?$/;
+ function resolveExports(modulesPath, request, parentPath) {
+ // The implementation's behavior is meant to mirror resolution in ESM.
+ const [, name, expansion = ""] =
+ StringPrototypeMatch(request, EXPORTS_PATTERN) || [];
+ if (!name) {
+ return;
+ }
+
+ return core.ops.op_require_resolve_exports(
+ modulesPath,
+ request,
+ name,
+ expansion,
+ parentPath,
+ ) ?? false;
+ }
+
+ Module._findPath = function (request, paths, isMain, parentPath) {
+ const absoluteRequest = ops.op_require_path_is_absolute(request);
+ if (absoluteRequest) {
+ paths = [""];
+ } else if (!paths || paths.length === 0) {
+ return false;
+ }
+
+ const cacheKey = request + "\x00" + ArrayPrototypeJoin(paths, "\x00");
+ const entry = Module._pathCache[cacheKey];
+ if (entry) {
+ return entry;
+ }
+
+ let exts;
+ let trailingSlash = request.length > 0 &&
+ StringPrototypeCharCodeAt(request, request.length - 1) ===
+ CHAR_FORWARD_SLASH;
+ if (!trailingSlash) {
+ trailingSlash = RegExpPrototypeTest(TRAILING_SLASH_REGEX, request);
+ }
+
+ // For each path
+ for (let i = 0; i < paths.length; i++) {
+ // Don't search further if path doesn't exist
+ const curPath = paths[i];
+ if (curPath && stat(curPath) < 1) continue;
+
+ if (!absoluteRequest) {
+ const exportsResolved = resolveExports(curPath, request, parentPath);
+ if (exportsResolved) {
+ return exportsResolved;
+ }
+ }
+
+ const isDenoDirPackage = Deno.core.opSync(
+ "op_require_is_deno_dir_package",
+ curPath,
+ );
+ const isRelative = ops.op_require_is_request_relative(
+ request,
+ );
+ // TODO(bartlomieju): could be a single op
+ const basePath = (isDenoDirPackage && !isRelative)
+ ? pathResolve(curPath, packageSpecifierSubPath(request))
+ : pathResolve(curPath, request);
+ let filename;
+
+ const rc = stat(basePath);
+ if (!trailingSlash) {
+ if (rc === 0) { // File.
+ filename = toRealPath(basePath);
+ }
+
+ if (!filename) {
+ // Try it with each of the extensions
+ if (exts === undefined) {
+ exts = ObjectKeys(Module._extensions);
+ }
+ filename = tryExtensions(basePath, exts, isMain);
+ }
+ }
+
+ if (!filename && rc === 1) { // Directory.
+ // try it with each of the extensions at "index"
+ if (exts === undefined) {
+ exts = ObjectKeys(Module._extensions);
+ }
+ filename = tryPackage(basePath, exts, isMain, request);
+ }
+
+ if (filename) {
+ Module._pathCache[cacheKey] = filename;
+ return filename;
+ }
+ }
+
+ return false;
+ };
+
+ Module._nodeModulePaths = function (from) {
+ return ops.op_require_node_module_paths(from);
+ };
+
+ Module._resolveLookupPaths = function (request, parent) {
+ const paths = [];
+ if (parent?.filename && parent.filename.length > 0) {
+ const denoDirPath = core.opSync(
+ "op_require_resolve_deno_dir",
+ request,
+ parent.filename,
+ );
+ if (denoDirPath) {
+ paths.push(denoDirPath);
+ }
+ }
+ paths.push(...ops.op_require_resolve_lookup_paths(
+ request,
+ parent?.paths,
+ parent?.filename ?? "",
+ ));
+ return paths;
+ };
+
+ Module._load = function (request, parent, isMain) {
+ let relResolveCacheIdentifier;
+ if (parent) {
+ // Fast path for (lazy loaded) modules in the same directory. The indirect
+ // caching is required to allow cache invalidation without changing the old
+ // cache key names.
+ relResolveCacheIdentifier = `${parent.path}\x00${request}`;
+ const filename = relativeResolveCache[relResolveCacheIdentifier];
+ if (filename !== undefined) {
+ const cachedModule = Module._cache[filename];
+ if (cachedModule !== undefined) {
+ updateChildren(parent, cachedModule, true);
+ if (!cachedModule.loaded) {
+ return getExportsForCircularRequire(cachedModule);
+ }
+ return cachedModule.exports;
+ }
+ delete relativeResolveCache[relResolveCacheIdentifier];
+ }
+ }
+
+ const filename = Module._resolveFilename(request, parent, isMain);
+ if (StringPrototypeStartsWith(filename, "node:")) {
+ // Slice 'node:' prefix
+ const id = StringPrototypeSlice(filename, 5);
+
+ const module = loadNativeModule(id, id);
+ if (!module) {
+ // TODO:
+ // throw new ERR_UNKNOWN_BUILTIN_MODULE(filename);
+ throw new Error("Unknown built-in module");
+ }
+
+ return module.exports;
+ }
+
+ const cachedModule = Module._cache[filename];
+ if (cachedModule !== undefined) {
+ updateChildren(parent, cachedModule, true);
+ if (!cachedModule.loaded) {
+ return getExportsForCircularRequire(cachedModule);
+ }
+ return cachedModule.exports;
+ }
+
+ const mod = loadNativeModule(filename, request);
+ if (
+ mod
+ ) {
+ return mod.exports;
+ }
+ // Don't call updateChildren(), Module constructor already does.
+ const module = cachedModule || new Module(filename, parent);
+
+ if (isMain) {
+ node.globalThis.process.mainModule = module;
+ module.id = ".";
+ }
+
+ Module._cache[filename] = module;
+ if (parent !== undefined) {
+ relativeResolveCache[relResolveCacheIdentifier] = filename;
+ }
+
+ let threw = true;
+ try {
+ module.load(filename);
+ threw = false;
+ } finally {
+ if (threw) {
+ delete Module._cache[filename];
+ if (parent !== undefined) {
+ delete relativeResolveCache[relResolveCacheIdentifier];
+ const children = parent?.children;
+ if (ArrayIsArray(children)) {
+ const index = ArrayPrototypeIndexOf(children, module);
+ if (index !== -1) {
+ ArrayPrototypeSplice(children, index, 1);
+ }
+ }
+ }
+ } else if (
+ module.exports &&
+ ObjectGetPrototypeOf(module.exports) ===
+ CircularRequirePrototypeWarningProxy
+ ) {
+ ObjectSetPrototypeOf(module.exports, ObjectPrototype);
+ }
+ }
+
+ return module.exports;
+ };
+
+ Module._resolveFilename = function (
+ request,
+ parent,
+ isMain,
+ options,
+ ) {
+ if (
+ StringPrototypeStartsWith(request, "node:") ||
+ nativeModuleCanBeRequiredByUsers(request)
+ ) {
+ return request;
+ }
+
+ let paths;
+
+ if (typeof options === "object" && options !== null) {
+ if (ArrayIsArray(options.paths)) {
+ const isRelative = ops.op_require_is_request_relative(
+ request,
+ );
+
+ if (isRelative) {
+ paths = options.paths;
+ } else {
+ const fakeParent = new Module("", null);
+
+ paths = [];
+
+ for (let i = 0; i < options.paths.length; i++) {
+ const path = options.paths[i];
+ fakeParent.paths = Module._nodeModulePaths(path);
+ const lookupPaths = Module._resolveLookupPaths(request, fakeParent);
+
+ for (let j = 0; j < lookupPaths.length; j++) {
+ if (!ArrayPrototypeIncludes(paths, lookupPaths[j])) {
+ ArrayPrototypePush(paths, lookupPaths[j]);
+ }
+ }
+ }
+ }
+ } else if (options.paths === undefined) {
+ paths = Module._resolveLookupPaths(request, parent);
+ } else {
+ // TODO:
+ // throw new ERR_INVALID_ARG_VALUE("options.paths", options.paths);
+ throw new Error("Invalid arg value options.paths", options.path);
+ }
+ } else {
+ paths = Module._resolveLookupPaths(request, parent);
+ }
+
+ if (parent?.filename) {
+ if (request[0] === "#") {
+ const maybeResolved = core.ops.op_require_package_imports_resolve(
+ parent.filename,
+ request,
+ );
+ if (maybeResolved) {
+ return maybeResolved;
+ }
+ }
+ }
+
+ // Try module self resolution first
+ const parentPath = ops.op_require_try_self_parent_path(
+ !!parent,
+ parent?.filename,
+ parent?.id,
+ );
+ const selfResolved = ops.op_require_try_self(parentPath, request);
+ if (selfResolved) {
+ const cacheKey = request + "\x00" +
+ (paths.length === 1 ? paths[0] : ArrayPrototypeJoin(paths, "\x00"));
+ Module._pathCache[cacheKey] = selfResolved;
+ return selfResolved;
+ }
+
+ // Look up the filename first, since that's the cache key.
+ const filename = Module._findPath(
+ request,
+ paths,
+ isMain,
+ parentPath,
+ );
+ if (filename) return filename;
+ const requireStack = [];
+ for (let cursor = parent; cursor; cursor = moduleParentCache.get(cursor)) {
+ ArrayPrototypePush(requireStack, cursor.filename || cursor.id);
+ }
+ let message = `Cannot find module '${request}'`;
+ if (requireStack.length > 0) {
+ message = message + "\nRequire stack:\n- " +
+ ArrayPrototypeJoin(requireStack, "\n- ");
+ }
+ // eslint-disable-next-line no-restricted-syntax
+ const err = new Error(message);
+ err.code = "MODULE_NOT_FOUND";
+ err.requireStack = requireStack;
+ throw err;
+ };
+
+ Module.prototype.load = function (filename) {
+ assert(!this.loaded);
+ this.filename = filename;
+ this.paths = Module._nodeModulePaths(
+ pathDirname(filename),
+ );
+ const extension = findLongestRegisteredExtension(filename);
+ // allow .mjs to be overriden
+ if (
+ StringPrototypeEndsWith(filename, ".mjs") && !Module._extensions[".mjs"]
+ ) {
+ // TODO: use proper error class
+ throw new Error("require ESM", filename);
+ }
+
+ Module._extensions[extension](this, filename);
+ this.loaded = true;
+
+ // TODO: do caching
+ };
+
+ // Loads a module at the given file path. Returns that module's
+ // `exports` property.
+ Module.prototype.require = function (id) {
+ if (typeof id !== "string") {
+ // TODO(bartlomieju): it should use different error type
+ // ("ERR_INVALID_ARG_VALUE")
+ throw new TypeError("Invalid argument type");
+ }
+
+ if (id === "") {
+ // TODO(bartlomieju): it should use different error type
+ // ("ERR_INVALID_ARG_VALUE")
+ throw new TypeError("id must be non empty");
+ }
+ requireDepth++;
+ try {
+ return Module._load(id, this, /* isMain */ false);
+ } finally {
+ requireDepth--;
+ }
+ };
+
+ Module.wrapper = [
+ // TODO:
+ // We provide non standard timer APIs in the CommonJS wrapper
+ // to avoid exposing them in global namespace.
+ "(function (exports, require, module, __filename, __dirname, globalThis) { (function (exports, require, module, __filename, __dirname, globalThis, Buffer, clearImmediate, clearInterval, clearTimeout, global, process, setImmediate, setInterval, setTimeout) {",
+ "\n}).call(this, exports, require, module, __filename, __dirname, globalThis, globalThis.Buffer, globalThis.clearImmediate, globalThis.clearInterval, globalThis.clearTimeout, globalThis.global, globalThis.process, globalThis.setImmediate, globalThis.setInterval, globalThis.setTimeout); })",
+ ];
+ Module.wrap = function (script) {
+ script = script.replace(/^#!.*?\n/, "");
+ return `${Module.wrapper[0]}${script}${Module.wrapper[1]}`;
+ };
+
+ function enrichCJSError(error) {
+ if (error instanceof SyntaxError) {
+ if (
+ error.message.includes(
+ "Cannot use import statement outside a module",
+ ) ||
+ error.message.includes("Unexpected token 'export'")
+ ) {
+ console.error(
+ 'To load an ES module, set "type": "module" in the package.json or use ' +
+ "the .mjs extension.",
+ );
+ }
+ }
+ }
+
+ function wrapSafe(
+ filename,
+ content,
+ cjsModuleInstance,
+ ) {
+ const wrapper = Module.wrap(content);
+ const [f, err] = core.evalContext(wrapper, filename);
+ if (err) {
+ if (node.globalThis.process.mainModule === cjsModuleInstance) {
+ enrichCJSError(err.thrown);
+ }
+ throw err.thrown;
+ }
+ return f;
+ }
+
+ Module.prototype._compile = function (content, filename) {
+ const compiledWrapper = wrapSafe(filename, content, this);
+
+ const dirname = pathDirname(filename);
+ const require = makeRequireFunction(this);
+ const exports = this.exports;
+ const thisValue = exports;
+ const module = this;
+ if (requireDepth === 0) {
+ statCache = new SafeMap();
+ }
+ const result = compiledWrapper.call(
+ thisValue,
+ exports,
+ require,
+ this,
+ filename,
+ dirname,
+ node.globalThis,
+ );
+ if (requireDepth === 0) {
+ statCache = null;
+ }
+ return result;
+ };
+
+ Module._extensions[".js"] = function (module, filename) {
+ const content = ops.op_require_read_file(filename);
+
+ if (StringPrototypeEndsWith(filename, ".js")) {
+ const pkg = core.ops.op_require_read_package_scope(filename);
+ if (pkg && pkg.exists && pkg.typ == "module") {
+ throw new Error(
+ `Import ESM module: ${filename} from ${module.parent.filename}`,
+ );
+ }
+ }
+
+ module._compile(content, filename);
+ };
+
+ function stripBOM(content) {
+ if (content.charCodeAt(0) === 0xfeff) {
+ content = content.slice(1);
+ }
+ return content;
+ }
+
+ // Native extension for .json
+ Module._extensions[".json"] = function (module, filename) {
+ const content = ops.op_require_read_file(filename);
+
+ try {
+ module.exports = JSONParse(stripBOM(content));
+ } catch (err) {
+ err.message = filename + ": " + err.message;
+ throw err;
+ }
+ };
+
+ // Native extension for .node
+ Module._extensions[".node"] = function (module, filename) {
+ throw new Error("not implemented loading .node files");
+ };
+
+ function createRequireFromPath(filename) {
+ const proxyPath = ops.op_require_proxy_path(filename);
+ const mod = new Module(proxyPath);
+ mod.filename = proxyPath;
+ mod.paths = Module._nodeModulePaths(mod.path);
+ return makeRequireFunction(mod);
+ }
+
+ function makeRequireFunction(mod) {
+ const require = function require(path) {
+ return mod.require(path);
+ };
+
+ function resolve(request, options) {
+ return Module._resolveFilename(request, mod, false, options);
+ }
+
+ require.resolve = resolve;
+
+ function paths(request) {
+ return Module._resolveLookupPaths(request, mod);
+ }
+
+ resolve.paths = paths;
+ require.main = mainModule;
+ // Enable support to add extra extension types.
+ require.extensions = Module._extensions;
+ require.cache = Module._cache;
+
+ return require;
+ }
+
+ function createRequire(filenameOrUrl) {
+ // FIXME: handle URLs and validation
+ const filename = core.opSync("op_require_as_file_path", filenameOrUrl);
+ return createRequireFromPath(filename);
+ }
+
+ Module.createRequire = createRequire;
+
+ Module._initPaths = function () {
+ const paths = ops.op_require_init_paths();
+ modulePaths = paths;
+ Module.globalPaths = ArrayPrototypeSlice(modulePaths);
+ };
+
+ Module.syncBuiltinESMExports = function syncBuiltinESMExports() {
+ throw new Error("not implemented");
+ };
+
+ Module.Module = Module;
+
+ const m = {
+ _cache: Module._cache,
+ _extensions: Module._extensions,
+ _findPath: Module._findPath,
+ _initPaths: Module._initPaths,
+ _load: Module._load,
+ _nodeModulePaths: Module._nodeModulePaths,
+ _pathCache: Module._pathCache,
+ _preloadModules: Module._preloadModules,
+ _resolveFilename: Module._resolveFilename,
+ _resolveLookupPaths: Module._resolveLookupPaths,
+ builtinModules: Module.builtinModules,
+ createRequire: Module.createRequire,
+ globalPaths: Module.globalPaths,
+ Module,
+ wrap: Module.wrap,
+ };
+
+ node.nativeModuleExports.module = m;
+
+ function loadNativeModule(_id, request) {
+ if (nativeModulePolyfill.has(request)) {
+ return nativeModulePolyfill.get(request);
+ }
+ const modExports = node.nativeModuleExports[request];
+ if (modExports) {
+ const nodeMod = new Module(request);
+ nodeMod.exports = modExports;
+ nodeMod.loaded = true;
+ nativeModulePolyfill.set(request, nodeMod);
+ return nodeMod;
+ }
+ return undefined;
+ }
+
+ function nativeModuleCanBeRequiredByUsers(request) {
+ return !!node.nativeModuleExports[request];
+ }
+
+ function readPackageScope() {
+ throw new Error("not implemented");
+ }
+
+ function bindExport(value, mod) {
+ // ensure exported functions are bound to their module object
+ if (typeof value === "function") {
+ return FunctionPrototypeBind(value, mod);
+ } else {
+ return value;
+ }
+ }
+
+ /** @param specifier {string} */
+ function packageSpecifierSubPath(specifier) {
+ let parts = specifier.split("/");
+ if (parts[0].startsWith("@")) {
+ parts = parts.slice(2);
+ } else {
+ parts = parts.slice(1);
+ }
+ return parts.join("/");
+ }
+
+ window.__bootstrap.internals = {
+ ...window.__bootstrap.internals ?? {},
+ require: {
+ Module,
+ wrapSafe,
+ toRealPath,
+ cjsParseCache,
+ readPackageScope,
+ bindExport,
+ },
+ };
+})(globalThis);