summaryrefslogtreecommitdiff
path: root/ext/timers
diff options
context:
space:
mode:
authorAndreu Botella <andreu@andreubotella.com>2022-02-15 12:17:30 +0100
committerGitHub <noreply@github.com>2022-02-15 12:17:30 +0100
commit760f4c9e2427e87815a8e59b0807693c8dcb623a (patch)
treecb04b2b42cfcf1fc46d74a3e4c7f86c73491d2b0 /ext/timers
parent5e845442fade02cd12d13e74222b26e217c5971d (diff)
chore(ext/timers): move ext/timers to ext/web (#13665)
Diffstat (limited to 'ext/timers')
-rw-r--r--ext/timers/01_timers.js394
-rw-r--r--ext/timers/02_performance.js569
-rw-r--r--ext/timers/Cargo.toml28
-rw-r--r--ext/timers/README.md5
-rw-r--r--ext/timers/benches/timers_ops.rs54
-rw-r--r--ext/timers/lib.rs127
6 files changed, 0 insertions, 1177 deletions
diff --git a/ext/timers/01_timers.js b/ext/timers/01_timers.js
deleted file mode 100644
index a0b1deb45..000000000
--- a/ext/timers/01_timers.js
+++ /dev/null
@@ -1,394 +0,0 @@
-// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
-"use strict";
-
-((window) => {
- const core = window.Deno.core;
- const {
- ArrayPrototypePush,
- ArrayPrototypeShift,
- Error,
- FunctionPrototypeCall,
- Map,
- MapPrototypeDelete,
- MapPrototypeGet,
- MapPrototypeHas,
- MapPrototypeSet,
- // deno-lint-ignore camelcase
- NumberPOSITIVE_INFINITY,
- PromisePrototypeThen,
- ObjectPrototypeIsPrototypeOf,
- SafeArrayIterator,
- SymbolFor,
- TypeError,
- } = window.__bootstrap.primordials;
- const { webidl } = window.__bootstrap;
-
- // Shamelessly cribbed from extensions/fetch/11_streams.js
- class AssertionError extends Error {
- constructor(msg) {
- super(msg);
- this.name = "AssertionError";
- }
- }
-
- /**
- * @param {unknown} cond
- * @param {string=} msg
- * @returns {asserts cond}
- */
- function assert(cond, msg = "Assertion failed.") {
- if (!cond) {
- throw new AssertionError(msg);
- }
- }
-
- function opNow() {
- return core.opSync("op_now");
- }
-
- function sleepSync(millis = 0) {
- return core.opSync("op_sleep_sync", millis);
- }
-
- // ---------------------------------------------------------------------------
-
- /**
- * The task queue corresponding to the timer task source.
- *
- * @type { {action: () => void, nestingLevel: number}[] }
- */
- const timerTasks = [];
-
- /**
- * The current task's timer nesting level, or zero if we're not currently
- * running a timer task (since the minimum nesting level is 1).
- *
- * @type {number}
- */
- let timerNestingLevel = 0;
-
- function handleTimerMacrotask() {
- if (timerTasks.length === 0) {
- return true;
- }
-
- const task = ArrayPrototypeShift(timerTasks);
-
- timerNestingLevel = task.nestingLevel;
-
- try {
- task.action();
- } finally {
- timerNestingLevel = 0;
- }
- return timerTasks.length === 0;
- }
-
- // ---------------------------------------------------------------------------
-
- /**
- * The keys in this map correspond to the key ID's in the spec's map of active
- * timers. The values are the timeout's cancel rid.
- *
- * @type {Map<number, { cancelRid: number, isRef: boolean, promiseId: number }>}
- */
- const activeTimers = new Map();
-
- let nextId = 1;
-
- /**
- * @param {Function | string} callback
- * @param {number} timeout
- * @param {Array<any>} args
- * @param {boolean} repeat
- * @param {number | undefined} prevId
- * @returns {number} The timer ID
- */
- function initializeTimer(
- callback,
- timeout,
- args,
- repeat,
- prevId,
- ) {
- // 2. If previousId was given, let id be previousId; otherwise, let
- // previousId be an implementation-defined integer than is greater than zero
- // and does not already exist in global's map of active timers.
- let id;
- let timerInfo;
- if (prevId !== undefined) {
- // `prevId` is only passed for follow-up calls on intervals
- assert(repeat);
- id = prevId;
- timerInfo = MapPrototypeGet(activeTimers, id);
- } else {
- // TODO(@andreubotella): Deal with overflow.
- // https://github.com/whatwg/html/issues/7358
- id = nextId++;
- const cancelRid = core.opSync("op_timer_handle");
- timerInfo = { cancelRid, isRef: true, promiseId: -1 };
-
- // Step 4 in "run steps after a timeout".
- MapPrototypeSet(activeTimers, id, timerInfo);
- }
-
- // 3. If the surrounding agent's event loop's currently running task is a
- // task that was created by this algorithm, then let nesting level be the
- // task's timer nesting level. Otherwise, let nesting level be zero.
- // 4. If timeout is less than 0, then set timeout to 0.
- // 5. If nesting level is greater than 5, and timeout is less than 4, then
- // set timeout to 4.
- //
- // The nesting level of 5 and minimum of 4 ms are spec-mandated magic
- // constants.
- if (timeout < 0) timeout = 0;
- if (timerNestingLevel > 5 && timeout < 4) timeout = 4;
-
- // 9. Let task be a task that runs the following steps:
- const task = {
- action: () => {
- // 1. If id does not exist in global's map of active timers, then abort
- // these steps.
- //
- // This is relevant if the timer has been canceled after the sleep op
- // resolves but before this task runs.
- if (!MapPrototypeHas(activeTimers, id)) {
- return;
- }
-
- // 2.
- // 3.
- // TODO(@andreubotella): Error handling.
- if (typeof callback === "function") {
- FunctionPrototypeCall(
- callback,
- globalThis,
- ...new SafeArrayIterator(args),
- );
- } else {
- // TODO(@andreubotella): eval doesn't seem to have a primordial, but
- // it can be redefined in the global scope.
- (0, eval)(callback);
- }
-
- if (repeat) {
- if (MapPrototypeHas(activeTimers, id)) {
- // 4. If id does not exist in global's map of active timers, then
- // abort these steps.
- // NOTE: If might have been removed via the author code in handler
- // calling clearTimeout() or clearInterval().
- // 5. If repeat is true, then perform the timer initialization steps
- // again, given global, handler, timeout, arguments, true, and id.
- initializeTimer(callback, timeout, args, true, id);
- }
- } else {
- // 6. Otherwise, remove global's map of active timers[id].
- core.tryClose(timerInfo.cancelRid);
- MapPrototypeDelete(activeTimers, id);
- }
- },
-
- // 10. Increment nesting level by one.
- // 11. Set task's timer nesting level to nesting level.
- nestingLevel: timerNestingLevel + 1,
- };
-
- // 12. Let completionStep be an algorithm step which queues a global task on
- // the timer task source given global to run task.
- // 13. Run steps after a timeout given global, "setTimeout/setInterval",
- // timeout, completionStep, and id.
- runAfterTimeout(
- () => ArrayPrototypePush(timerTasks, task),
- timeout,
- timerInfo,
- );
-
- return id;
- }
-
- // ---------------------------------------------------------------------------
-
- /**
- * @typedef ScheduledTimer
- * @property {number} millis
- * @property {() => void} cb
- * @property {boolean} resolved
- * @property {ScheduledTimer | null} prev
- * @property {ScheduledTimer | null} next
- */
-
- /**
- * A doubly linked list of timers.
- * @type { { head: ScheduledTimer | null, tail: ScheduledTimer | null } }
- */
- const scheduledTimers = { head: null, tail: null };
-
- /**
- * @param {() => void} cb Will be run after the timeout, if it hasn't been
- * cancelled.
- * @param {number} millis
- * @param {{ cancelRid: number, isRef: boolean, promiseId: number }} timerInfo
- */
- function runAfterTimeout(cb, millis, timerInfo) {
- const cancelRid = timerInfo.cancelRid;
- const sleepPromise = core.opAsync("op_sleep", millis, cancelRid);
- timerInfo.promiseId =
- sleepPromise[SymbolFor("Deno.core.internalPromiseId")];
- if (!timerInfo.isRef) {
- core.unrefOp(timerInfo.promiseId);
- }
-
- /** @type {ScheduledTimer} */
- const timerObject = {
- millis,
- cb,
- resolved: false,
- prev: scheduledTimers.tail,
- next: null,
- };
-
- // Add timerObject to the end of the list.
- if (scheduledTimers.tail === null) {
- assert(scheduledTimers.head === null);
- scheduledTimers.head = scheduledTimers.tail = timerObject;
- } else {
- scheduledTimers.tail.next = timerObject;
- scheduledTimers.tail = timerObject;
- }
-
- // 1.
- PromisePrototypeThen(
- sleepPromise,
- () => {
- // 2. Wait until any invocations of this algorithm that had the same
- // global and orderingIdentifier, that started before this one, and
- // whose milliseconds is equal to or less than this one's, have
- // completed.
- // 4. Perform completionSteps.
-
- // IMPORTANT: Since the sleep ops aren't guaranteed to resolve in the
- // right order, whenever one resolves, we run through the scheduled
- // timers list (which is in the order in which they were scheduled), and
- // we call the callback for every timer which both:
- // a) has resolved, and
- // b) its timeout is lower than the lowest unresolved timeout found so
- // far in the list.
-
- timerObject.resolved = true;
-
- let lowestUnresolvedTimeout = NumberPOSITIVE_INFINITY;
-
- let currentEntry = scheduledTimers.head;
- while (currentEntry !== null) {
- if (currentEntry.millis < lowestUnresolvedTimeout) {
- if (currentEntry.resolved) {
- currentEntry.cb();
- removeFromScheduledTimers(currentEntry);
- } else {
- lowestUnresolvedTimeout = currentEntry.millis;
- }
- }
-
- currentEntry = currentEntry.next;
- }
- },
- (err) => {
- if (ObjectPrototypeIsPrototypeOf(core.InterruptedPrototype, err)) {
- // The timer was cancelled.
- removeFromScheduledTimers(timerObject);
- } else {
- throw err;
- }
- },
- );
- }
-
- /** @param {ScheduledTimer} timerObj */
- function removeFromScheduledTimers(timerObj) {
- if (timerObj.prev !== null) {
- timerObj.prev.next = timerObj.next;
- } else {
- assert(scheduledTimers.head === timerObj);
- scheduledTimers.head = timerObj.next;
- }
- if (timerObj.next !== null) {
- timerObj.next.prev = timerObj.prev;
- } else {
- assert(scheduledTimers.tail === timerObj);
- scheduledTimers.tail = timerObj.prev;
- }
- }
-
- // ---------------------------------------------------------------------------
-
- function checkThis(thisArg) {
- if (thisArg !== null && thisArg !== undefined && thisArg !== globalThis) {
- throw new TypeError("Illegal invocation");
- }
- }
-
- function setTimeout(callback, timeout = 0, ...args) {
- checkThis(this);
- if (typeof callback !== "function") {
- callback = webidl.converters.DOMString(callback);
- }
- timeout = webidl.converters.long(timeout);
-
- return initializeTimer(callback, timeout, args, false);
- }
-
- function setInterval(callback, timeout = 0, ...args) {
- checkThis(this);
- if (typeof callback !== "function") {
- callback = webidl.converters.DOMString(callback);
- }
- timeout = webidl.converters.long(timeout);
-
- return initializeTimer(callback, timeout, args, true);
- }
-
- function clearTimeout(id = 0) {
- checkThis(this);
- id = webidl.converters.long(id);
- const timerInfo = MapPrototypeGet(activeTimers, id);
- if (timerInfo !== undefined) {
- core.tryClose(timerInfo.cancelRid);
- MapPrototypeDelete(activeTimers, id);
- }
- }
-
- function clearInterval(id = 0) {
- checkThis(this);
- clearTimeout(id);
- }
-
- function refTimer(id) {
- const timerInfo = MapPrototypeGet(activeTimers, id);
- if (timerInfo === undefined || timerInfo.isRef) {
- return;
- }
- timerInfo.isRef = true;
- core.refOp(timerInfo.promiseId);
- }
-
- function unrefTimer(id) {
- const timerInfo = MapPrototypeGet(activeTimers, id);
- if (timerInfo === undefined || !timerInfo.isRef) {
- return;
- }
- timerInfo.isRef = false;
- core.unrefOp(timerInfo.promiseId);
- }
-
- window.__bootstrap.timers = {
- setTimeout,
- setInterval,
- clearTimeout,
- clearInterval,
- handleTimerMacrotask,
- opNow,
- sleepSync,
- refTimer,
- unrefTimer,
- };
-})(this);
diff --git a/ext/timers/02_performance.js b/ext/timers/02_performance.js
deleted file mode 100644
index c48a3d888..000000000
--- a/ext/timers/02_performance.js
+++ /dev/null
@@ -1,569 +0,0 @@
-// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
-"use strict";
-
-((window) => {
- const {
- ArrayPrototypeFilter,
- ArrayPrototypeFind,
- ArrayPrototypePush,
- ArrayPrototypeReverse,
- ArrayPrototypeSlice,
- ObjectKeys,
- ObjectPrototypeIsPrototypeOf,
- Symbol,
- SymbolFor,
- TypeError,
- } = window.__bootstrap.primordials;
-
- const { webidl, structuredClone } = window.__bootstrap;
- const consoleInternal = window.__bootstrap.console;
- const { opNow } = window.__bootstrap.timers;
- const { DOMException } = window.__bootstrap.domException;
-
- const illegalConstructorKey = Symbol("illegalConstructorKey");
- const customInspect = SymbolFor("Deno.customInspect");
- let performanceEntries = [];
-
- webidl.converters["PerformanceMarkOptions"] = webidl
- .createDictionaryConverter(
- "PerformanceMarkOptions",
- [
- {
- key: "detail",
- converter: webidl.converters.any,
- },
- {
- key: "startTime",
- converter: webidl.converters.DOMHighResTimeStamp,
- },
- ],
- );
-
- webidl.converters["DOMString or DOMHighResTimeStamp"] = (V, opts) => {
- if (webidl.type(V) === "Number" && V !== null) {
- return webidl.converters.DOMHighResTimeStamp(V, opts);
- }
- return webidl.converters.DOMString(V, opts);
- };
-
- webidl.converters["PerformanceMeasureOptions"] = webidl
- .createDictionaryConverter(
- "PerformanceMeasureOptions",
- [
- {
- key: "detail",
- converter: webidl.converters.any,
- },
- {
- key: "start",
- converter: webidl.converters["DOMString or DOMHighResTimeStamp"],
- },
- {
- key: "duration",
- converter: webidl.converters.DOMHighResTimeStamp,
- },
- {
- key: "end",
- converter: webidl.converters["DOMString or DOMHighResTimeStamp"],
- },
- ],
- );
-
- webidl.converters["DOMString or PerformanceMeasureOptions"] = (V, opts) => {
- if (webidl.type(V) === "Object" && V !== null) {
- return webidl.converters["PerformanceMeasureOptions"](V, opts);
- }
- return webidl.converters.DOMString(V, opts);
- };
-
- function findMostRecent(
- name,
- type,
- ) {
- return ArrayPrototypeFind(
- ArrayPrototypeReverse(ArrayPrototypeSlice(performanceEntries)),
- (entry) => entry.name === name && entry.entryType === type,
- );
- }
-
- function convertMarkToTimestamp(mark) {
- if (typeof mark === "string") {
- const entry = findMostRecent(mark, "mark");
- if (!entry) {
- throw new DOMException(
- `Cannot find mark: "${mark}".`,
- "SyntaxError",
- );
- }
- return entry.startTime;
- }
- if (mark < 0) {
- throw new TypeError("Mark cannot be negative.");
- }
- return mark;
- }
-
- function filterByNameType(
- name,
- type,
- ) {
- return ArrayPrototypeFilter(
- performanceEntries,
- (entry) =>
- (name ? entry.name === name : true) &&
- (type ? entry.entryType === type : true),
- );
- }
-
- const now = opNow;
-
- const _name = Symbol("[[name]]");
- const _entryType = Symbol("[[entryType]]");
- const _startTime = Symbol("[[startTime]]");
- const _duration = Symbol("[[duration]]");
- class PerformanceEntry {
- [_name] = "";
- [_entryType] = "";
- [_startTime] = 0;
- [_duration] = 0;
-
- get name() {
- webidl.assertBranded(this, PerformanceEntryPrototype);
- return this[_name];
- }
-
- get entryType() {
- webidl.assertBranded(this, PerformanceEntryPrototype);
- return this[_entryType];
- }
-
- get startTime() {
- webidl.assertBranded(this, PerformanceEntryPrototype);
- return this[_startTime];
- }
-
- get duration() {
- webidl.assertBranded(this, PerformanceEntryPrototype);
- return this[_duration];
- }
-
- constructor(
- name = null,
- entryType = null,
- startTime = null,
- duration = null,
- key = undefined,
- ) {
- if (key !== illegalConstructorKey) {
- webidl.illegalConstructor();
- }
- this[webidl.brand] = webidl.brand;
-
- this[_name] = name;
- this[_entryType] = entryType;
- this[_startTime] = startTime;
- this[_duration] = duration;
- }
-
- toJSON() {
- webidl.assertBranded(this, PerformanceEntryPrototype);
- return {
- name: this[_name],
- entryType: this[_entryType],
- startTime: this[_startTime],
- duration: this[_duration],
- };
- }
-
- [customInspect](inspect) {
- return inspect(consoleInternal.createFilteredInspectProxy({
- object: this,
- evaluate: ObjectPrototypeIsPrototypeOf(
- PerformanceEntryPrototype,
- this,
- ),
- keys: [
- "name",
- "entryType",
- "startTime",
- "duration",
- ],
- }));
- }
- }
- webidl.configurePrototype(PerformanceEntry);
- const PerformanceEntryPrototype = PerformanceEntry.prototype;
-
- const _detail = Symbol("[[detail]]");
- class PerformanceMark extends PerformanceEntry {
- [_detail] = null;
-
- get detail() {
- webidl.assertBranded(this, PerformanceMarkPrototype);
- return this[_detail];
- }
-
- get entryType() {
- webidl.assertBranded(this, PerformanceMarkPrototype);
- return "mark";
- }
-
- constructor(
- name,
- options = {},
- ) {
- const prefix = "Failed to construct 'PerformanceMark'";
- webidl.requiredArguments(arguments.length, 1, { prefix });
-
- name = webidl.converters.DOMString(name, {
- prefix,
- context: "Argument 1",
- });
-
- options = webidl.converters.PerformanceMarkOptions(options, {
- prefix,
- context: "Argument 2",
- });
-
- const { detail = null, startTime = now() } = options;
-
- super(name, "mark", startTime, 0, illegalConstructorKey);
- this[webidl.brand] = webidl.brand;
- if (startTime < 0) {
- throw new TypeError("startTime cannot be negative");
- }
- this[_detail] = structuredClone(detail);
- }
-
- toJSON() {
- webidl.assertBranded(this, PerformanceMarkPrototype);
- return {
- name: this.name,
- entryType: this.entryType,
- startTime: this.startTime,
- duration: this.duration,
- detail: this.detail,
- };
- }
-
- [customInspect](inspect) {
- return inspect(consoleInternal.createFilteredInspectProxy({
- object: this,
- evaluate: ObjectPrototypeIsPrototypeOf(PerformanceMarkPrototype, this),
- keys: [
- "name",
- "entryType",
- "startTime",
- "duration",
- "detail",
- ],
- }));
- }
- }
- webidl.configurePrototype(PerformanceMark);
- const PerformanceMarkPrototype = PerformanceMark.prototype;
- class PerformanceMeasure extends PerformanceEntry {
- [_detail] = null;
-
- get detail() {
- webidl.assertBranded(this, PerformanceMeasurePrototype);
- return this[_detail];
- }
-
- get entryType() {
- webidl.assertBranded(this, PerformanceMeasurePrototype);
- return "measure";
- }
-
- constructor(
- name = null,
- startTime = null,
- duration = null,
- detail = null,
- key = undefined,
- ) {
- if (key !== illegalConstructorKey) {
- webidl.illegalConstructor();
- }
-
- super(name, "measure", startTime, duration, key);
- this[webidl.brand] = webidl.brand;
- this[_detail] = structuredClone(detail);
- }
-
- toJSON() {
- webidl.assertBranded(this, PerformanceMeasurePrototype);
- return {
- name: this.name,
- entryType: this.entryType,
- startTime: this.startTime,
- duration: this.duration,
- detail: this.detail,
- };
- }
-
- [customInspect](inspect) {
- return inspect(consoleInternal.createFilteredInspectProxy({
- object: this,
- evaluate: ObjectPrototypeIsPrototypeOf(
- PerformanceMeasurePrototype,
- this,
- ),
- keys: [
- "name",
- "entryType",
- "startTime",
- "duration",
- "detail",
- ],
- }));
- }
- }
- webidl.configurePrototype(PerformanceMeasure);
- const PerformanceMeasurePrototype = PerformanceMeasure.prototype;
- class Performance {
- constructor() {
- webidl.illegalConstructor();
- }
-
- clearMarks(markName = undefined) {
- webidl.assertBranded(this, PerformancePrototype);
- if (markName !== undefined) {
- markName = webidl.converters.DOMString(markName, {
- prefix: "Failed to execute 'clearMarks' on 'Performance'",
- context: "Argument 1",
- });
-
- performanceEntries = ArrayPrototypeFilter(
- performanceEntries,
- (entry) => !(entry.name === markName && entry.entryType === "mark"),
- );
- } else {
- performanceEntries = ArrayPrototypeFilter(
- performanceEntries,
- (entry) => entry.entryType !== "mark",
- );
- }
- }
-
- clearMeasures(measureName = undefined) {
- webidl.assertBranded(this, PerformancePrototype);
- if (measureName !== undefined) {
- measureName = webidl.converters.DOMString(measureName, {
- prefix: "Failed to execute 'clearMeasures' on 'Performance'",
- context: "Argument 1",
- });
-
- performanceEntries = ArrayPrototypeFilter(
- performanceEntries,
- (entry) =>
- !(entry.name === measureName && entry.entryType === "measure"),
- );
- } else {
- performanceEntries = ArrayPrototypeFilter(
- performanceEntries,
- (entry) => entry.entryType !== "measure",
- );
- }
- }
-
- getEntries() {
- webidl.assertBranded(this, PerformancePrototype);
- return filterByNameType();
- }
-
- getEntriesByName(
- name,
- type = undefined,
- ) {
- webidl.assertBranded(this, PerformancePrototype);
- const prefix = "Failed to execute 'getEntriesByName' on 'Performance'";
- webidl.requiredArguments(arguments.length, 1, { prefix });
-
- name = webidl.converters.DOMString(name, {
- prefix,
- context: "Argument 1",
- });
-
- if (type !== undefined) {
- type = webidl.converters.DOMString(type, {
- prefix,
- context: "Argument 2",
- });
- }
-
- return filterByNameType(name, type);
- }
-
- getEntriesByType(type) {
- webidl.assertBranded(this, PerformancePrototype);
- const prefix = "Failed to execute 'getEntriesByName' on 'Performance'";
- webidl.requiredArguments(arguments.length, 1, { prefix });
-
- type = webidl.converters.DOMString(type, {
- prefix,
- context: "Argument 1",
- });
-
- return filterByNameType(undefined, type);
- }
-
- mark(
- markName,
- markOptions = {},
- ) {
- webidl.assertBranded(this, PerformancePrototype);
- const prefix = "Failed to execute 'mark' on 'Performance'";
- webidl.requiredArguments(arguments.length, 1, { prefix });
-
- markName = webidl.converters.DOMString(markName, {
- prefix,
- context: "Argument 1",
- });
-
- markOptions = webidl.converters.PerformanceMarkOptions(markOptions, {
- prefix,
- context: "Argument 2",
- });
-
- // 3.1.1.1 If the global object is a Window object and markName uses the
- // same name as a read only attribute in the PerformanceTiming interface,
- // throw a SyntaxError. - not implemented
- const entry = new PerformanceMark(markName, markOptions);
- // 3.1.1.7 Queue entry - not implemented
- ArrayPrototypePush(performanceEntries, entry);
- return entry;
- }
-
- measure(
- measureName,
- startOrMeasureOptions = {},
- endMark = undefined,
- ) {
- webidl.assertBranded(this, PerformancePrototype);
- const prefix = "Failed to execute 'measure' on 'Performance'";
- webidl.requiredArguments(arguments.length, 1, { prefix });
-
- measureName = webidl.converters.DOMString(measureName, {
- prefix,
- context: "Argument 1",
- });
-
- startOrMeasureOptions = webidl.converters
- ["DOMString or PerformanceMeasureOptions"](startOrMeasureOptions, {
- prefix,
- context: "Argument 2",
- });
-
- if (endMark !== undefined) {
- endMark = webidl.converters.DOMString(endMark, {
- prefix,
- context: "Argument 3",
- });
- }
-
- if (
- startOrMeasureOptions && typeof startOrMeasureOptions === "object" &&
- ObjectKeys(startOrMeasureOptions).length > 0
- ) {
- if (endMark) {
- throw new TypeError("Options cannot be passed with endMark.");
- }
- if (
- !("start" in startOrMeasureOptions) &&
- !("end" in startOrMeasureOptions)
- ) {
- throw new TypeError(
- "A start or end mark must be supplied in options.",
- );
- }
- if (
- "start" in startOrMeasureOptions &&
- "duration" in startOrMeasureOptions &&
- "end" in startOrMeasureOptions
- ) {
- throw new TypeError(
- "Cannot specify start, end, and duration together in options.",
- );
- }
- }
- let endTime;
- if (endMark) {
- endTime = convertMarkToTimestamp(endMark);
- } else if (
- typeof startOrMeasureOptions === "object" &&
- "end" in startOrMeasureOptions
- ) {
- endTime = convertMarkToTimestamp(startOrMeasureOptions.end);
- } else if (
- typeof startOrMeasureOptions === "object" &&
- "start" in startOrMeasureOptions &&
- "duration" in startOrMeasureOptions
- ) {
- const start = convertMarkToTimestamp(startOrMeasureOptions.start);
- const duration = convertMarkToTimestamp(startOrMeasureOptions.duration);
- endTime = start + duration;
- } else {
- endTime = now();
- }
- let startTime;
- if (
- typeof startOrMeasureOptions === "object" &&
- "start" in startOrMeasureOptions
- ) {
- startTime = convertMarkToTimestamp(startOrMeasureOptions.start);
- } else if (
- typeof startOrMeasureOptions === "object" &&
- "end" in startOrMeasureOptions &&
- "duration" in startOrMeasureOptions
- ) {
- const end = convertMarkToTimestamp(startOrMeasureOptions.end);
- const duration = convertMarkToTimestamp(startOrMeasureOptions.duration);
- startTime = end - duration;
- } else if (typeof startOrMeasureOptions === "string") {
- startTime = convertMarkToTimestamp(startOrMeasureOptions);
- } else {
- startTime = 0;
- }
- const entry = new PerformanceMeasure(
- measureName,
- startTime,
- endTime - startTime,
- typeof startOrMeasureOptions === "object"
- ? startOrMeasureOptions.detail ?? null
- : null,
- illegalConstructorKey,
- );
- ArrayPrototypePush(performanceEntries, entry);
- return entry;
- }
-
- now() {
- webidl.assertBranded(this, PerformancePrototype);
- return now();
- }
-
- toJSON() {
- webidl.assertBranded(this, PerformancePrototype);
- return {};
- }
-
- [customInspect](inspect) {
- return inspect(consoleInternal.createFilteredInspectProxy({
- object: this,
- evaluate: ObjectPrototypeIsPrototypeOf(PerformancePrototype, this),
- keys: [],
- }));
- }
- }
- webidl.configurePrototype(Performance);
- const PerformancePrototype = Performance.prototype;
-
- window.__bootstrap.performance = {
- PerformanceEntry,
- PerformanceMark,
- PerformanceMeasure,
- Performance,
- performance: webidl.createBranded(Performance),
- };
-})(this);
diff --git a/ext/timers/Cargo.toml b/ext/timers/Cargo.toml
deleted file mode 100644
index 15979388e..000000000
--- a/ext/timers/Cargo.toml
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
-
-[package]
-name = "deno_timers"
-version = "0.34.0"
-authors = ["the Deno authors"]
-edition = "2021"
-license = "MIT"
-readme = "README.md"
-repository = "https://github.com/denoland/deno"
-description = "Timers API implementation for Deno"
-
-[lib]
-path = "lib.rs"
-
-[dependencies]
-deno_core = { version = "0.118.0", path = "../../core" }
-tokio = { version = "1.10.1", features = ["full"] }
-
-[dev-dependencies]
-deno_bench_util = { version = "0.30.0", path = "../../bench_util" }
-deno_url = { version = "0.36.0", path = "../url" }
-deno_web = { version = "0.67.0", path = "../web" }
-deno_webidl = { version = "0.36.0", path = "../webidl" }
-
-[[bench]]
-name = "timers_ops"
-harness = false
diff --git a/ext/timers/README.md b/ext/timers/README.md
deleted file mode 100644
index 5a2a8e516..000000000
--- a/ext/timers/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# deno_timers
-
-This crate implements the timers API.
-
-Spec: https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers
diff --git a/ext/timers/benches/timers_ops.rs b/ext/timers/benches/timers_ops.rs
deleted file mode 100644
index 8d13d5807..000000000
--- a/ext/timers/benches/timers_ops.rs
+++ /dev/null
@@ -1,54 +0,0 @@
-use deno_core::Extension;
-
-use deno_bench_util::bench_or_profile;
-use deno_bench_util::bencher::{benchmark_group, Bencher};
-use deno_bench_util::{bench_js_async, bench_js_sync};
-use deno_web::BlobStore;
-
-struct Permissions;
-
-impl deno_timers::TimersPermission for Permissions {
- fn allow_hrtime(&mut self) -> bool {
- true
- }
- fn check_unstable(
- &self,
- _state: &deno_core::OpState,
- _api_name: &'static str,
- ) {
- }
-}
-
-fn setup() -> Vec<Extension> {
- vec![
- deno_webidl::init(),
- deno_url::init(),
- deno_web::init(BlobStore::default(), None),
- deno_timers::init::<Permissions>(),
- Extension::builder()
- .js(vec![
- ("setup",
- Box::new(|| Ok(r#"
- const { opNow, setTimeout, handleTimerMacrotask } = globalThis.__bootstrap.timers;
- Deno.core.setMacrotaskCallback(handleTimerMacrotask);
- "#.to_owned())),
- ),
- ])
- .state(|state| {
- state.put(Permissions{});
- Ok(())
- })
- .build()
- ]
-}
-
-fn bench_op_now(b: &mut Bencher) {
- bench_js_sync(b, r#"opNow();"#, setup);
-}
-
-fn bench_set_timeout(b: &mut Bencher) {
- bench_js_async(b, r#"setTimeout(() => {}, 0);"#, setup);
-}
-
-benchmark_group!(benches, bench_op_now, bench_set_timeout,);
-bench_or_profile!(benches);
diff --git a/ext/timers/lib.rs b/ext/timers/lib.rs
deleted file mode 100644
index 63aabe9d4..000000000
--- a/ext/timers/lib.rs
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
-
-//! This module helps deno implement timers and performance APIs.
-
-use deno_core::error::AnyError;
-use deno_core::include_js_files;
-use deno_core::op_async;
-use deno_core::op_sync;
-use deno_core::CancelFuture;
-use deno_core::CancelHandle;
-use deno_core::Extension;
-use deno_core::OpState;
-use deno_core::Resource;
-use deno_core::ResourceId;
-use std::borrow::Cow;
-use std::cell::RefCell;
-use std::rc::Rc;
-use std::time::Duration;
-use std::time::Instant;
-
-pub trait TimersPermission {
- fn allow_hrtime(&mut self) -> bool;
- fn check_unstable(&self, state: &OpState, api_name: &'static str);
-}
-
-pub fn init<P: TimersPermission + 'static>() -> Extension {
- Extension::builder()
- .js(include_js_files!(
- prefix "deno:ext/timers",
- "01_timers.js",
- "02_performance.js",
- ))
- .ops(vec![
- ("op_now", op_sync(op_now::<P>)),
- ("op_timer_handle", op_sync(op_timer_handle)),
- ("op_sleep", op_async(op_sleep)),
- ("op_sleep_sync", op_sync(op_sleep_sync::<P>)),
- ])
- .state(|state| {
- state.put(StartTime::now());
- Ok(())
- })
- .build()
-}
-
-pub type StartTime = Instant;
-
-// Returns a milliseconds and nanoseconds subsec
-// since the start time of the deno runtime.
-// If the High precision flag is not set, the
-// nanoseconds are rounded on 2ms.
-pub fn op_now<TP>(
- state: &mut OpState,
- _argument: (),
- _: (),
-) -> Result<f64, AnyError>
-where
- TP: TimersPermission + 'static,
-{
- let start_time = state.borrow::<StartTime>();
- let seconds = start_time.elapsed().as_secs();
- let mut subsec_nanos = start_time.elapsed().subsec_nanos() as f64;
- let reduced_time_precision = 2_000_000.0; // 2ms in nanoseconds
-
- // If the permission is not enabled
- // Round the nano result on 2 milliseconds
- // see: https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp#Reduced_time_precision
- if !state.borrow_mut::<TP>().allow_hrtime() {
- subsec_nanos -= subsec_nanos % reduced_time_precision;
- }
-
- let result = (seconds * 1_000) as f64 + (subsec_nanos / 1_000_000.0);
-
- Ok(result)
-}
-
-pub struct TimerHandle(Rc<CancelHandle>);
-
-impl Resource for TimerHandle {
- fn name(&self) -> Cow<str> {
- "timer".into()
- }
-
- fn close(self: Rc<Self>) {
- self.0.cancel();
- }
-}
-
-/// Creates a [`TimerHandle`] resource that can be used to cancel invocations of
-/// [`op_sleep`].
-pub fn op_timer_handle(
- state: &mut OpState,
- _: (),
- _: (),
-) -> Result<ResourceId, AnyError> {
- let rid = state
- .resource_table
- .add(TimerHandle(CancelHandle::new_rc()));
- Ok(rid)
-}
-
-/// Waits asynchronously until either `millis` milliseconds have passed or the
-/// [`TimerHandle`] resource given by `rid` has been canceled.
-pub async fn op_sleep(
- state: Rc<RefCell<OpState>>,
- millis: u64,
- rid: ResourceId,
-) -> Result<(), AnyError> {
- let handle = state.borrow().resource_table.get::<TimerHandle>(rid)?;
- tokio::time::sleep(Duration::from_millis(millis))
- .or_cancel(handle.0.clone())
- .await?;
- Ok(())
-}
-
-pub fn op_sleep_sync<TP>(
- state: &mut OpState,
- millis: u64,
- _: (),
-) -> Result<(), AnyError>
-where
- TP: TimersPermission + 'static,
-{
- state.borrow::<TP>().check_unstable(state, "Deno.sleepSync");
- std::thread::sleep(Duration::from_millis(millis));
- Ok(())
-}