summaryrefslogtreecommitdiff
path: root/ext/node/polyfills/_next_tick.ts
diff options
context:
space:
mode:
authorBartek IwaƄczuk <biwanczuk@gmail.com>2023-02-14 17:38:45 +0100
committerGitHub <noreply@github.com>2023-02-14 17:38:45 +0100
commitd47147fb6ad229b1c039aff9d0959b6e281f4df5 (patch)
tree6e9e790f2b9bc71b5f0c9c7e64b95cae31579d58 /ext/node/polyfills/_next_tick.ts
parent1d00bbe47e2ca14e2d2151518e02b2324461a065 (diff)
feat(ext/node): embed std/node into the snapshot (#17724)
This commit moves "deno_std/node" in "ext/node" crate. The code is transpiled and snapshotted during the build process. During the first pass a minimal amount of work was done to create the snapshot, a lot of code in "ext/node" depends on presence of "Deno" global. This code will be gradually fixed in the follow up PRs to migrate it to import relevant APIs from "internal:" modules. Currently the code from snapshot is not used in any way, and all Node/npm compatibility still uses code from "https://deno.land/std/node" (or from the location specified by "DENO_NODE_COMPAT_URL"). This will also be handled in a follow up PRs. --------- Co-authored-by: crowlkats <crowlkats@toaxl.com> Co-authored-by: Divy Srivastava <dj.srivastava23@gmail.com> Co-authored-by: Yoshiya Hinosawa <stibium121@gmail.com>
Diffstat (limited to 'ext/node/polyfills/_next_tick.ts')
-rw-r--r--ext/node/polyfills/_next_tick.ts173
1 files changed, 173 insertions, 0 deletions
diff --git a/ext/node/polyfills/_next_tick.ts b/ext/node/polyfills/_next_tick.ts
new file mode 100644
index 000000000..7cbff0ea4
--- /dev/null
+++ b/ext/node/polyfills/_next_tick.ts
@@ -0,0 +1,173 @@
+// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+// Copyright Joyent, Inc. and other Node contributors.
+
+// deno-lint-ignore-file no-inner-declarations
+
+import { core } from "internal:deno_node/polyfills/_core.ts";
+import { validateFunction } from "internal:deno_node/polyfills/internal/validators.mjs";
+import { _exiting } from "internal:deno_node/polyfills/_process/exiting.ts";
+import { FixedQueue } from "internal:deno_node/polyfills/internal/fixed_queue.ts";
+
+interface Tock {
+ callback: (...args: Array<unknown>) => void;
+ args: Array<unknown>;
+}
+
+const queue = new FixedQueue();
+
+// deno-lint-ignore no-explicit-any
+let _nextTick: any;
+
+export function processTicksAndRejections() {
+ let tock;
+ do {
+ // deno-lint-ignore no-cond-assign
+ while (tock = queue.shift()) {
+ // FIXME(bartlomieju): Deno currently doesn't support async hooks
+ // const asyncId = tock[async_id_symbol];
+ // emitBefore(asyncId, tock[trigger_async_id_symbol], tock);
+
+ try {
+ const callback = (tock as Tock).callback;
+ if ((tock as Tock).args === undefined) {
+ callback();
+ } else {
+ const args = (tock as Tock).args;
+ switch (args.length) {
+ case 1:
+ callback(args[0]);
+ break;
+ case 2:
+ callback(args[0], args[1]);
+ break;
+ case 3:
+ callback(args[0], args[1], args[2]);
+ break;
+ case 4:
+ callback(args[0], args[1], args[2], args[3]);
+ break;
+ default:
+ callback(...args);
+ }
+ }
+ } finally {
+ // FIXME(bartlomieju): Deno currently doesn't support async hooks
+ // if (destroyHooksExist())
+ // emitDestroy(asyncId);
+ }
+
+ // FIXME(bartlomieju): Deno currently doesn't support async hooks
+ // emitAfter(asyncId);
+ }
+ core.runMicrotasks();
+ // FIXME(bartlomieju): Deno currently doesn't unhandled rejections
+ // } while (!queue.isEmpty() || processPromiseRejections());
+ } while (!queue.isEmpty());
+ core.setHasTickScheduled(false);
+ // FIXME(bartlomieju): Deno currently doesn't unhandled rejections
+ // setHasRejectionToWarn(false);
+}
+
+if (typeof core.setNextTickCallback !== "undefined") {
+ function runNextTicks() {
+ // FIXME(bartlomieju): Deno currently doesn't unhandled rejections
+ // if (!hasTickScheduled() && !hasRejectionToWarn())
+ // runMicrotasks();
+ // if (!hasTickScheduled() && !hasRejectionToWarn())
+ // return;
+ if (!core.hasTickScheduled()) {
+ core.runMicrotasks();
+ }
+ if (!core.hasTickScheduled()) {
+ return true;
+ }
+
+ processTicksAndRejections();
+ return true;
+ }
+
+ core.setNextTickCallback(processTicksAndRejections);
+ core.setMacrotaskCallback(runNextTicks);
+
+ function __nextTickNative<T extends Array<unknown>>(
+ this: unknown,
+ callback: (...args: T) => void,
+ ...args: T
+ ) {
+ validateFunction(callback, "callback");
+
+ if (_exiting) {
+ return;
+ }
+
+ // TODO(bartlomieju): seems superfluous if we don't depend on `arguments`
+ let args_;
+ switch (args.length) {
+ case 0:
+ break;
+ case 1:
+ args_ = [args[0]];
+ break;
+ case 2:
+ args_ = [args[0], args[1]];
+ break;
+ case 3:
+ args_ = [args[0], args[1], args[2]];
+ break;
+ default:
+ args_ = new Array(args.length);
+ for (let i = 0; i < args.length; i++) {
+ args_[i] = args[i];
+ }
+ }
+
+ if (queue.isEmpty()) {
+ core.setHasTickScheduled(true);
+ }
+ // FIXME(bartlomieju): Deno currently doesn't support async hooks
+ // const asyncId = newAsyncId();
+ // const triggerAsyncId = getDefaultTriggerAsyncId();
+ const tickObject = {
+ // FIXME(bartlomieju): Deno currently doesn't support async hooks
+ // [async_id_symbol]: asyncId,
+ // [trigger_async_id_symbol]: triggerAsyncId,
+ callback,
+ args: args_,
+ };
+ // FIXME(bartlomieju): Deno currently doesn't support async hooks
+ // if (initHooksExist())
+ // emitInit(asyncId, 'TickObject', triggerAsyncId, tickObject);
+ queue.push(tickObject);
+ }
+ _nextTick = __nextTickNative;
+} else {
+ function __nextTickQueueMicrotask<T extends Array<unknown>>(
+ this: unknown,
+ callback: (...args: T) => void,
+ ...args: T
+ ) {
+ if (args) {
+ queueMicrotask(() => callback.call(this, ...args));
+ } else {
+ queueMicrotask(callback);
+ }
+ }
+
+ _nextTick = __nextTickQueueMicrotask;
+}
+
+// `nextTick()` will not enqueue any callback when the process is about to
+// exit since the callback would not have a chance to be executed.
+export function nextTick(this: unknown, callback: () => void): void;
+export function nextTick<T extends Array<unknown>>(
+ this: unknown,
+ callback: (...args: T) => void,
+ ...args: T
+): void;
+export function nextTick<T extends Array<unknown>>(
+ this: unknown,
+ callback: (...args: T) => void,
+ ...args: T
+) {
+ _nextTick(callback, ...args);
+}