summaryrefslogtreecommitdiff
path: root/ext/node/polyfills
diff options
context:
space:
mode:
Diffstat (limited to 'ext/node/polyfills')
-rw-r--r--ext/node/polyfills/inspector.js210
-rw-r--r--ext/node/polyfills/inspector.ts82
-rw-r--r--ext/node/polyfills/inspector/promises.js20
3 files changed, 230 insertions, 82 deletions
diff --git a/ext/node/polyfills/inspector.js b/ext/node/polyfills/inspector.js
new file mode 100644
index 000000000..7eb15ce91
--- /dev/null
+++ b/ext/node/polyfills/inspector.js
@@ -0,0 +1,210 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+// Copyright Joyent and Node contributors. All rights reserved. MIT license.
+
+import process from "node:process";
+import { EventEmitter } from "node:events";
+import { primordials } from "ext:core/mod.js";
+import {
+ op_get_extras_binding_object,
+ op_inspector_close,
+ op_inspector_connect,
+ op_inspector_disconnect,
+ op_inspector_dispatch,
+ op_inspector_emit_protocol_event,
+ op_inspector_enabled,
+ op_inspector_open,
+ op_inspector_url,
+ op_inspector_wait,
+} from "ext:core/ops";
+import {
+ isUint32,
+ validateFunction,
+ validateInt32,
+ validateObject,
+ validateString,
+} from "ext:deno_node/internal/validators.mjs";
+import {
+ ERR_INSPECTOR_ALREADY_ACTIVATED,
+ ERR_INSPECTOR_ALREADY_CONNECTED,
+ ERR_INSPECTOR_CLOSED,
+ ERR_INSPECTOR_COMMAND,
+ ERR_INSPECTOR_NOT_ACTIVE,
+ ERR_INSPECTOR_NOT_CONNECTED,
+ ERR_INSPECTOR_NOT_WORKER,
+} from "ext:deno_node/internal/errors.ts";
+
+const {
+ SymbolDispose,
+ JSONParse,
+ JSONStringify,
+ SafeMap,
+} = primordials;
+
+class Session extends EventEmitter {
+ #connection = null;
+ #nextId = 1;
+ #messageCallbacks = new SafeMap();
+
+ connect() {
+ if (this.#connection) {
+ throw new ERR_INSPECTOR_ALREADY_CONNECTED("The inspector session");
+ }
+ this.#connection = op_inspector_connect(false, (m) => this.#onMessage(m));
+ }
+
+ connectToMainThread() {
+ if (isMainThread) {
+ throw new ERR_INSPECTOR_NOT_WORKER();
+ }
+ if (this.#connection) {
+ throw new ERR_INSPECTOR_ALREADY_CONNECTED("The inspector session");
+ }
+ this.#connection = op_inspector_connect(true, (m) => this.#onMessage(m));
+ }
+
+ #onMessage(message) {
+ const parsed = JSONParse(message);
+ try {
+ if (parsed.id) {
+ const callback = this.#messageCallbacks.get(parsed.id);
+ this.#messageCallbacks.delete(parsed.id);
+ if (callback) {
+ if (parsed.error) {
+ return callback(
+ new ERR_INSPECTOR_COMMAND(
+ parsed.error.code,
+ parsed.error.message,
+ ),
+ );
+ }
+
+ callback(null, parsed.result);
+ }
+ } else {
+ this.emit(parsed.method, parsed);
+ this.emit("inspectorNotification", parsed);
+ }
+ } catch (error) {
+ process.emitWarning(error);
+ }
+ }
+
+ post(method, params, callback) {
+ validateString(method, "method");
+ if (!callback && typeof params === "function") {
+ callback = params;
+ params = null;
+ }
+ if (params) {
+ validateObject(params, "params");
+ }
+ if (callback) {
+ validateFunction(callback, "callback");
+ }
+
+ if (!this.#connection) {
+ throw new ERR_INSPECTOR_NOT_CONNECTED();
+ }
+ const id = this.#nextId++;
+ const message = { id, method };
+ if (params) {
+ message.params = params;
+ }
+ if (callback) {
+ this.#messageCallbacks.set(id, callback);
+ }
+ op_inspector_dispatch(this.#connection, JSONStringify(message));
+ }
+
+ disconnect() {
+ if (!this.#connection) {
+ return;
+ }
+ op_inspector_disconnect(this.#connection);
+ this.#connection = null;
+ // deno-lint-ignore prefer-primordials
+ for (const callback of this.#messageCallbacks.values()) {
+ process.nextTick(callback, new ERR_INSPECTOR_CLOSED());
+ }
+ this.#messageCallbacks.clear();
+ this.#nextId = 1;
+ }
+}
+
+function open(port, host, wait) {
+ if (op_inspector_enabled()) {
+ throw new ERR_INSPECTOR_ALREADY_ACTIVATED();
+ }
+ // inspectorOpen() currently does not typecheck its arguments and adding
+ // such checks would be a potentially breaking change. However, the native
+ // open() function requires the port to fit into a 16-bit unsigned integer,
+ // causing an integer overflow otherwise, so we at least need to prevent that.
+ if (isUint32(port)) {
+ validateInt32(port, "port", 0, 65535);
+ } else {
+ // equiv of handling args[0]->IsUint32()
+ port = undefined;
+ }
+ if (typeof host !== "string") {
+ // equiv of handling args[1]->IsString()
+ host = undefined;
+ }
+ op_inspector_open(port, host);
+ if (wait) {
+ op_inspector_wait();
+ }
+
+ return {
+ __proto__: null,
+ [SymbolDispose]() {
+ _debugEnd();
+ },
+ };
+}
+
+function close() {
+ op_inspector_close();
+}
+
+function url() {
+ return op_inspector_url();
+}
+
+function waitForDebugger() {
+ if (!op_inspector_wait()) {
+ throw new ERR_INSPECTOR_NOT_ACTIVE();
+ }
+}
+
+function broadcastToFrontend(eventName, params) {
+ validateString(eventName, "eventName");
+ if (params) {
+ validateObject(params, "params");
+ }
+ op_inspector_emit_protocol_event(eventName, JSONStringify(params ?? {}));
+}
+
+const Network = {
+ requestWillBeSent: (params) =>
+ broadcastToFrontend("Network.requestWillBeSent", params),
+ responseReceived: (params) =>
+ broadcastToFrontend("Network.responseReceived", params),
+ loadingFinished: (params) =>
+ broadcastToFrontend("Network.loadingFinished", params),
+ loadingFailed: (params) =>
+ broadcastToFrontend("Network.loadingFailed", params),
+};
+
+const console = op_get_extras_binding_object().console;
+
+export { close, console, Network, open, Session, url, waitForDebugger };
+
+export default {
+ open,
+ close,
+ url,
+ waitForDebugger,
+ console,
+ Session,
+ Network,
+};
diff --git a/ext/node/polyfills/inspector.ts b/ext/node/polyfills/inspector.ts
deleted file mode 100644
index 9de86ab14..000000000
--- a/ext/node/polyfills/inspector.ts
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
-// Copyright Joyent and Node contributors. All rights reserved. MIT license.
-
-import { EventEmitter } from "node:events";
-import { notImplemented } from "ext:deno_node/_utils.ts";
-import { primordials } from "ext:core/mod.js";
-
-const {
- SafeMap,
-} = primordials;
-
-class Session extends EventEmitter {
- #connection = null;
- #nextId = 1;
- #messageCallbacks = new SafeMap();
-
- /** Connects the session to the inspector back-end. */
- connect() {
- notImplemented("inspector.Session.prototype.connect");
- }
-
- /** Connects the session to the main thread
- * inspector back-end. */
- connectToMainThread() {
- notImplemented("inspector.Session.prototype.connectToMainThread");
- }
-
- /** Posts a message to the inspector back-end. */
- post(
- _method: string,
- _params?: Record<string, unknown>,
- _callback?: (...args: unknown[]) => void,
- ) {
- notImplemented("inspector.Session.prototype.post");
- }
-
- /** Immediately closes the session, all pending
- * message callbacks will be called with an
- * error.
- */
- disconnect() {
- notImplemented("inspector.Session.prototype.disconnect");
- }
-}
-
-/** Activates inspector on host and port.
- * See https://nodejs.org/api/inspector.html#inspectoropenport-host-wait */
-function open(_port?: number, _host?: string, _wait?: boolean) {
- notImplemented("inspector.Session.prototype.open");
-}
-
-/** Deactivate the inspector. Blocks until there are no active connections.
- * See https://nodejs.org/api/inspector.html#inspectorclose */
-function close() {
- notImplemented("inspector.Session.prototype.close");
-}
-
-/** Return the URL of the active inspector, or undefined if there is none.
- * See https://nodejs.org/api/inspector.html#inspectorurl */
-function url() {
- // TODO(kt3k): returns undefined for now, which means the inspector is not activated.
- return undefined;
-}
-
-/** Blocks until a client (existing or connected later) has sent Runtime.runIfWaitingForDebugger command.
- * See https://nodejs.org/api/inspector.html#inspectorwaitfordebugger */
-function waitForDebugger() {
- notImplemented("inspector.wairForDebugger");
-}
-
-const console = globalThis.console;
-
-export { close, console, open, Session, url, waitForDebugger };
-
-export default {
- close,
- console,
- open,
- Session,
- url,
- waitForDebugger,
-};
diff --git a/ext/node/polyfills/inspector/promises.js b/ext/node/polyfills/inspector/promises.js
new file mode 100644
index 000000000..3483e53f5
--- /dev/null
+++ b/ext/node/polyfills/inspector/promises.js
@@ -0,0 +1,20 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+// Copyright Joyent and Node contributors. All rights reserved. MIT license.
+
+import inspector from "node:inspector";
+import { promisify } from "ext:deno_node/internal/util.mjs";
+
+class Session extends inspector.Session {
+ constructor() {
+ super();
+ }
+}
+Session.prototype.post = promisify(inspector.Session.prototype.post);
+
+export * from "node:inspector";
+export { Session };
+
+export default {
+ ...inspector,
+ Session,
+};