diff options
Diffstat (limited to 'ext/node/02_require.js')
-rw-r--r-- | ext/node/02_require.js | 938 |
1 files changed, 0 insertions, 938 deletions
diff --git a/ext/node/02_require.js b/ext/node/02_require.js deleted file mode 100644 index 43343a21a..000000000 --- a/ext/node/02_require.js +++ /dev/null @@ -1,938 +0,0 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. - -// deno-lint-ignore-file - -const core = globalThis.Deno.core; -const ops = core.ops; -const internals = globalThis.__bootstrap.internals; -const primordials = globalThis.__bootstrap.primordials; -const { - ArrayIsArray, - ArrayPrototypeIncludes, - ArrayPrototypeIndexOf, - ArrayPrototypeJoin, - ArrayPrototypePush, - ArrayPrototypeSlice, - ArrayPrototypeSplice, - ObjectGetOwnPropertyDescriptor, - ObjectGetPrototypeOf, - ObjectPrototypeHasOwnProperty, - ObjectSetPrototypeOf, - ObjectKeys, - ObjectPrototype, - ObjectCreate, - Proxy, - SafeMap, - SafeWeakMap, - SafeArrayIterator, - JSONParse, - String, - StringPrototypeEndsWith, - StringPrototypeIndexOf, - StringPrototypeIncludes, - StringPrototypeMatch, - StringPrototypeSlice, - StringPrototypeSplit, - StringPrototypeStartsWith, - StringPrototypeCharCodeAt, - RegExpPrototypeTest, - Error, - TypeError, -} = primordials; -const node = internals.node; - -// Map used to store CJS parsing data. -const cjsParseCache = new SafeWeakMap(); - -function pathDirname(filepath) { - if (filepath == null || filepath === "") { - throw new Error("Empty 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; -let hasBrokenOnInspectBrk = false; -let hasInspectBrk = false; -// Are we running with --node-modules-dir flag? -let usesLocalNodeModulesDir = false; - -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 packageJsonPath = pathResolve( - requestPath, - "package.json", - ); - const pkg = ops.op_require_read_package_scope(packageJsonPath)?.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 { - node.globalThis.process.emitWarning( - `Invalid 'main' field in '${packageJsonPath}' 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 = ObjectCreate(null); -Module._cache = ObjectCreate(null); -Module._pathCache = ObjectCreate(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, - usesLocalNodeModulesDir, -) { - // The implementation's behavior is meant to mirror resolution in ESM. - const [, name, expansion = ""] = - StringPrototypeMatch(request, EXPORTS_PATTERN) || []; - if (!name) { - return; - } - - return ops.op_require_resolve_exports( - usesLocalNodeModulesDir, - 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, - usesLocalNodeModulesDir, - ); - if (exportsResolved) { - return exportsResolved; - } - } - - const isDenoDirPackage = ops.op_require_is_deno_dir_package( - curPath, - ); - const isRelative = ops.op_require_is_request_relative( - request, - ); - 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 (fromPath) { - return ops.op_require_node_module_paths(fromPath); -}; - -Module._resolveLookupPaths = function (request, parent) { - const paths = []; - - if (ops.op_require_is_request_relative(request) && parent?.filename) { - ArrayPrototypePush( - paths, - ops.op_require_path_dirname(parent.filename), - ); - return paths; - } - - if (parent?.filename && parent.filename.length > 0) { - const denoDirPath = ops.op_require_resolve_deno_dir( - request, - parent.filename, - ); - if (denoDirPath) { - ArrayPrototypePush(paths, denoDirPath); - } - } - const lookupPathsResult = ops.op_require_resolve_lookup_paths( - request, - parent?.paths, - parent?.filename ?? "", - ); - if (lookupPathsResult) { - ArrayPrototypePush(paths, ...new SafeArrayIterator(lookupPathsResult)); - } - 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; - 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 = 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 = [ - // We provide the non-standard APIs in the CommonJS wrapper - // to avoid exposing them in global namespace. - "(function (exports, require, module, __filename, __dirname, globalThis) { const { Buffer, clearImmediate, clearInterval, clearTimeout, console, global, process, setImmediate, setInterval, setTimeout} = globalThis; var window = undefined; (function () {", - "\n}).call(this); })", -]; -Module.wrap = function (script) { - script = script.replace(/^#!.*?\n/, ""); - return `${Module.wrapper[0]}${script}${Module.wrapper[1]}`; -}; - -function enrichCJSError(error) { - if (error instanceof SyntaxError) { - if ( - StringPrototypeIncludes( - error.message, - "Cannot use import statement outside a module", - ) || - StringPrototypeIncludes(error.message, "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, `file://${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(); - } - - if (hasInspectBrk && !hasBrokenOnInspectBrk) { - hasBrokenOnInspectBrk = true; - ops.op_require_break_on_next_statement(); - } - - 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 = ops.op_require_read_closest_package_json(filename); - if (pkg && pkg.exists && pkg.typ == "module") { - let message = `Trying to import ESM module: ${filename}`; - - if (module.parent) { - message += ` from ${module.parent.filename}`; - } - - message += ` using require()`; - - throw new Error(message); - } - } - - module._compile(content, filename); -}; - -function stripBOM(content) { - if (StringPrototypeCharCodeAt(content, 0) === 0xfeff) { - content = StringPrototypeSlice(content, 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) { - if (filename.endsWith("fsevents.node")) { - throw new Error("Using fsevents module is currently not supported"); - } - module.exports = ops.op_napi_open(filename, node.globalThis); -}; - -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; -} - -// Matches to: -// - /foo/... -// - \foo\... -// - C:/foo/... -// - C:\foo\... -const RE_START_OF_ABS_PATH = /^([/\\]|[a-zA-Z]:[/\\])/; - -function isAbsolute(filenameOrUrl) { - return RE_START_OF_ABS_PATH.test(filenameOrUrl); -} - -function createRequire(filenameOrUrl) { - let fileUrlStr; - if (filenameOrUrl instanceof URL) { - if (filenameOrUrl.protocol !== "file:") { - throw new Error( - `The argument 'filename' must be a file URL object, file URL string, or absolute path string. Received ${filenameOrUrl}`, - ); - } - fileUrlStr = filenameOrUrl.toString(); - } else if (typeof filenameOrUrl === "string") { - if (!filenameOrUrl.startsWith("file:") && !isAbsolute(filenameOrUrl)) { - throw new Error( - `The argument 'filename' must be a file URL object, file URL string, or absolute path string. Received ${filenameOrUrl}`, - ); - } - fileUrlStr = filenameOrUrl; - } else { - throw new Error( - `The argument 'filename' must be a file URL object, file URL string, or absolute path string. Received ${filenameOrUrl}`, - ); - } - const filename = ops.op_require_as_file_path(fileUrlStr); - 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; - -node.nativeModuleExports.module = Module; - -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"); -} - -/** @param specifier {string} */ -function packageSpecifierSubPath(specifier) { - let parts = StringPrototypeSplit(specifier, "/"); - if (StringPrototypeStartsWith(parts[0], "@")) { - parts = ArrayPrototypeSlice(parts, 2); - } else { - parts = ArrayPrototypeSlice(parts, 1); - } - return ArrayPrototypeJoin(parts, "/"); -} - -internals.require = { - setUsesLocalNodeModulesDir() { - usesLocalNodeModulesDir = true; - }, - setInspectBrk() { - hasInspectBrk = true; - }, - Module, - wrapSafe, - toRealPath, - cjsParseCache, - readPackageScope, -}; |