summaryrefslogtreecommitdiff
path: root/std/node/module.ts
diff options
context:
space:
mode:
Diffstat (limited to 'std/node/module.ts')
-rw-r--r--std/node/module.ts1163
1 files changed, 0 insertions, 1163 deletions
diff --git a/std/node/module.ts b/std/node/module.ts
deleted file mode 100644
index 0d6ef9133..000000000
--- a/std/node/module.ts
+++ /dev/null
@@ -1,1163 +0,0 @@
-// 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.
-
-import "./global.ts";
-
-import * as nodeBuffer from "./buffer.ts";
-import * as nodeEvents from "./events.ts";
-import * as nodeFS from "./fs.ts";
-import * as nodeOs from "./os.ts";
-import * as nodePath from "./path.ts";
-import * as nodeQueryString from "./querystring.ts";
-import * as nodeStream from "./stream.ts";
-import * as nodeStringDecoder from "./string_decoder.ts";
-import * as nodeTimers from "./timers.ts";
-import * as nodeUtil from "./util.ts";
-
-import * as path from "../path/mod.ts";
-import { assert } from "../_util/assert.ts";
-import { fileURLToPath, pathToFileURL } from "./url.ts";
-import { isWindows } from "../_util/os.ts";
-
-const CHAR_FORWARD_SLASH = "/".charCodeAt(0);
-const CHAR_BACKWARD_SLASH = "\\".charCodeAt(0);
-const CHAR_COLON = ":".charCodeAt(0);
-
-const relativeResolveCache = Object.create(null);
-
-let requireDepth = 0;
-let statCache: Map<string, StatResult> | null = null;
-
-type StatResult = -1 | 0 | 1;
-// Returns 0 if the path refers to
-// a file, 1 when it's a directory or < 0 on error.
-function stat(filename: string): StatResult {
- filename = path.toNamespacedPath(filename);
- if (statCache !== null) {
- const result = statCache.get(filename);
- if (result !== undefined) return result;
- }
- try {
- const info = Deno.statSync(filename);
- const result = info.isFile ? 0 : 1;
- if (statCache !== null) statCache.set(filename, result);
- return result;
- } catch (e) {
- if (e instanceof Deno.errors.PermissionDenied) {
- throw new Error("CJS loader requires --allow-read.");
- }
- return -1;
- }
-}
-
-function updateChildren(
- parent: Module | null,
- child: Module,
- scan: boolean,
-): void {
- const children = parent && parent.children;
- if (children && !(scan && children.includes(child))) {
- children.push(child);
- }
-}
-
-class Module {
- id: string;
- // deno-lint-ignore no-explicit-any
- exports: any;
- parent: Module | null;
- filename: string | null;
- loaded: boolean;
- children: Module[];
- paths: string[];
- path: string;
- constructor(id = "", parent?: Module | null) {
- this.id = id;
- this.exports = {};
- this.parent = parent || null;
- updateChildren(parent || null, this, false);
- this.filename = null;
- this.loaded = false;
- this.children = [];
- this.paths = [];
- this.path = path.dirname(id);
- }
- static builtinModules: string[] = [];
- static _extensions: {
- // deno-lint-ignore no-explicit-any
- [key: string]: (module: Module, filename: string) => any;
- } = Object.create(null);
- static _cache: { [key: string]: Module } = Object.create(null);
- static _pathCache = Object.create(null);
- static globalPaths: string[] = [];
- // Proxy related code removed.
- static wrapper = [
- "(function (exports, require, module, __filename, __dirname) { ",
- "\n});",
- ];
-
- // Loads a module at the given file path. Returns that module's
- // `exports` property.
- // deno-lint-ignore no-explicit-any
- require(id: string): any {
- if (id === "") {
- throw new Error(`id '${id}' must be a non-empty string`);
- }
- requireDepth++;
- try {
- return Module._load(id, this, /* isMain */ false);
- } finally {
- requireDepth--;
- }
- }
-
- // Given a file name, pass it to the proper extension handler.
- load(filename: string): void {
- assert(!this.loaded);
- this.filename = filename;
- this.paths = Module._nodeModulePaths(path.dirname(filename));
-
- const extension = findLongestRegisteredExtension(filename);
- // Removed ESM code
- Module._extensions[extension](this, filename);
- this.loaded = true;
- // Removed ESM code
- }
-
- // Run the file contents in the correct scope or sandbox. Expose
- // the correct helper variables (require, module, exports) to
- // the file.
- // Returns exception, if any.
- // deno-lint-ignore no-explicit-any
- _compile(content: string, filename: string): any {
- // manifest code removed
- const compiledWrapper = wrapSafe(filename, content);
- // inspector code remove
- const dirname = path.dirname(filename);
- const require = makeRequireFunction(this);
- const exports = this.exports;
- const thisValue = exports;
- if (requireDepth === 0) {
- statCache = new Map();
- }
- const result = compiledWrapper.call(
- thisValue,
- exports,
- require,
- this,
- filename,
- dirname,
- );
- if (requireDepth === 0) {
- statCache = null;
- }
- return result;
- }
-
- /*
- * Check for node modules paths.
- * */
- static _resolveLookupPaths(
- request: string,
- parent: Module | null,
- ): string[] | null {
- if (
- request.charAt(0) !== "." ||
- (request.length > 1 &&
- request.charAt(1) !== "." &&
- request.charAt(1) !== "/" &&
- (!isWindows || request.charAt(1) !== "\\"))
- ) {
- let paths = modulePaths;
- if (parent !== null && parent.paths && parent.paths.length) {
- paths = parent.paths.concat(paths);
- }
-
- return paths.length > 0 ? paths : null;
- }
-
- // With --eval, parent.id is not set and parent.filename is null.
- if (!parent || !parent.id || !parent.filename) {
- // Make require('./path/to/foo') work - normally the path is taken
- // from realpath(__filename) but with eval there is no filename
- return ["."].concat(Module._nodeModulePaths("."), modulePaths);
- }
- // Returns the parent path of the file
- return [path.dirname(parent.filename)];
- }
-
- static _resolveFilename(
- request: string,
- parent: Module,
- isMain: boolean,
- options?: { paths: string[] },
- ): string {
- // Polyfills.
- if (nativeModuleCanBeRequiredByUsers(request)) {
- return request;
- }
-
- let paths: string[];
-
- if (typeof options === "object" && options !== null) {
- if (Array.isArray(options.paths)) {
- const isRelative = request.startsWith("./") ||
- request.startsWith("../") ||
- (isWindows && request.startsWith(".\\")) ||
- request.startsWith("..\\");
-
- 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 (!paths.includes(lookupPaths![j])) {
- paths.push(lookupPaths![j]);
- }
- }
- }
- }
- } else if (options.paths === undefined) {
- paths = Module._resolveLookupPaths(request, parent)!;
- } else {
- throw new Error("options.paths is invalid");
- }
- } else {
- paths = Module._resolveLookupPaths(request, parent)!;
- }
-
- // Look up the filename first, since that's the cache key.
- const filename = Module._findPath(request, paths, isMain);
- if (!filename) {
- const requireStack = [];
- for (let cursor: Module | null = parent; cursor; cursor = cursor.parent) {
- requireStack.push(cursor.filename || cursor.id);
- }
- let message = `Cannot find module '${request}'`;
- if (requireStack.length > 0) {
- message = message + "\nRequire stack:\n- " + requireStack.join("\n- ");
- }
- const err = new Error(message) as Error & {
- code: string;
- requireStack: string[];
- };
- err.code = "MODULE_NOT_FOUND";
- err.requireStack = requireStack;
- throw err;
- }
- return filename as string;
- }
-
- static _findPath(
- request: string,
- paths: string[],
- isMain: boolean,
- ): string | boolean {
- const absoluteRequest = path.isAbsolute(request);
- if (absoluteRequest) {
- paths = [""];
- } else if (!paths || paths.length === 0) {
- return false;
- }
-
- const cacheKey = request + "\x00" +
- (paths.length === 1 ? paths[0] : paths.join("\x00"));
- const entry = Module._pathCache[cacheKey];
- if (entry) {
- return entry;
- }
-
- let exts;
- let trailingSlash = request.length > 0 &&
- request.charCodeAt(request.length - 1) === CHAR_FORWARD_SLASH;
- if (!trailingSlash) {
- trailingSlash = /(?:^|\/)\.?\.$/.test(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;
- const basePath = resolveExports(curPath, request, absoluteRequest);
- let filename;
-
- const rc = stat(basePath);
- if (!trailingSlash) {
- if (rc === 0) {
- // File.
- // preserveSymlinks removed
- filename = toRealPath(basePath);
- }
-
- if (!filename) {
- // Try it with each of the extensions
- if (exts === undefined) exts = Object.keys(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 = Object.keys(Module._extensions);
- filename = tryPackage(basePath, exts, isMain, request);
- }
-
- if (filename) {
- Module._pathCache[cacheKey] = filename;
- return filename;
- }
- }
- // trySelf removed.
-
- return false;
- }
-
- // Check the cache for the requested file.
- // 1. If a module already exists in the cache: return its exports object.
- // 2. If the module is native: call
- // `NativeModule.prototype.compileForPublicLoader()` and return the exports.
- // 3. Otherwise, create a new module for the file and save it to the cache.
- // Then have it load the file contents before returning its exports
- // object.
- // deno-lint-ignore no-explicit-any
- static _load(request: string, parent: Module, isMain: boolean): any {
- let relResolveCacheIdentifier: string | undefined;
- 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);
-
- const cachedModule = Module._cache[filename];
- if (cachedModule !== undefined) {
- updateChildren(parent, cachedModule, true);
- if (!cachedModule.loaded) {
- return getExportsForCircularRequire(cachedModule);
- }
- return cachedModule.exports;
- }
-
- // Native module polyfills
- const mod = loadNativeModule(filename, request);
- if (mod) return mod.exports;
-
- // Don't call updateChildren(), Module constructor already does.
- const module = new Module(filename, parent);
-
- if (isMain) {
- // TODO(bartlomieju): set process info
- // process.mainModule = module;
- module.id = ".";
- }
-
- Module._cache[filename] = module;
- if (parent !== undefined) {
- assert(relResolveCacheIdentifier);
- relativeResolveCache[relResolveCacheIdentifier] = filename;
- }
-
- let threw = true;
- try {
- // Source map code removed
- module.load(filename);
- threw = false;
- } finally {
- if (threw) {
- delete Module._cache[filename];
- if (parent !== undefined) {
- assert(relResolveCacheIdentifier);
- delete relativeResolveCache[relResolveCacheIdentifier];
- }
- } else if (
- module.exports &&
- Object.getPrototypeOf(module.exports) ===
- CircularRequirePrototypeWarningProxy
- ) {
- Object.setPrototypeOf(module.exports, PublicObjectPrototype);
- }
- }
-
- return module.exports;
- }
-
- static wrap(script: string): string {
- return `${Module.wrapper[0]}${script}${Module.wrapper[1]}`;
- }
-
- static _nodeModulePaths(from: string): string[] {
- if (isWindows) {
- // Guarantee that 'from' is absolute.
- from = path.resolve(from);
-
- // note: this approach *only* works when the path is guaranteed
- // to be absolute. Doing a fully-edge-case-correct path.split
- // that works on both Windows and Posix is non-trivial.
-
- // return root node_modules when path is 'D:\\'.
- // path.resolve will make sure from.length >=3 in Windows.
- if (
- from.charCodeAt(from.length - 1) === CHAR_BACKWARD_SLASH &&
- from.charCodeAt(from.length - 2) === CHAR_COLON
- ) {
- return [from + "node_modules"];
- }
-
- const paths = [];
- for (let i = from.length - 1, p = 0, last = from.length; i >= 0; --i) {
- const code = from.charCodeAt(i);
- // The path segment separator check ('\' and '/') was used to get
- // node_modules path for every path segment.
- // Use colon as an extra condition since we can get node_modules
- // path for drive root like 'C:\node_modules' and don't need to
- // parse drive name.
- if (
- code === CHAR_BACKWARD_SLASH ||
- code === CHAR_FORWARD_SLASH ||
- code === CHAR_COLON
- ) {
- if (p !== nmLen) paths.push(from.slice(0, last) + "\\node_modules");
- last = i;
- p = 0;
- } else if (p !== -1) {
- if (nmChars[p] === code) {
- ++p;
- } else {
- p = -1;
- }
- }
- }
-
- return paths;
- } else {
- // posix
- // Guarantee that 'from' is absolute.
- from = path.resolve(from);
- // Return early not only to avoid unnecessary work, but to *avoid* returning
- // an array of two items for a root: [ '//node_modules', '/node_modules' ]
- if (from === "/") return ["/node_modules"];
-
- // note: this approach *only* works when the path is guaranteed
- // to be absolute. Doing a fully-edge-case-correct path.split
- // that works on both Windows and Posix is non-trivial.
- const paths = [];
- for (let i = from.length - 1, p = 0, last = from.length; i >= 0; --i) {
- const code = from.charCodeAt(i);
- if (code === CHAR_FORWARD_SLASH) {
- if (p !== nmLen) paths.push(from.slice(0, last) + "/node_modules");
- last = i;
- p = 0;
- } else if (p !== -1) {
- if (nmChars[p] === code) {
- ++p;
- } else {
- p = -1;
- }
- }
- }
-
- // Append /node_modules to handle root paths.
- paths.push("/node_modules");
-
- return paths;
- }
- }
-
- /**
- * Create a `require` function that can be used to import CJS modules.
- * Follows CommonJS resolution similar to that of Node.js,
- * with `node_modules` lookup and `index.js` lookup support.
- * Also injects available Node.js builtin module polyfills.
- *
- * const require = createRequire(import.meta.url);
- * const fs = require("fs");
- * const leftPad = require("left-pad");
- * const cjsModule = require("./cjs_mod");
- *
- * @param filename path or URL to current module
- * @return Require function to import CJS modules
- */
- static createRequire(filename: string | URL): RequireFunction {
- let filepath: string;
- if (
- filename instanceof URL ||
- (typeof filename === "string" && !path.isAbsolute(filename))
- ) {
- filepath = fileURLToPath(filename);
- } else if (typeof filename !== "string") {
- throw new Error("filename should be a string");
- } else {
- filepath = filename;
- }
- return createRequireFromPath(filepath);
- }
-
- static _initPaths(): void {
- const homeDir = Deno.env.get("HOME");
- const nodePath = Deno.env.get("NODE_PATH");
-
- // Removed $PREFIX/bin/node case
-
- let paths = [];
-
- if (homeDir) {
- paths.unshift(path.resolve(homeDir, ".node_libraries"));
- paths.unshift(path.resolve(homeDir, ".node_modules"));
- }
-
- if (nodePath) {
- paths = nodePath
- .split(path.delimiter)
- .filter(function pathsFilterCB(path) {
- return !!path;
- })
- .concat(paths);
- }
-
- modulePaths = paths;
-
- // Clone as a shallow copy, for introspection.
- Module.globalPaths = modulePaths.slice(0);
- }
-
- static _preloadModules(requests: string[]): void {
- if (!Array.isArray(requests)) {
- return;
- }
-
- // Preloaded modules have a dummy parent module which is deemed to exist
- // in the current working directory. This seeds the search path for
- // preloaded modules.
- const parent = new Module("internal/preload", null);
- try {
- parent.paths = Module._nodeModulePaths(Deno.cwd());
- } catch (e) {
- if (e.code !== "ENOENT") {
- throw e;
- }
- }
- for (let n = 0; n < requests.length; n++) {
- parent.require(requests[n]);
- }
- }
-}
-
-// Polyfills.
-const nativeModulePolyfill = new Map<string, Module>();
-// deno-lint-ignore no-explicit-any
-function createNativeModule(id: string, exports: any): Module {
- const mod = new Module(id);
- mod.exports = exports;
- mod.loaded = true;
- return mod;
-}
-
-nativeModulePolyfill.set("buffer", createNativeModule("buffer", nodeBuffer));
-nativeModulePolyfill.set("events", createNativeModule("events", nodeEvents));
-nativeModulePolyfill.set("fs", createNativeModule("fs", nodeFS));
-nativeModulePolyfill.set("os", createNativeModule("os", nodeOs));
-nativeModulePolyfill.set("path", createNativeModule("path", nodePath));
-nativeModulePolyfill.set(
- "querystring",
- createNativeModule("querystring", nodeQueryString),
-);
-nativeModulePolyfill.set(
- "stream",
- createNativeModule("string_decoder", nodeStream),
-);
-nativeModulePolyfill.set(
- "string_decoder",
- createNativeModule("string_decoder", nodeStringDecoder),
-);
-nativeModulePolyfill.set("timers", createNativeModule("timers", nodeTimers));
-nativeModulePolyfill.set("util", createNativeModule("util", nodeUtil));
-
-function loadNativeModule(
- _filename: string,
- request: string,
-): Module | undefined {
- return nativeModulePolyfill.get(request);
-}
-function nativeModuleCanBeRequiredByUsers(request: string): boolean {
- return nativeModulePolyfill.has(request);
-}
-// Populate with polyfill names
-for (const id of nativeModulePolyfill.keys()) {
- Module.builtinModules.push(id);
-}
-
-let modulePaths: string[] = [];
-
-// Given a module name, and a list of paths to test, returns the first
-// matching file in the following precedence.
-//
-// require("a.<ext>")
-// -> a.<ext>
-//
-// require("a")
-// -> a
-// -> a.<ext>
-// -> a/index.<ext>
-
-const packageJsonCache = new Map<string, PackageInfo | null>();
-
-interface PackageInfo {
- name?: string;
- main?: string;
- // deno-lint-ignore no-explicit-any
- exports?: any;
- // deno-lint-ignore no-explicit-any
- type?: any;
-}
-
-function readPackage(requestPath: string): PackageInfo | null {
- const jsonPath = path.resolve(requestPath, "package.json");
-
- const existing = packageJsonCache.get(jsonPath);
- if (existing !== undefined) {
- return existing;
- }
-
- let json: string | undefined;
- try {
- json = new TextDecoder().decode(
- Deno.readFileSync(path.toNamespacedPath(jsonPath)),
- );
- } catch {
- // pass
- }
-
- if (json === undefined) {
- packageJsonCache.set(jsonPath, null);
- return null;
- }
-
- try {
- const parsed = JSON.parse(json);
- const filtered = {
- name: parsed.name,
- main: parsed.main,
- exports: parsed.exports,
- type: parsed.type,
- };
- packageJsonCache.set(jsonPath, filtered);
- return filtered;
- } catch (e) {
- e.path = jsonPath;
- e.message = "Error parsing " + jsonPath + ": " + e.message;
- throw e;
- }
-}
-
-function readPackageScope(
- checkPath: string,
-): { path: string; data: PackageInfo } | false {
- const rootSeparatorIndex = checkPath.indexOf(path.sep);
- let separatorIndex;
- while (
- (separatorIndex = checkPath.lastIndexOf(path.sep)) > rootSeparatorIndex
- ) {
- checkPath = checkPath.slice(0, separatorIndex);
- if (checkPath.endsWith(path.sep + "node_modules")) return false;
- const pjson = readPackage(checkPath);
- if (pjson) {
- return {
- path: checkPath,
- data: pjson,
- };
- }
- }
- return false;
-}
-
-function readPackageMain(requestPath: string): string | undefined {
- const pkg = readPackage(requestPath);
- return pkg ? pkg.main : undefined;
-}
-
-// deno-lint-ignore no-explicit-any
-function readPackageExports(requestPath: string): any | undefined {
- const pkg = readPackage(requestPath);
- return pkg ? pkg.exports : undefined;
-}
-
-function tryPackage(
- requestPath: string,
- exts: string[],
- isMain: boolean,
- _originalPath: string,
-): string | false {
- const pkg = readPackageMain(requestPath);
-
- if (!pkg) {
- return tryExtensions(path.resolve(requestPath, "index"), exts, isMain);
- }
-
- const filename = path.resolve(requestPath, pkg);
- let actual = tryFile(filename, isMain) ||
- tryExtensions(filename, exts, isMain) ||
- tryExtensions(path.resolve(filename, "index"), exts, isMain);
- if (actual === false) {
- actual = tryExtensions(path.resolve(requestPath, "index"), exts, isMain);
- if (!actual) {
- const err = new Error(
- `Cannot find module '${filename}'. ` +
- 'Please verify that the package.json has a valid "main" entry',
- ) as Error & { code: string };
- err.code = "MODULE_NOT_FOUND";
- throw err;
- }
- }
- return actual;
-}
-
-// Check if the file exists and is not a directory
-// if using --preserve-symlinks and isMain is false,
-// keep symlinks intact, otherwise resolve to the
-// absolute realpath.
-function tryFile(requestPath: string, _isMain: boolean): string | false {
- const rc = stat(requestPath);
- return rc === 0 && toRealPath(requestPath);
-}
-
-function toRealPath(requestPath: string): string {
- return Deno.realPathSync(requestPath);
-}
-
-// Given a path, check if the file exists with any of the set extensions
-function tryExtensions(
- p: string,
- exts: string[],
- isMain: boolean,
-): string | false {
- 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: string): string {
- const name = path.basename(filename);
- let currentExtension;
- let index;
- let startIndex = 0;
- while ((index = name.indexOf(".", startIndex)) !== -1) {
- startIndex = index + 1;
- if (index === 0) continue; // Skip dotfiles like .gitignore
- currentExtension = name.slice(index);
- if (Module._extensions[currentExtension]) return currentExtension;
- }
- return ".js";
-}
-
-// --experimental-resolve-self trySelf() support removed.
-
-// deno-lint-ignore no-explicit-any
-function isConditionalDotExportSugar(exports: any, _basePath: string): boolean {
- if (typeof exports === "string") return true;
- if (Array.isArray(exports)) return true;
- if (typeof exports !== "object") return false;
- let isConditional = false;
- let firstCheck = true;
- for (const key of Object.keys(exports)) {
- const curIsConditional = key[0] !== ".";
- if (firstCheck) {
- firstCheck = false;
- isConditional = curIsConditional;
- } else if (isConditional !== curIsConditional) {
- throw new Error(
- '"exports" cannot ' +
- "contain some keys starting with '.' and some not. The exports " +
- "object must either be an object of package subpath keys or an " +
- "object of main entry condition name keys only.",
- );
- }
- }
- return isConditional;
-}
-
-function applyExports(basePath: string, expansion: string): string {
- const mappingKey = `.${expansion}`;
-
- let pkgExports = readPackageExports(basePath);
- if (pkgExports === undefined || pkgExports === null) {
- return path.resolve(basePath, mappingKey);
- }
-
- if (isConditionalDotExportSugar(pkgExports, basePath)) {
- pkgExports = { ".": pkgExports };
- }
-
- if (typeof pkgExports === "object") {
- if (Object.prototype.hasOwnProperty.call(pkgExports, mappingKey)) {
- const mapping = pkgExports[mappingKey];
- return resolveExportsTarget(
- pathToFileURL(basePath + "/"),
- mapping,
- "",
- basePath,
- mappingKey,
- );
- }
-
- // Fallback to CJS main lookup when no main export is defined
- if (mappingKey === ".") return basePath;
-
- let dirMatch = "";
- for (const candidateKey of Object.keys(pkgExports)) {
- if (candidateKey[candidateKey.length - 1] !== "/") continue;
- if (
- candidateKey.length > dirMatch.length &&
- mappingKey.startsWith(candidateKey)
- ) {
- dirMatch = candidateKey;
- }
- }
-
- if (dirMatch !== "") {
- const mapping = pkgExports[dirMatch];
- const subpath = mappingKey.slice(dirMatch.length);
- return resolveExportsTarget(
- pathToFileURL(basePath + "/"),
- mapping,
- subpath,
- basePath,
- mappingKey,
- );
- }
- }
- // Fallback to CJS main lookup when no main export is defined
- if (mappingKey === ".") return basePath;
-
- const e = new Error(
- `Package exports for '${basePath}' do not define ` +
- `a '${mappingKey}' subpath`,
- ) as Error & { code?: string };
- e.code = "MODULE_NOT_FOUND";
- throw e;
-}
-
-// This only applies to requests of a specific form:
-// 1. name/.*
-// 2. @scope/name/.*
-const EXPORTS_PATTERN = /^((?:@[^/\\%]+\/)?[^./\\%][^/\\%]*)(\/.*)?$/;
-function resolveExports(
- nmPath: string,
- request: string,
- absoluteRequest: boolean,
-): string {
- // The implementation's behavior is meant to mirror resolution in ESM.
- if (!absoluteRequest) {
- const [, name, expansion = ""] = request.match(EXPORTS_PATTERN) || [];
- if (!name) {
- return path.resolve(nmPath, request);
- }
-
- const basePath = path.resolve(nmPath, name);
- return applyExports(basePath, expansion);
- }
-
- return path.resolve(nmPath, request);
-}
-
-function resolveExportsTarget(
- pkgPath: URL,
- // deno-lint-ignore no-explicit-any
- target: any,
- subpath: string,
- basePath: string,
- mappingKey: string,
-): string {
- if (typeof target === "string") {
- if (
- target.startsWith("./") &&
- (subpath.length === 0 || target.endsWith("/"))
- ) {
- const resolvedTarget = new URL(target, pkgPath);
- const pkgPathPath = pkgPath.pathname;
- const resolvedTargetPath = resolvedTarget.pathname;
- if (
- resolvedTargetPath.startsWith(pkgPathPath) &&
- resolvedTargetPath.indexOf("/node_modules/", pkgPathPath.length - 1) ===
- -1
- ) {
- const resolved = new URL(subpath, resolvedTarget);
- const resolvedPath = resolved.pathname;
- if (
- resolvedPath.startsWith(resolvedTargetPath) &&
- resolvedPath.indexOf("/node_modules/", pkgPathPath.length - 1) === -1
- ) {
- return fileURLToPath(resolved);
- }
- }
- }
- } else if (Array.isArray(target)) {
- for (const targetValue of target) {
- if (Array.isArray(targetValue)) continue;
- try {
- return resolveExportsTarget(
- pkgPath,
- targetValue,
- subpath,
- basePath,
- mappingKey,
- );
- } catch (e) {
- if (e.code !== "MODULE_NOT_FOUND") throw e;
- }
- }
- } else if (typeof target === "object" && target !== null) {
- // removed experimentalConditionalExports
- if (Object.prototype.hasOwnProperty.call(target, "default")) {
- try {
- return resolveExportsTarget(
- pkgPath,
- target.default,
- subpath,
- basePath,
- mappingKey,
- );
- } catch (e) {
- if (e.code !== "MODULE_NOT_FOUND") throw e;
- }
- }
- }
- let e: Error & { code?: string };
- if (mappingKey !== ".") {
- e = new Error(
- `Package exports for '${basePath}' do not define a ` +
- `valid '${mappingKey}' target${subpath ? " for " + subpath : ""}`,
- );
- } else {
- e = new Error(`No valid exports main found for '${basePath}'`);
- }
- e.code = "MODULE_NOT_FOUND";
- throw e;
-}
-
-// 'node_modules' character codes reversed
-const nmChars = [115, 101, 108, 117, 100, 111, 109, 95, 101, 100, 111, 110];
-const nmLen = nmChars.length;
-
-// deno-lint-ignore no-explicit-any
-function emitCircularRequireWarning(prop: any): void {
- console.error(
- `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(
- {},
- {
- // deno-lint-ignore no-explicit-any
- get(target: Record<string, any>, prop: string): any {
- if (prop in target) return target[prop];
- emitCircularRequireWarning(prop);
- return undefined;
- },
-
- getOwnPropertyDescriptor(target, prop): PropertyDescriptor | undefined {
- if (Object.prototype.hasOwnProperty.call(target, prop)) {
- return Object.getOwnPropertyDescriptor(target, prop);
- }
- emitCircularRequireWarning(prop);
- return undefined;
- },
- },
-);
-
-// Object.prototype and ObjectProtoype refer to our 'primordials' versions
-// and are not identical to the versions on the global object.
-const PublicObjectPrototype = globalThis.Object.prototype;
-
-// deno-lint-ignore no-explicit-any
-function getExportsForCircularRequire(module: Module): any {
- if (
- module.exports &&
- Object.getPrototypeOf(module.exports) === PublicObjectPrototype &&
- // 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.
- Object.setPrototypeOf(module.exports, CircularRequirePrototypeWarningProxy);
- }
-
- return module.exports;
-}
-
-type RequireWrapper = (
- // deno-lint-ignore no-explicit-any
- exports: any,
- // deno-lint-ignore no-explicit-any
- require: any,
- module: Module,
- __filename: string,
- __dirname: string,
-) => void;
-
-function wrapSafe(filename: string, content: string): RequireWrapper {
- // TODO(bartlomieju): fix this
- const wrapper = Module.wrap(content);
- // deno-lint-ignore no-explicit-any
- const [f, err] = (Deno as any).core.evalContext(wrapper, filename);
- if (err) {
- throw err;
- }
- return f;
- // ESM code removed.
-}
-
-// Native extension for .js
-Module._extensions[".js"] = (module: Module, filename: string): void => {
- if (filename.endsWith(".js")) {
- const pkg = readPackageScope(filename);
- if (pkg !== false && pkg.data && pkg.data.type === "module") {
- throw new Error("Importing ESM module");
- }
- }
- const content = new TextDecoder().decode(Deno.readFileSync(filename));
- module._compile(content, filename);
-};
-
-// Native extension for .json
-Module._extensions[".json"] = (module: Module, filename: string): void => {
- const content = new TextDecoder().decode(Deno.readFileSync(filename));
- // manifest code removed
- try {
- module.exports = JSON.parse(stripBOM(content));
- } catch (err) {
- err.message = filename + ": " + err.message;
- throw err;
- }
-};
-
-// .node extension is not supported
-
-function createRequireFromPath(filename: string): RequireFunction {
- // Allow a directory to be passed as the filename
- const trailingSlash = filename.endsWith("/") ||
- (isWindows && filename.endsWith("\\"));
-
- const proxyPath = trailingSlash ? path.join(filename, "noop.js") : filename;
-
- const m = new Module(proxyPath);
- m.filename = proxyPath;
-
- m.paths = Module._nodeModulePaths(m.path);
- return makeRequireFunction(m);
-}
-
-// deno-lint-ignore no-explicit-any
-type Require = (id: string) => any;
-// deno-lint-ignore no-explicit-any
-type RequireResolve = (request: string, options: any) => string;
-interface RequireResolveFunction extends RequireResolve {
- paths: (request: string) => string[] | null;
-}
-
-interface RequireFunction extends Require {
- resolve: RequireResolveFunction;
- // deno-lint-ignore no-explicit-any
- extensions: { [key: string]: (module: Module, filename: string) => any };
- cache: { [key: string]: Module };
-}
-
-function makeRequireFunction(mod: Module): RequireFunction {
- // deno-lint-ignore no-explicit-any
- const require = function require(path: string): any {
- return mod.require(path);
- };
-
- function resolve(request: string, options?: { paths: string[] }): string {
- return Module._resolveFilename(request, mod, false, options);
- }
-
- require.resolve = resolve;
-
- function paths(request: string): string[] | null {
- return Module._resolveLookupPaths(request, mod);
- }
-
- resolve.paths = paths;
- // TODO(bartlomieju): set main
- // require.main = process.mainModule;
-
- // Enable support to add extra extension types.
- require.extensions = Module._extensions;
-
- require.cache = Module._cache;
-
- return require;
-}
-
-/**
- * Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)
- * because the buffer-to-string conversion in `fs.readFileSync()`
- * translates it to FEFF, the UTF-16 BOM.
- */
-function stripBOM(content: string): string {
- if (content.charCodeAt(0) === 0xfeff) {
- content = content.slice(1);
- }
- return content;
-}
-
-export const builtinModules = Module.builtinModules;
-export const createRequire = Module.createRequire;
-export default Module;