summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/modules.rs37
-rw-r--r--ext/node/lib.rs8
-rw-r--r--ext/node/polyfills/global.ts91
-rw-r--r--ext/node/polyfills/internal/blob.mjs7
-rw-r--r--ext/node/polyfills/internal/crypto/types.ts46
-rw-r--r--ext/node/polyfills/internal/freelist.ts30
-rw-r--r--ext/node/polyfills/internal/streams/legacy.mjs113
-rw-r--r--ext/node/polyfills/module.js20
-rw-r--r--ext/node/polyfills/module_esm.ts842
-rw-r--r--ext/node/polyfills/upstream_modules.ts39
10 files changed, 37 insertions, 1196 deletions
diff --git a/core/modules.rs b/core/modules.rs
index b6220bb3b..3d335f8eb 100644
--- a/core/modules.rs
+++ b/core/modules.rs
@@ -328,6 +328,7 @@ pub type InternalModuleLoaderCb =
pub struct InternalModuleLoader {
module_loader: Rc<dyn ModuleLoader>,
esm_sources: Vec<ExtensionFileSource>,
+ used_esm_sources: RefCell<HashMap<String, bool>>,
maybe_load_callback: Option<InternalModuleLoaderCb>,
}
@@ -336,6 +337,7 @@ impl Default for InternalModuleLoader {
Self {
module_loader: Rc::new(NoopModuleLoader),
esm_sources: vec![],
+ used_esm_sources: RefCell::new(HashMap::default()),
maybe_load_callback: None,
}
}
@@ -347,14 +349,43 @@ impl InternalModuleLoader {
esm_sources: Vec<ExtensionFileSource>,
maybe_load_callback: Option<InternalModuleLoaderCb>,
) -> Self {
+ let used_esm_sources: HashMap<String, bool> = esm_sources
+ .iter()
+ .map(|file_source| (file_source.specifier.to_string(), false))
+ .collect();
+
InternalModuleLoader {
module_loader: module_loader.unwrap_or_else(|| Rc::new(NoopModuleLoader)),
esm_sources,
+ used_esm_sources: RefCell::new(used_esm_sources),
maybe_load_callback,
}
}
}
+impl Drop for InternalModuleLoader {
+ fn drop(&mut self) {
+ let used_esm_sources = self.used_esm_sources.get_mut();
+ let unused_modules: Vec<_> = used_esm_sources
+ .iter()
+ .filter(|(_s, v)| !*v)
+ .map(|(s, _)| s)
+ .collect();
+
+ if !unused_modules.is_empty() {
+ let mut msg =
+ "Following modules were passed to InternalModuleLoader but never used:\n"
+ .to_string();
+ for m in unused_modules {
+ msg.push_str(" - ");
+ msg.push_str(m);
+ msg.push('\n');
+ }
+ panic!("{}", msg);
+ }
+ }
+}
+
impl ModuleLoader for InternalModuleLoader {
fn resolve(
&self,
@@ -400,6 +431,12 @@ impl ModuleLoader for InternalModuleLoader {
.find(|file_source| file_source.specifier == module_specifier.as_str());
if let Some(file_source) = maybe_file_source {
+ {
+ let mut used_esm_sources = self.used_esm_sources.borrow_mut();
+ let used = used_esm_sources.get_mut(&file_source.specifier).unwrap();
+ *used = true;
+ }
+
let result = if let Some(load_callback) = &self.maybe_load_callback {
load_callback(file_source)
} else {
diff --git a/ext/node/lib.rs b/ext/node/lib.rs
index d84b26339..6df408ffd 100644
--- a/ext/node/lib.rs
+++ b/ext/node/lib.rs
@@ -179,7 +179,6 @@ pub fn init_polyfill() -> Extension {
"events.ts",
"fs.ts",
"fs/promises.ts",
- "global.ts",
"http.ts",
"http2.ts",
"https.ts",
@@ -211,7 +210,6 @@ pub fn init_polyfill() -> Extension {
"internal_binding/uv.ts",
"internal/assert.mjs",
"internal/async_hooks.ts",
- "internal/blob.mjs",
"internal/buffer.mjs",
"internal/child_process.ts",
"internal/cli_table.ts",
@@ -234,7 +232,6 @@ pub fn init_polyfill() -> Extension {
"internal/crypto/random.ts",
"internal/crypto/scrypt.ts",
"internal/crypto/sig.ts",
- "internal/crypto/types.ts",
"internal/crypto/util.ts",
"internal/crypto/x509.ts",
"internal/dgram.ts",
@@ -245,7 +242,6 @@ pub fn init_polyfill() -> Extension {
"internal/errors.ts",
"internal/event_target.mjs",
"internal/fixed_queue.ts",
- "internal/freelist.ts",
"internal/fs/streams.mjs",
"internal/fs/utils.mjs",
"internal/hide_stack_frames.ts",
@@ -270,7 +266,6 @@ pub fn init_polyfill() -> Extension {
"internal/streams/duplex.mjs",
"internal/streams/end-of-stream.mjs",
"internal/streams/lazy_transform.mjs",
- "internal/streams/legacy.mjs",
"internal/streams/passthrough.mjs",
"internal/streams/readable.mjs",
"internal/streams/state.mjs",
@@ -287,8 +282,6 @@ pub fn init_polyfill() -> Extension {
"internal/util/types.ts",
"internal/validators.mjs",
"module_all.ts",
- "module_esm.ts",
- "module.js",
"net.ts",
"os.ts",
"path.ts",
@@ -318,7 +311,6 @@ pub fn init_polyfill() -> Extension {
"timers/promises.ts",
"tls.ts",
"tty.ts",
- "upstream_modules.ts",
"url.ts",
"util.ts",
"util/types.ts",
diff --git a/ext/node/polyfills/global.ts b/ext/node/polyfills/global.ts
deleted file mode 100644
index 2ab33921c..000000000
--- a/ext/node/polyfills/global.ts
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-// deno-lint-ignore-file no-var
-import processModule from "internal:deno_node/process.ts";
-import { Buffer as bufferModule } from "internal:deno_node/buffer.ts";
-import {
- clearInterval,
- clearTimeout,
- setInterval,
- setTimeout,
-} from "internal:deno_node/timers.ts";
-import timers from "internal:deno_node/timers.ts";
-
-type GlobalType = {
- process: typeof processModule;
- Buffer: typeof bufferModule;
- setImmediate: typeof timers.setImmediate;
- clearImmediate: typeof timers.clearImmediate;
- setTimeout: typeof timers.setTimeout;
- clearTimeout: typeof timers.clearTimeout;
- setInterval: typeof timers.setInterval;
- clearInterval: typeof timers.clearInterval;
-};
-
-declare global {
- interface Window {
- global: GlobalType;
- }
-
- interface globalThis {
- global: GlobalType;
- }
-
- var global: GlobalType;
- var process: typeof processModule;
- var Buffer: typeof bufferModule;
- type Buffer = bufferModule;
- var setImmediate: typeof timers.setImmediate;
- var clearImmediate: typeof timers.clearImmediate;
-}
-
-Object.defineProperty(globalThis, "global", {
- value: new Proxy(globalThis, {
- get(target, prop, receiver) {
- switch (prop) {
- case "setInterval":
- return setInterval;
- case "setTimeout":
- return setTimeout;
- case "clearInterval":
- return clearInterval;
- case "clearTimeout":
- return clearTimeout;
- default:
- return Reflect.get(target, prop, receiver);
- }
- },
- }),
- writable: false,
- enumerable: false,
- configurable: true,
-});
-
-Object.defineProperty(globalThis, "process", {
- value: processModule,
- enumerable: false,
- writable: true,
- configurable: true,
-});
-
-Object.defineProperty(globalThis, "Buffer", {
- value: bufferModule,
- enumerable: false,
- writable: true,
- configurable: true,
-});
-
-Object.defineProperty(globalThis, "setImmediate", {
- value: timers.setImmediate,
- enumerable: true,
- writable: true,
- configurable: true,
-});
-
-Object.defineProperty(globalThis, "clearImmediate", {
- value: timers.clearImmediate,
- enumerable: true,
- writable: true,
- configurable: true,
-});
-
-export {};
diff --git a/ext/node/polyfills/internal/blob.mjs b/ext/node/polyfills/internal/blob.mjs
deleted file mode 100644
index 1b685fad4..000000000
--- a/ext/node/polyfills/internal/blob.mjs
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-// Node's implementation checks for a symbol they put in the blob prototype
-// Since the implementation of Blob is Deno's, the only option is to check the
-// objects constructor
-export function isBlob(object) {
- return object instanceof Blob;
-}
diff --git a/ext/node/polyfills/internal/crypto/types.ts b/ext/node/polyfills/internal/crypto/types.ts
deleted file mode 100644
index 3231d378e..000000000
--- a/ext/node/polyfills/internal/crypto/types.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-// Copyright Joyent, Inc. and Node.js contributors. All rights reserved. MIT license.
-
-import { Buffer } from "internal:deno_node/buffer.ts";
-
-export type HASH_DATA = string | ArrayBufferView | Buffer;
-
-export type BinaryToTextEncoding = "base64" | "base64url" | "hex" | "binary";
-
-export type CharacterEncoding = "utf8" | "utf-8" | "utf16le" | "latin1";
-
-export type LegacyCharacterEncoding = "ascii" | "binary" | "ucs2" | "ucs-2";
-
-export type Encoding =
- | BinaryToTextEncoding
- | CharacterEncoding
- | LegacyCharacterEncoding;
-
-export type ECDHKeyFormat = "compressed" | "uncompressed" | "hybrid";
-
-export type BinaryLike = string | ArrayBufferView;
-
-export type KeyFormat = "pem" | "der";
-
-export type KeyType =
- | "rsa"
- | "rsa-pss"
- | "dsa"
- | "ec"
- | "ed25519"
- | "ed448"
- | "x25519"
- | "x448";
-
-export interface PrivateKeyInput {
- key: string | Buffer;
- format?: KeyFormat | undefined;
- type?: "pkcs1" | "pkcs8" | "sec1" | undefined;
- passphrase?: string | Buffer | undefined;
-}
-
-export interface PublicKeyInput {
- key: string | Buffer;
- format?: KeyFormat | undefined;
- type?: "pkcs1" | "spki" | undefined;
-}
diff --git a/ext/node/polyfills/internal/freelist.ts b/ext/node/polyfills/internal/freelist.ts
deleted file mode 100644
index 8faba8e68..000000000
--- a/ext/node/polyfills/internal/freelist.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-// Copyright Joyent and Node contributors. All rights reserved. MIT license.
-
-type Fn<T> = (...args: unknown[]) => T;
-export class FreeList<T> {
- name: string;
- ctor: Fn<T>;
- max: number;
- list: Array<T>;
- constructor(name: string, max: number, ctor: Fn<T>) {
- this.name = name;
- this.ctor = ctor;
- this.max = max;
- this.list = [];
- }
-
- alloc(): T {
- return this.list.length > 0
- ? this.list.pop()
- : Reflect.apply(this.ctor, this, arguments);
- }
-
- free(obj: T) {
- if (this.list.length < this.max) {
- this.list.push(obj);
- return true;
- }
- return false;
- }
-}
diff --git a/ext/node/polyfills/internal/streams/legacy.mjs b/ext/node/polyfills/internal/streams/legacy.mjs
deleted file mode 100644
index bb2d30bc4..000000000
--- a/ext/node/polyfills/internal/streams/legacy.mjs
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-// Copyright Joyent and Node contributors. All rights reserved. MIT license.
-// deno-lint-ignore-file
-
-import EE from "internal:deno_node/events.ts";
-
-function Stream(opts) {
- EE.call(this, opts);
-}
-Object.setPrototypeOf(Stream.prototype, EE.prototype);
-Object.setPrototypeOf(Stream, EE);
-
-Stream.prototype.pipe = function (dest, options) {
- // deno-lint-ignore no-this-alias
- const source = this;
-
- function ondata(chunk) {
- if (dest.writable && dest.write(chunk) === false && source.pause) {
- source.pause();
- }
- }
-
- source.on("data", ondata);
-
- function ondrain() {
- if (source.readable && source.resume) {
- source.resume();
- }
- }
-
- dest.on("drain", ondrain);
-
- // If the 'end' option is not supplied, dest.end() will be called when
- // source gets the 'end' or 'close' events. Only dest.end() once.
- if (!dest._isStdio && (!options || options.end !== false)) {
- source.on("end", onend);
- source.on("close", onclose);
- }
-
- let didOnEnd = false;
- function onend() {
- if (didOnEnd) return;
- didOnEnd = true;
-
- dest.end();
- }
-
- function onclose() {
- if (didOnEnd) return;
- didOnEnd = true;
-
- if (typeof dest.destroy === "function") dest.destroy();
- }
-
- // Don't leave dangling pipes when there are errors.
- function onerror(er) {
- cleanup();
- if (EE.listenerCount(this, "error") === 0) {
- this.emit("error", er);
- }
- }
-
- prependListener(source, "error", onerror);
- prependListener(dest, "error", onerror);
-
- // Remove all the event listeners that were added.
- function cleanup() {
- source.removeListener("data", ondata);
- dest.removeListener("drain", ondrain);
-
- source.removeListener("end", onend);
- source.removeListener("close", onclose);
-
- source.removeListener("error", onerror);
- dest.removeListener("error", onerror);
-
- source.removeListener("end", cleanup);
- source.removeListener("close", cleanup);
-
- dest.removeListener("close", cleanup);
- }
-
- source.on("end", cleanup);
- source.on("close", cleanup);
-
- dest.on("close", cleanup);
- dest.emit("pipe", source);
-
- // Allow for unix-like usage: A.pipe(B).pipe(C)
- return dest;
-};
-
-function prependListener(emitter, event, fn) {
- // Sadly this is not cacheable as some libraries bundle their own
- // event emitter implementation with them.
- if (typeof emitter.prependListener === "function") {
- return emitter.prependListener(event, fn);
- }
-
- // This is a hack to make sure that our error handler is attached before any
- // userland ones. NEVER DO THIS. This is here only because this code needs
- // to continue to work with older versions of Node.js that do not include
- // the prependListener() method. The goal is to eventually remove this hack.
- if (!emitter._events || !emitter._events[event]) {
- emitter.on(event, fn);
- } else if (Array.isArray(emitter._events[event])) {
- emitter._events[event].unshift(fn);
- } else {
- emitter._events[event] = [fn, emitter._events[event]];
- }
-}
-
-export { prependListener, Stream };
diff --git a/ext/node/polyfills/module.js b/ext/node/polyfills/module.js
deleted file mode 100644
index 2b7c20e26..000000000
--- a/ext/node/polyfills/module.js
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-
-const internals = globalThis.__bootstrap.internals;
-const m = internals.require.Module;
-export const _cache = m._cache;
-export const _extensions = m._extensions;
-export const _findPath = m._findPath;
-export const _initPaths = m._initPaths;
-export const _load = m._load;
-export const _nodeModulePaths = m._nodeModulePaths;
-export const _pathCache = m._pathCache;
-export const _preloadModules = m._preloadModules;
-export const _resolveFilename = m._resolveFilename;
-export const _resolveLookupPaths = m._resolveLookupPaths;
-export const builtinModules = m.builtinModules;
-export const createRequire = m.createRequire;
-export const globalPaths = m.globalPaths;
-export const Module = m.Module;
-export const wrap = m.wrap;
-export default m;
diff --git a/ext/node/polyfills/module_esm.ts b/ext/node/polyfills/module_esm.ts
deleted file mode 100644
index 5b1cef0bb..000000000
--- a/ext/node/polyfills/module_esm.ts
+++ /dev/null
@@ -1,842 +0,0 @@
-// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-// 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.
-
-/**
- * NOTE(bartlomieju):
- * Functionality of this file is ported in Rust in `cli/compat/esm_resolver.ts`.
- * Unfortunately we have no way to call ESM resolution in Rust from TypeScript code.
- */
-
-import { fileURLToPath, pathToFileURL } from "internal:deno_node/url.ts";
-import {
- ERR_INVALID_MODULE_SPECIFIER,
- ERR_INVALID_PACKAGE_CONFIG,
- ERR_INVALID_PACKAGE_TARGET,
- ERR_MODULE_NOT_FOUND,
- ERR_PACKAGE_IMPORT_NOT_DEFINED,
- ERR_PACKAGE_PATH_NOT_EXPORTED,
- NodeError,
-} from "internal:deno_node/internal/errors.ts";
-
-const { hasOwn } = Object;
-
-export const encodedSepRegEx = /%2F|%2C/i;
-
-function throwInvalidSubpath(
- subpath: string,
- packageJSONUrl: string,
- internal: boolean,
- base: string,
-) {
- const reason = `request is not a valid subpath for the "${
- internal ? "imports" : "exports"
- }" resolution of ${fileURLToPath(packageJSONUrl)}`;
- throw new ERR_INVALID_MODULE_SPECIFIER(
- subpath,
- reason,
- base && fileURLToPath(base),
- );
-}
-
-function throwInvalidPackageTarget(
- subpath: string,
- // deno-lint-ignore no-explicit-any
- target: any,
- packageJSONUrl: string,
- internal: boolean,
- base: string,
-) {
- if (typeof target === "object" && target !== null) {
- target = JSON.stringify(target, null, "");
- } else {
- target = `${target}`;
- }
- throw new ERR_INVALID_PACKAGE_TARGET(
- fileURLToPath(new URL(".", packageJSONUrl)),
- subpath,
- target,
- internal,
- base && fileURLToPath(base),
- );
-}
-
-function throwImportNotDefined(
- specifier: string,
- packageJSONUrl: URL | undefined,
- base: string | URL,
-): TypeError & { code: string } {
- throw new ERR_PACKAGE_IMPORT_NOT_DEFINED(
- specifier,
- packageJSONUrl && fileURLToPath(new URL(".", packageJSONUrl)),
- fileURLToPath(base),
- );
-}
-
-function throwExportsNotFound(
- subpath: string,
- packageJSONUrl: string,
- base?: string,
-): Error & { code: string } {
- throw new ERR_PACKAGE_PATH_NOT_EXPORTED(
- subpath,
- fileURLToPath(new URL(".", packageJSONUrl)),
- base && fileURLToPath(base),
- );
-}
-
-function patternKeyCompare(a: string, b: string): number {
- const aPatternIndex = a.indexOf("*");
- const bPatternIndex = b.indexOf("*");
- const baseLenA = aPatternIndex === -1 ? a.length : aPatternIndex + 1;
- const baseLenB = bPatternIndex === -1 ? b.length : bPatternIndex + 1;
- if (baseLenA > baseLenB) return -1;
- if (baseLenB > baseLenA) return 1;
- if (aPatternIndex === -1) return 1;
- if (bPatternIndex === -1) return -1;
- if (a.length > b.length) return -1;
- if (b.length > a.length) return 1;
- return 0;
-}
-
-function fileExists(url: string | URL): boolean {
- try {
- const info = Deno.statSync(url);
- return info.isFile;
- } catch {
- return false;
- }
-}
-
-function tryStatSync(path: string): { isDirectory: boolean } {
- try {
- const info = Deno.statSync(path);
- return { isDirectory: info.isDirectory };
- } catch {
- return { isDirectory: false };
- }
-}
-
-/**
- * Legacy CommonJS main resolution:
- * 1. let M = pkg_url + (json main field)
- * 2. TRY(M, M.js, M.json, M.node)
- * 3. TRY(M/index.js, M/index.json, M/index.node)
- * 4. TRY(pkg_url/index.js, pkg_url/index.json, pkg_url/index.node)
- * 5. NOT_FOUND
- */
-function legacyMainResolve(
- packageJSONUrl: URL,
- packageConfig: PackageConfig,
- base: string | URL,
-): URL {
- let guess;
- if (packageConfig.main !== undefined) {
- // Note: fs check redundances will be handled by Descriptor cache here.
- if (
- fileExists(guess = new URL(`./${packageConfig.main}`, packageJSONUrl))
- ) {
- return guess;
- } else if (
- fileExists(guess = new URL(`./${packageConfig.main}.js`, packageJSONUrl))
- ) {
- // pass
- } else if (
- fileExists(
- guess = new URL(`./${packageConfig.main}.json`, packageJSONUrl),
- )
- ) {
- // pass
- } else if (
- fileExists(
- guess = new URL(`./${packageConfig.main}.node`, packageJSONUrl),
- )
- ) {
- // pass
- } else if (
- fileExists(
- guess = new URL(`./${packageConfig.main}/index.js`, packageJSONUrl),
- )
- ) {
- // pass
- } else if (
- fileExists(
- guess = new URL(`./${packageConfig.main}/index.json`, packageJSONUrl),
- )
- ) {
- // pass
- } else if (
- fileExists(
- guess = new URL(`./${packageConfig.main}/index.node`, packageJSONUrl),
- )
- ) {
- // pass
- } else guess = undefined;
- if (guess) {
- // TODO(bartlomieju):
- // emitLegacyIndexDeprecation(guess, packageJSONUrl, base,
- // packageConfig.main);
- return guess;
- }
- // Fallthrough.
- }
- if (fileExists(guess = new URL("./index.js", packageJSONUrl))) {
- // pass
- } // So fs.
- else if (fileExists(guess = new URL("./index.json", packageJSONUrl))) {
- // pass
- } else if (fileExists(guess = new URL("./index.node", packageJSONUrl))) {
- // pass
- } else guess = undefined;
- if (guess) {
- // TODO(bartlomieju):
- // emitLegacyIndexDeprecation(guess, packageJSONUrl, base, packageConfig.main);
- return guess;
- }
- // Not found.
- throw new ERR_MODULE_NOT_FOUND(
- fileURLToPath(new URL(".", packageJSONUrl)),
- fileURLToPath(base),
- );
-}
-
-function parsePackageName(
- specifier: string,
- base: string | URL,
-): { packageName: string; packageSubpath: string; isScoped: boolean } {
- let separatorIndex = specifier.indexOf("/");
- let validPackageName = true;
- let isScoped = false;
- if (specifier[0] === "@") {
- isScoped = true;
- if (separatorIndex === -1 || specifier.length === 0) {
- validPackageName = false;
- } else {
- separatorIndex = specifier.indexOf("/", separatorIndex + 1);
- }
- }
-
- const packageName = separatorIndex === -1
- ? specifier
- : specifier.slice(0, separatorIndex);
-
- // Package name cannot have leading . and cannot have percent-encoding or
- // separators.
- for (let i = 0; i < packageName.length; i++) {
- if (packageName[i] === "%" || packageName[i] === "\\") {
- validPackageName = false;
- break;
- }
- }
-
- if (!validPackageName) {
- throw new ERR_INVALID_MODULE_SPECIFIER(
- specifier,
- "is not a valid package name",
- fileURLToPath(base),
- );
- }
-
- const packageSubpath = "." +
- (separatorIndex === -1 ? "" : specifier.slice(separatorIndex));
-
- return { packageName, packageSubpath, isScoped };
-}
-
-function packageResolve(
- specifier: string,
- base: string,
- conditions: Set<string>,
-): URL | undefined {
- const { packageName, packageSubpath, isScoped } = parsePackageName(
- specifier,
- base,
- );
-
- // ResolveSelf
- const packageConfig = getPackageScopeConfig(base);
- if (packageConfig.exists) {
- const packageJSONUrl = pathToFileURL(packageConfig.pjsonPath);
- if (
- packageConfig.name === packageName &&
- packageConfig.exports !== undefined && packageConfig.exports !== null
- ) {
- return packageExportsResolve(
- packageJSONUrl.toString(),
- packageSubpath,
- packageConfig,
- base,
- conditions,
- );
- }
- }
-
- let packageJSONUrl = new URL(
- "./node_modules/" + packageName + "/package.json",
- base,
- );
- let packageJSONPath = fileURLToPath(packageJSONUrl);
- let lastPath;
- do {
- const stat = tryStatSync(
- packageJSONPath.slice(0, packageJSONPath.length - 13),
- );
- if (!stat.isDirectory) {
- lastPath = packageJSONPath;
- packageJSONUrl = new URL(
- (isScoped ? "../../../../node_modules/" : "../../../node_modules/") +
- packageName + "/package.json",
- packageJSONUrl,
- );
- packageJSONPath = fileURLToPath(packageJSONUrl);
- continue;
- }
-
- // Package match.
- const packageConfig = getPackageConfig(packageJSONPath, specifier, base);
- if (packageConfig.exports !== undefined && packageConfig.exports !== null) {
- return packageExportsResolve(
- packageJSONUrl.toString(),
- packageSubpath,
- packageConfig,
- base,
- conditions,
- );
- }
- if (packageSubpath === ".") {
- return legacyMainResolve(packageJSONUrl, packageConfig, base);
- }
- return new URL(packageSubpath, packageJSONUrl);
- // Cross-platform root check.
- } while (packageJSONPath.length !== lastPath.length);
-
- // TODO(bartlomieju): this is false positive
- // deno-lint-ignore no-unreachable
- throw new ERR_MODULE_NOT_FOUND(packageName, fileURLToPath(base));
-}
-
-const invalidSegmentRegEx = /(^|\\|\/)(\.\.?|node_modules)(\\|\/|$)/;
-const patternRegEx = /\*/g;
-
-function resolvePackageTargetString(
- target: string,
- subpath: string,
- match: string,
- packageJSONUrl: string,
- base: string,
- pattern: boolean,
- internal: boolean,
- conditions: Set<string>,
-): URL | undefined {
- if (subpath !== "" && !pattern && target[target.length - 1] !== "/") {
- throwInvalidPackageTarget(match, target, packageJSONUrl, internal, base);
- }
-
- if (!target.startsWith("./")) {
- if (
- internal && !target.startsWith("../") &&
- !target.startsWith("/")
- ) {
- let isURL = false;
- try {
- new URL(target);
- isURL = true;
- } catch {
- // pass
- }
- if (!isURL) {
- const exportTarget = pattern
- ? target.replace(patternRegEx, () => subpath)
- : target + subpath;
- return packageResolve(exportTarget, packageJSONUrl, conditions);
- }
- }
- throwInvalidPackageTarget(match, target, packageJSONUrl, internal, base);
- }
-
- if (invalidSegmentRegEx.test(target.slice(2))) {
- throwInvalidPackageTarget(match, target, packageJSONUrl, internal, base);
- }
-
- const resolved = new URL(target, packageJSONUrl);
- const resolvedPath = resolved.pathname;
- const packagePath = new URL(".", packageJSONUrl).pathname;
-
- if (!resolvedPath.startsWith(packagePath)) {
- throwInvalidPackageTarget(match, target, packageJSONUrl, internal, base);
- }
-
- if (subpath === "") return resolved;
-
- if (invalidSegmentRegEx.test(subpath)) {
- const request = pattern
- ? match.replace("*", () => subpath)
- : match + subpath;
- throwInvalidSubpath(request, packageJSONUrl, internal, base);
- }
-
- if (pattern) {
- return new URL(resolved.href.replace(patternRegEx, () => subpath));
- }
- return new URL(subpath, resolved);
-}
-
-function isArrayIndex(key: string): boolean {
- const keyNum = +key;
- if (`${keyNum}` !== key) return false;
- return keyNum >= 0 && keyNum < 0xFFFF_FFFF;
-}
-
-function resolvePackageTarget(
- packageJSONUrl: string,
- // deno-lint-ignore no-explicit-any
- target: any,
- subpath: string,
- packageSubpath: string,
- base: string,
- pattern: boolean,
- internal: boolean,
- conditions: Set<string>,
-): URL | undefined {
- if (typeof target === "string") {
- return resolvePackageTargetString(
- target,
- subpath,
- packageSubpath,
- packageJSONUrl,
- base,
- pattern,
- internal,
- conditions,
- );
- } else if (Array.isArray(target)) {
- if (target.length === 0) {
- return undefined;
- }
-
- let lastException;
- for (let i = 0; i < target.length; i++) {
- const targetItem = target[i];
- let resolved;
- try {
- resolved = resolvePackageTarget(
- packageJSONUrl,
- targetItem,
- subpath,
- packageSubpath,
- base,
- pattern,
- internal,
- conditions,
- );
- } catch (e: unknown) {
- lastException = e;
- if (e instanceof NodeError && e.code === "ERR_INVALID_PACKAGE_TARGET") {
- continue;
- }
- throw e;
- }
- if (resolved === undefined) {
- continue;
- }
- if (resolved === null) {
- lastException = null;
- continue;
- }
- return resolved;
- }
- if (lastException === undefined || lastException === null) {
- return undefined;
- }
- throw lastException;
- } else if (typeof target === "object" && target !== null) {
- const keys = Object.getOwnPropertyNames(target);
- for (let i = 0; i < keys.length; i++) {
- const key = keys[i];
- if (isArrayIndex(key)) {
- throw new ERR_INVALID_PACKAGE_CONFIG(
- fileURLToPath(packageJSONUrl),
- base,
- '"exports" cannot contain numeric property keys.',
- );
- }
- }
- for (let i = 0; i < keys.length; i++) {
- const key = keys[i];
- if (key === "default" || conditions.has(key)) {
- const conditionalTarget = target[key];
- const resolved = resolvePackageTarget(
- packageJSONUrl,
- conditionalTarget,
- subpath,
- packageSubpath,
- base,
- pattern,
- internal,
- conditions,
- );
- if (resolved === undefined) {
- continue;
- }
- return resolved;
- }
- }
- return undefined;
- } else if (target === null) {
- return undefined;
- }
- throwInvalidPackageTarget(
- packageSubpath,
- target,
- packageJSONUrl,
- internal,
- base,
- );
-}
-
-export function packageExportsResolve(
- packageJSONUrl: string,
- packageSubpath: string,
- packageConfig: PackageConfig,
- base: string,
- conditions: Set<string>,
- // @ts-ignore `URL` needs to be forced due to control flow
-): URL {
- let exports = packageConfig.exports;
- if (isConditionalExportsMainSugar(exports, packageJSONUrl, base)) {
- exports = { ".": exports };
- }
-
- if (
- hasOwn(exports, packageSubpath) &&
- !packageSubpath.includes("*") &&
- !packageSubpath.endsWith("/")
- ) {
- const target = exports[packageSubpath];
- const resolved = resolvePackageTarget(
- packageJSONUrl,
- target,
- "",
- packageSubpath,
- base,
- false,
- false,
- conditions,
- );
- if (resolved === null || resolved === undefined) {
- throwExportsNotFound(packageSubpath, packageJSONUrl, base);
- }
- return resolved!;
- }
-
- let bestMatch = "";
- let bestMatchSubpath = "";
- const keys = Object.getOwnPropertyNames(exports);
- for (let i = 0; i < keys.length; i++) {
- const key = keys[i];
- const patternIndex = key.indexOf("*");
- if (
- patternIndex !== -1 &&
- packageSubpath.startsWith(key.slice(0, patternIndex))
- ) {
- // When this reaches EOL, this can throw at the top of the whole function:
- //
- // if (StringPrototypeEndsWith(packageSubpath, '/'))
- // throwInvalidSubpath(packageSubpath)
- //
- // To match "imports" and the spec.
- if (packageSubpath.endsWith("/")) {
- // TODO(@bartlomieju):
- // emitTrailingSlashPatternDeprecation(
- // packageSubpath,
- // packageJSONUrl,
- // base,
- // );
- }
- const patternTrailer = key.slice(patternIndex + 1);
- if (
- packageSubpath.length >= key.length &&
- packageSubpath.endsWith(patternTrailer) &&
- patternKeyCompare(bestMatch, key) === 1 &&
- key.lastIndexOf("*") === patternIndex
- ) {
- bestMatch = key;
- bestMatchSubpath = packageSubpath.slice(
- patternIndex,
- packageSubpath.length - patternTrailer.length,
- );
- }
- }
- }
-
- if (bestMatch) {
- const target = exports[bestMatch];
- const resolved = resolvePackageTarget(
- packageJSONUrl,
- target,
- bestMatchSubpath,
- bestMatch,
- base,
- true,
- false,
- conditions,
- );
- if (resolved === null || resolved === undefined) {
- throwExportsNotFound(packageSubpath, packageJSONUrl, base);
- }
- return resolved!;
- }
-
- throwExportsNotFound(packageSubpath, packageJSONUrl, base);
-}
-
-export interface PackageConfig {
- pjsonPath: string;
- exists: boolean;
- name?: string;
- main?: string;
- // deno-lint-ignore no-explicit-any
- exports?: any;
- // deno-lint-ignore no-explicit-any
- imports?: any;
- type?: string;
-}
-
-const packageJSONCache = new Map(); /* string -> PackageConfig */
-
-function getPackageConfig(
- path: string,
- specifier: string | URL,
- base?: string | URL,
-): PackageConfig {
- const existing = packageJSONCache.get(path);
- if (existing !== undefined) {
- return existing;
- }
-
- let source: string | undefined;
- try {
- source = new TextDecoder().decode(
- Deno.readFileSync(path),
- );
- } catch {
- // pass
- }
-
- if (source === undefined) {
- const packageConfig = {
- pjsonPath: path,
- exists: false,
- main: undefined,
- name: undefined,
- type: "none",
- exports: undefined,
- imports: undefined,
- };
- packageJSONCache.set(path, packageConfig);
- return packageConfig;
- }
-
- let packageJSON;
- try {
- packageJSON = JSON.parse(source);
- } catch (error) {
- throw new ERR_INVALID_PACKAGE_CONFIG(
- path,
- (base ? `"${specifier}" from ` : "") + fileURLToPath(base || specifier),
- // @ts-ignore there's no assertion for type and `error` is thus `unknown`
- error.message,
- );
- }
-
- let { imports, main, name, type } = packageJSON;
- const { exports } = packageJSON;
- if (typeof imports !== "object" || imports === null) imports = undefined;
- if (typeof main !== "string") main = undefined;
- if (typeof name !== "string") name = undefined;
- // Ignore unknown types for forwards compatibility
- if (type !== "module" && type !== "commonjs") type = "none";
-
- const packageConfig = {
- pjsonPath: path,
- exists: true,
- main,
- name,
- type,
- exports,
- imports,
- };
- packageJSONCache.set(path, packageConfig);
- return packageConfig;
-}
-
-function getPackageScopeConfig(resolved: URL | string): PackageConfig {
- let packageJSONUrl = new URL("./package.json", resolved);
- while (true) {
- const packageJSONPath = packageJSONUrl.pathname;
- if (packageJSONPath.endsWith("node_modules/package.json")) {
- break;
- }
- const packageConfig = getPackageConfig(
- fileURLToPath(packageJSONUrl),
- resolved,
- );
- if (packageConfig.exists) return packageConfig;
-
- const lastPackageJSONUrl = packageJSONUrl;
- packageJSONUrl = new URL("../package.json", packageJSONUrl);
-
- // Terminates at root where ../package.json equals ../../package.json
- // (can't just check "/package.json" for Windows support).
- if (packageJSONUrl.pathname === lastPackageJSONUrl.pathname) break;
- }
- const packageJSONPath = fileURLToPath(packageJSONUrl);
- const packageConfig = {
- pjsonPath: packageJSONPath,
- exists: false,
- main: undefined,
- name: undefined,
- type: "none",
- exports: undefined,
- imports: undefined,
- };
- packageJSONCache.set(packageJSONPath, packageConfig);
- return packageConfig;
-}
-
-export function packageImportsResolve(
- name: string,
- base: string,
- conditions: Set<string>,
- // @ts-ignore `URL` needs to be forced due to control flow
-): URL {
- if (
- name === "#" || name.startsWith("#/") ||
- name.startsWith("/")
- ) {
- const reason = "is not a valid internal imports specifier name";
- throw new ERR_INVALID_MODULE_SPECIFIER(name, reason, fileURLToPath(base));
- }
- let packageJSONUrl;
- const packageConfig = getPackageScopeConfig(base);
- if (packageConfig.exists) {
- packageJSONUrl = pathToFileURL(packageConfig.pjsonPath);
- const imports = packageConfig.imports;
- if (imports) {
- if (
- hasOwn(imports, name) &&
- !name.includes("*")
- ) {
- const resolved = resolvePackageTarget(
- packageJSONUrl.toString(),
- imports[name],
- "",
- name,
- base,
- false,
- true,
- conditions,
- );
- if (resolved !== null && resolved !== undefined) {
- return resolved;
- }
- } else {
- let bestMatch = "";
- let bestMatchSubpath = "";
- const keys = Object.getOwnPropertyNames(imports);
- for (let i = 0; i < keys.length; i++) {
- const key = keys[i];
- const patternIndex = key.indexOf("*");
- if (
- patternIndex !== -1 &&
- name.startsWith(
- key.slice(0, patternIndex),
- )
- ) {
- const patternTrailer = key.slice(patternIndex + 1);
- if (
- name.length >= key.length &&
- name.endsWith(patternTrailer) &&
- patternKeyCompare(bestMatch, key) === 1 &&
- key.lastIndexOf("*") === patternIndex
- ) {
- bestMatch = key;
- bestMatchSubpath = name.slice(
- patternIndex,
- name.length - patternTrailer.length,
- );
- }
- }
- }
-
- if (bestMatch) {
- const target = imports[bestMatch];
- const resolved = resolvePackageTarget(
- packageJSONUrl.toString(),
- target,
- bestMatchSubpath,
- bestMatch,
- base,
- true,
- true,
- conditions,
- );
- if (resolved !== null && resolved !== undefined) {
- return resolved;
- }
- }
- }
- }
- }
- throwImportNotDefined(name, packageJSONUrl, base);
-}
-
-function isConditionalExportsMainSugar(
- // deno-lint-ignore no-explicit-any
- exports: any,
- packageJSONUrl: string,
- base: string,
-): boolean {
- if (typeof exports === "string" || Array.isArray(exports)) return true;
- if (typeof exports !== "object" || exports === null) return false;
-
- const keys = Object.getOwnPropertyNames(exports);
- let isConditionalSugar = false;
- let i = 0;
- for (let j = 0; j < keys.length; j++) {
- const key = keys[j];
- const curIsConditionalSugar = key === "" || key[0] !== ".";
- if (i++ === 0) {
- isConditionalSugar = curIsConditionalSugar;
- } else if (isConditionalSugar !== curIsConditionalSugar) {
- const message =
- "\"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.";
- throw new ERR_INVALID_PACKAGE_CONFIG(
- fileURLToPath(packageJSONUrl),
- base,
- message,
- );
- }
- }
- return isConditionalSugar;
-}
diff --git a/ext/node/polyfills/upstream_modules.ts b/ext/node/polyfills/upstream_modules.ts
deleted file mode 100644
index ed8d6faa0..000000000
--- a/ext/node/polyfills/upstream_modules.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-// Upstream modules
-const callerPath = `const callerCallsite = require("caller-callsite");
-const re = /^file:/;
-
-module.exports = () => {
- const fileUrl = callerCallsite().getFileName();
- return fileUrl.replace(re, "");
-};
-`;
-
-// From: https://github.com/stefanpenner/get-caller-file/blob/2383bf9e98ed3c568ff69d7586cf59c0f1dcb9d3/index.ts
-const getCallerFile = `
-const re = /^file:\\/\\//;
-
-module.exports = function getCallerFile(position = 2) {
- if (position >= Error.stackTraceLimit) {
- throw new TypeError('getCallerFile(position) requires position be less then Error.stackTraceLimit but position was: "' + position + '" and Error.stackTraceLimit was: "' + Error.stackTraceLimit + '"');
- }
-
- const oldPrepareStackTrace = Error.prepareStackTrace;
- Error.prepareStackTrace = (_, stack) => stack;
- const stack = new Error().stack;
- Error.prepareStackTrace = oldPrepareStackTrace;
-
-
- if (stack !== null && typeof stack === 'object') {
- // stack[0] holds this file
- // stack[1] holds where this function was called
- // stack[2] holds the file we're interested in
- return stack[position] ? stack[position].getFileName().replace(re, "") : undefined;
- }
-};
-`;
-
-export default {
- "caller-path": callerPath,
- "get-caller-file": getCallerFile,
-} as Record<string, string>;