1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-11 08:33:43 -05:00

refactor: Event and EventTarget implementations (#4707)

Refactors Event and EventTarget so that they better encapsulate their
non-public data as well as are more forward compatible with things like
DOM Nodes.

Moves `dom_types.ts` -> `dom_types.d.ts` which was always the intention,
it was a legacy of when we used to build the types from the code and the
limitations of the compiler.  There was a lot of cruft in `dom_types`
which shouldn't have been there, and mis-alignment to the DOM standards.
This generally has been eliminated, though we still have some minor
differences from the DOM (like the removal of some deprecated
methods/properties).

Adds `DOMException`.  Strictly it shouldn't inherit from `Error`, but
most browsers provide a stack trace when one is thrown, so the behaviour
in Deno actually better matches the browser.

`Event` still doesn't log to console like it does in the browser.  I
 wanted to get this raised and that could be an enhancement later on (it
 currently doesn't either).
This commit is contained in:
Kitson Kelly 2020-04-12 01:42:02 +10:00 committed by GitHub
parent 2b362bef85
commit fc4819e1e0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
40 changed files with 1205 additions and 1120 deletions

View file

@ -1,10 +1,12 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import "./lib.deno.shared_globals.d.ts";
import * as blob from "./web/blob.ts"; import * as blob from "./web/blob.ts";
import * as consoleTypes from "./web/console.ts"; import * as consoleTypes from "./web/console.ts";
import * as promiseTypes from "./web/promise.ts"; import * as promiseTypes from "./web/promise.ts";
import * as customEvent from "./web/custom_event.ts"; import * as customEvent from "./web/custom_event.ts";
import * as domTypes from "./web/dom_types.ts"; import * as domException from "./web/dom_exception.ts";
import * as domFile from "./web/dom_file.ts"; import * as domFile from "./web/dom_file.ts";
import * as event from "./web/event.ts"; import * as event from "./web/event.ts";
import * as eventTarget from "./web/event_target.ts"; import * as eventTarget from "./web/event_target.ts";
@ -123,21 +125,13 @@ declare global {
// Only `var` variables show up in the `globalThis` type when doing a global // Only `var` variables show up in the `globalThis` type when doing a global
// scope augmentation. // scope augmentation.
/* eslint-disable no-var */ /* eslint-disable no-var */
var addEventListener: (
type: string,
callback: domTypes.EventListenerOrEventListenerObject | null,
options?: boolean | domTypes.AddEventListenerOptions | undefined
) => void;
var queueMicrotask: (callback: () => void) => void;
var console: consoleTypes.Console;
var location: domTypes.Location;
// Assigned to `window` global - main runtime // Assigned to `window` global - main runtime
var Deno: { var Deno: {
core: DenoCore; core: DenoCore;
}; };
var onload: ((e: domTypes.Event) => void) | undefined; var onload: ((e: Event) => void) | undefined;
var onunload: ((e: domTypes.Event) => void) | undefined; var onunload: ((e: Event) => void) | undefined;
var bootstrapMainRuntime: (() => void) | undefined; var bootstrapMainRuntime: (() => void) | undefined;
// Assigned to `self` global - worker runtime and compiler // Assigned to `self` global - worker runtime and compiler
@ -150,7 +144,7 @@ declare global {
source: string, source: string,
lineno: number, lineno: number,
colno: number, colno: number,
e: domTypes.Event e: Event
) => boolean | void) ) => boolean | void)
| undefined; | undefined;
@ -163,9 +157,6 @@ declare global {
// Assigned to `self` global - compiler // Assigned to `self` global - compiler
var bootstrapTsCompilerRuntime: (() => void) | undefined; var bootstrapTsCompilerRuntime: (() => void) | undefined;
var bootstrapWasmCompilerRuntime: (() => void) | undefined; var bootstrapWasmCompilerRuntime: (() => void) | undefined;
var performance: performanceUtil.Performance;
var setTimeout: typeof timers.setTimeout;
/* eslint-enable */ /* eslint-enable */
} }
@ -218,9 +209,10 @@ export const windowOrWorkerGlobalScopeProperties = {
console: writable(new consoleTypes.Console(core.print)), console: writable(new consoleTypes.Console(core.print)),
Blob: nonEnumerable(blob.DenoBlob), Blob: nonEnumerable(blob.DenoBlob),
File: nonEnumerable(domFile.DomFileImpl), File: nonEnumerable(domFile.DomFileImpl),
CustomEvent: nonEnumerable(customEvent.CustomEvent), CustomEvent: nonEnumerable(customEvent.CustomEventImpl),
Event: nonEnumerable(event.Event), DOMException: nonEnumerable(domException.DOMExceptionImpl),
EventTarget: nonEnumerable(eventTarget.EventTarget), Event: nonEnumerable(event.EventImpl),
EventTarget: nonEnumerable(eventTarget.EventTargetImpl),
URL: nonEnumerable(url.URL), URL: nonEnumerable(url.URL),
URLSearchParams: nonEnumerable(urlSearchParams.URLSearchParams), URLSearchParams: nonEnumerable(urlSearchParams.URLSearchParams),
Headers: nonEnumerable(headers.Headers), Headers: nonEnumerable(headers.Headers),
@ -234,19 +226,17 @@ export const windowOrWorkerGlobalScopeProperties = {
Worker: nonEnumerable(workers.WorkerImpl), Worker: nonEnumerable(workers.WorkerImpl),
}; };
export const eventTargetProperties = { // eslint-disable-next-line @typescript-eslint/no-explicit-any
[domTypes.eventTargetHost]: nonEnumerable(null), export function setEventTargetData(value: any): void {
[domTypes.eventTargetListeners]: nonEnumerable({}), eventTarget.eventTargetData.set(value, eventTarget.getDefaultTargetData());
[domTypes.eventTargetMode]: nonEnumerable(""), }
[domTypes.eventTargetNodeType]: nonEnumerable(0),
[eventTarget.eventTargetAssignedSlot]: nonEnumerable(false),
[eventTarget.eventTargetHasActivationBehavior]: nonEnumerable(false),
export const eventTargetProperties = {
addEventListener: readOnly( addEventListener: readOnly(
eventTarget.EventTarget.prototype.addEventListener eventTarget.EventTargetImpl.prototype.addEventListener
), ),
dispatchEvent: readOnly(eventTarget.EventTarget.prototype.dispatchEvent), dispatchEvent: readOnly(eventTarget.EventTargetImpl.prototype.dispatchEvent),
removeEventListener: readOnly( removeEventListener: readOnly(
eventTarget.EventTarget.prototype.removeEventListener eventTarget.EventTargetImpl.prototype.removeEventListener
), ),
}; };

View file

@ -1,12 +1,8 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, no-var */
/// <reference no-default-lib="true" /> /// <reference no-default-lib="true" />
// TODO: we need to remove this, but Fetch::Response::Body implements Reader
// which requires Deno.EOF, and we shouldn't be leaking that, but https_proxy
// at the least requires the Reader interface on Body, which it shouldn't
/// <reference lib="deno.ns" />
/// <reference lib="esnext" /> /// <reference lib="esnext" />
// This follows the WebIDL at: https://webassembly.github.io/spec/js-api/ // This follows the WebIDL at: https://webassembly.github.io/spec/js-api/
@ -184,6 +180,7 @@ declare function setTimeout(
delay?: number, delay?: number,
...args: unknown[] ...args: unknown[]
): number; ): number;
/** Repeatedly calls a function , with a fixed time delay between each call. */ /** Repeatedly calls a function , with a fixed time delay between each call. */
declare function setInterval( declare function setInterval(
cb: (...args: unknown[]) => void, cb: (...args: unknown[]) => void,
@ -194,8 +191,8 @@ declare function clearTimeout(id?: number): void;
declare function clearInterval(id?: number): void; declare function clearInterval(id?: number): void;
declare function queueMicrotask(func: Function): void; declare function queueMicrotask(func: Function): void;
declare const console: Console; declare var console: Console;
declare const location: Location; declare var location: Location;
declare function addEventListener( declare function addEventListener(
type: string, type: string,
@ -315,6 +312,12 @@ interface DOMStringList {
[index: number]: string; [index: number]: string;
} }
declare class DOMException extends Error {
constructor(message?: string, name?: string);
readonly name: string;
readonly message: string;
}
/** The location (URL) of the object it is linked to. Changes done on it are /** The location (URL) of the object it is linked to. Changes done on it are
* reflected on the object it relates to. Both the Document and Window * reflected on the object it relates to. Both the Document and Window
* interface have such a linked Location, accessible via Document.location and * interface have such a linked Location, accessible via Document.location and
@ -1060,122 +1063,81 @@ declare namespace performance {
export function now(): number; export function now(): number;
} }
/** An event which takes place in the DOM. */
interface Event {
/**
* Returns true or false depending on how event was initialized. True if
* event goes through its target's ancestors in reverse tree order, and
* false otherwise.
*/
readonly bubbles: boolean;
// TODO(ry) Remove cancelBubbleImmediately - non-standard extension.
cancelBubbleImmediately: boolean;
cancelBubble: boolean;
/**
* Returns true or false depending on how event was initialized. Its return
* value does not always carry meaning, but true can indicate that part of
* the operation during which event was dispatched, can be canceled by
* invoking the preventDefault() method.
*/
readonly cancelable: boolean;
/**
* Returns true or false depending on how event was initialized. True if
* event invokes listeners past a ShadowRoot node that is the root of its
* target, and false otherwise.
*/
readonly composed: boolean;
/**
* Returns the object whose event listener's callback is currently being
* invoked.
*/
readonly currentTarget: EventTarget | null;
/**
* Returns true if preventDefault() was invoked successfully to indicate
* cancelation, and false otherwise.
*/
readonly defaultPrevented: boolean;
/**
* Returns the event's phase, which is one of NONE, CAPTURING_PHASE,
* AT_TARGET, and BUBBLING_PHASE.
*/
readonly eventPhase: number;
/**
* Returns true if event was dispatched by the user agent, and false
* otherwise.
*/
readonly isTrusted: boolean;
returnValue: boolean;
/** @deprecated */
readonly srcElement: EventTarget | null;
/**
* Returns the object to which event is dispatched (its target).
*/
readonly target: EventTarget | null;
/**
* Returns the event's timestamp as the number of milliseconds measured
* relative to the time origin.
*/
readonly timeStamp: number;
/**
* Returns the type of event, e.g. "click", "hashchange", or "submit".
*/
readonly type: string;
/**
* Returns the invocation target objects of event's path (objects on which
* listeners will be invoked), except for any nodes in shadow trees of which
* the shadow root's mode is "closed" that are not reachable from event's
* currentTarget.
*/
composedPath(): EventTarget[];
initEvent(type: string, bubbles?: boolean, cancelable?: boolean): void;
/**
* If invoked when the cancelable attribute value is true, and while
* executing a listener for the event with passive set to false, signals to
* the operation that caused event to be dispatched that it needs to be
* canceled.
*/
preventDefault(): void;
/**
* Invoking this method prevents event from reaching any registered event
* listeners after the current one finishes running and, when dispatched in
* a tree, also prevents event from reaching any other objects.
*/
stopImmediatePropagation(): void;
/**
* When dispatched in a tree, invoking this method prevents event from
* reaching any objects other than the current object.
*/
stopPropagation(): void;
readonly AT_TARGET: number;
readonly BUBBLING_PHASE: number;
readonly CAPTURING_PHASE: number;
readonly NONE: number;
}
interface EventInit { interface EventInit {
bubbles?: boolean; bubbles?: boolean;
cancelable?: boolean; cancelable?: boolean;
composed?: boolean; composed?: boolean;
} }
declare const Event: { /** An event which takes place in the DOM. */
prototype: Event; declare class Event {
new (type: string, eventInitDict?: EventInit): Event; constructor(type: string, eventInitDict?: EventInit);
/** Returns true or false depending on how event was initialized. True if
* event goes through its target's ancestors in reverse tree order, and
* false otherwise. */
readonly bubbles: boolean;
cancelBubble: boolean;
/** Returns true or false depending on how event was initialized. Its return
* value does not always carry meaning, but true can indicate that part of the
* operation during which event was dispatched, can be canceled by invoking
* the preventDefault() method. */
readonly cancelable: boolean;
/** Returns true or false depending on how event was initialized. True if
* event invokes listeners past a ShadowRoot node that is the root of its
* target, and false otherwise. */
readonly composed: boolean;
/** Returns the object whose event listener's callback is currently being
* invoked. */
readonly currentTarget: EventTarget | null;
/** Returns true if preventDefault() was invoked successfully to indicate
* cancellation, and false otherwise. */
readonly defaultPrevented: boolean;
/** Returns the event's phase, which is one of NONE, CAPTURING_PHASE,
* AT_TARGET, and BUBBLING_PHASE. */
readonly eventPhase: number;
/** Returns true if event was dispatched by the user agent, and false
* otherwise. */
readonly isTrusted: boolean;
/** Returns the object to which event is dispatched (its target). */
readonly target: EventTarget | null;
/** Returns the event's timestamp as the number of milliseconds measured
* relative to the time origin. */
readonly timeStamp: number;
/** Returns the type of event, e.g. "click", "hashchange", or "submit". */
readonly type: string;
/** Returns the invocation target objects of event's path (objects on which
* listeners will be invoked), except for any nodes in shadow trees of which
* the shadow root's mode is "closed" that are not reachable from event's
* currentTarget. */
composedPath(): EventTarget[];
/** If invoked when the cancelable attribute value is true, and while
* executing a listener for the event with passive set to false, signals to
* the operation that caused event to be dispatched that it needs to be
* canceled. */
preventDefault(): void;
/** Invoking this method prevents event from reaching any registered event
* listeners after the current one finishes running and, when dispatched in a
* tree, also prevents event from reaching any other objects. */
stopImmediatePropagation(): void;
/** When dispatched in a tree, invoking this method prevents event from
* reaching any objects other than the current object. */
stopPropagation(): void;
readonly AT_TARGET: number; readonly AT_TARGET: number;
readonly BUBBLING_PHASE: number; readonly BUBBLING_PHASE: number;
readonly CAPTURING_PHASE: number; readonly CAPTURING_PHASE: number;
readonly NONE: number; readonly NONE: number;
}; static readonly AT_TARGET: number;
static readonly BUBBLING_PHASE: number;
static readonly CAPTURING_PHASE: number;
static readonly NONE: number;
}
/** /**
* EventTarget is a DOM interface implemented by objects that can receive events * EventTarget is a DOM interface implemented by objects that can receive events
* and may have listeners for them. * and may have listeners for them.
*/ */
interface EventTarget { declare class EventTarget {
/** /** Appends an event listener for events whose type attribute value is type.
* Appends an event listener for events whose type attribute value is type.
* The callback argument sets the callback that will be invoked when the event * The callback argument sets the callback that will be invoked when the event
* is dispatched. * is dispatched.
* *
@ -1197,41 +1159,32 @@ interface EventTarget {
* invoked once after which the event listener will be removed. * invoked once after which the event listener will be removed.
* *
* The event listener is appended to target's event listener list and is not * The event listener is appended to target's event listener list and is not
* appended if it has the same type, callback, and capture. * appended if it has the same type, callback, and capture. */
*/
addEventListener( addEventListener(
type: string, type: string,
listener: EventListenerOrEventListenerObject | null, listener: EventListenerOrEventListenerObject | null,
options?: boolean | AddEventListenerOptions options?: boolean | AddEventListenerOptions
): void; ): void;
/** /** Dispatches a synthetic event event to target and returns true if either
* Dispatches a synthetic event event to target and returns true if either
* event's cancelable attribute value is false or its preventDefault() method * event's cancelable attribute value is false or its preventDefault() method
* was not invoked, and false otherwise. * was not invoked, and false otherwise. */
*/
dispatchEvent(event: Event): boolean; dispatchEvent(event: Event): boolean;
/** /** Removes the event listener in target's event listener list with the same
* Removes the event listener in target's event listener list with the same * type, callback, and options. */
* type, callback, and options.
*/
removeEventListener( removeEventListener(
type: string, type: string,
callback: EventListenerOrEventListenerObject | null, callback: EventListenerOrEventListenerObject | null,
options?: EventListenerOptions | boolean options?: EventListenerOptions | boolean
): void; ): void;
[Symbol.toStringTag]: string;
} }
declare const EventTarget: {
prototype: EventTarget;
new (): EventTarget;
};
interface EventListener { interface EventListener {
(evt: Event): void; (evt: Event): void | Promise<void>;
} }
interface EventListenerObject { interface EventListenerObject {
handleEvent(evt: Event): void; handleEvent(evt: Event): void | Promise<void>;
} }
declare type EventListenerOrEventListenerObject = declare type EventListenerOrEventListenerObject =
@ -1257,27 +1210,16 @@ interface ProgressEvent<T extends EventTarget = EventTarget> extends Event {
readonly total: number; readonly total: number;
} }
interface CustomEvent<T = any> extends Event {
/**
* Returns any custom data event was created with. Typically used for synthetic events.
*/
readonly detail: T;
initCustomEvent(
typeArg: string,
canBubbleArg: boolean,
cancelableArg: boolean,
detailArg: T
): void;
}
interface CustomEventInit<T = any> extends EventInit { interface CustomEventInit<T = any> extends EventInit {
detail?: T; detail?: T;
} }
declare const CustomEvent: { declare class CustomEvent<T = any> extends Event {
prototype: CustomEvent; constructor(typeArg: string, eventInitDict?: CustomEventInit<T>);
new <T>(typeArg: string, eventInitDict?: CustomEventInit<T>): CustomEvent<T>; /** Returns any custom data event was created with. Typically used for
}; * synthetic events. */
readonly detail: T;
}
interface AbortSignalEventMap { interface AbortSignalEventMap {
abort: Event; abort: Event;

View file

@ -1,28 +1,28 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-interface, @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
/// <reference no-default-lib="true" /> /// <reference no-default-lib="true" />
/// <reference lib="deno.ns" /> /// <reference lib="deno.ns" />
/// <reference lib="deno.shared_globals" /> /// <reference lib="deno.shared_globals" />
/// <reference lib="esnext" /> /// <reference lib="esnext" />
declare interface Window { declare interface Window extends EventTarget {
window: Window & typeof globalThis; readonly window: Window & typeof globalThis;
self: Window & typeof globalThis; readonly self: Window & typeof globalThis;
onload: Function | undefined; onload: ((this: Window, ev: Event) => any) | null;
onunload: Function | undefined; onunload: ((this: Window, ev: Event) => any) | null;
location: Location; location: Location;
crypto: Crypto; crypto: Crypto;
close: () => void; close: () => void;
closed: boolean; readonly closed: boolean;
Deno: typeof Deno; Deno: typeof Deno;
} }
declare const window: Window & typeof globalThis; declare const window: Window & typeof globalThis;
declare const self: Window & typeof globalThis; declare const self: Window & typeof globalThis;
declare const onload: Function | undefined; declare const onload: ((this: Window, ev: Event) => any) | null;
declare const onunload: Function | undefined; declare const onunload: ((this: Window, ev: Event) => any) | null;
declare const crypto: Crypto; declare const crypto: Crypto;
declare interface Crypto { declare interface Crypto {
@ -45,4 +45,4 @@ declare interface Crypto {
): T; ): T;
} }
/* eslint-enable @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-interface, @typescript-eslint/no-explicit-any */ /* eslint-enable @typescript-eslint/no-explicit-any */

View file

@ -8,7 +8,6 @@
// It sets up runtime by providing globals for `WindowScope` and adds `Deno` global. // It sets up runtime by providing globals for `WindowScope` and adds `Deno` global.
import * as Deno from "./deno.ts"; import * as Deno from "./deno.ts";
import * as domTypes from "./web/dom_types.ts";
import * as csprng from "./ops/get_random_values.ts"; import * as csprng from "./ops/get_random_values.ts";
import { exit } from "./ops/os.ts"; import { exit } from "./ops/os.ts";
import { import {
@ -18,6 +17,7 @@ import {
windowOrWorkerGlobalScopeMethods, windowOrWorkerGlobalScopeMethods,
windowOrWorkerGlobalScopeProperties, windowOrWorkerGlobalScopeProperties,
eventTargetProperties, eventTargetProperties,
setEventTargetData,
} from "./globals.ts"; } from "./globals.ts";
import { internalObject } from "./internals.ts"; import { internalObject } from "./internals.ts";
import { setSignals } from "./signals.ts"; import { setSignals } from "./signals.ts";
@ -59,9 +59,9 @@ export const mainRuntimeGlobalProperties = {
self: readOnly(globalThis), self: readOnly(globalThis),
crypto: readOnly(csprng), crypto: readOnly(csprng),
// TODO(bartlomieju): from MDN docs (https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope) // TODO(bartlomieju): from MDN docs (https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope)
// it seems those two properties should be availble to workers as well // it seems those two properties should be available to workers as well
onload: writable(undefined), onload: writable(null),
onunload: writable(undefined), onunload: writable(null),
close: writable(windowClose), close: writable(windowClose),
closed: getterOnly(() => windowIsClosing), closed: getterOnly(() => windowIsClosing),
}; };
@ -78,15 +78,16 @@ export function bootstrapMainRuntime(): void {
Object.defineProperties(globalThis, windowOrWorkerGlobalScopeProperties); Object.defineProperties(globalThis, windowOrWorkerGlobalScopeProperties);
Object.defineProperties(globalThis, eventTargetProperties); Object.defineProperties(globalThis, eventTargetProperties);
Object.defineProperties(globalThis, mainRuntimeGlobalProperties); Object.defineProperties(globalThis, mainRuntimeGlobalProperties);
setEventTargetData(globalThis);
// Registers the handler for window.onload function. // Registers the handler for window.onload function.
globalThis.addEventListener("load", (e: domTypes.Event): void => { globalThis.addEventListener("load", (e) => {
const { onload } = globalThis; const { onload } = globalThis;
if (typeof onload === "function") { if (typeof onload === "function") {
onload(e); onload(e);
} }
}); });
// Registers the handler for window.onunload function. // Registers the handler for window.onunload function.
globalThis.addEventListener("unload", (e: domTypes.Event): void => { globalThis.addEventListener("unload", (e) => {
const { onunload } = globalThis; const { onunload } = globalThis;
if (typeof onunload === "function") { if (typeof onunload === "function") {
onunload(e); onunload(e);

View file

@ -0,0 +1,9 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { unitTest, assertEquals, assert } from "./test_util.ts";
unitTest(function testDomError() {
const de = new DOMException("foo", "bar");
assert(de);
assertEquals(de.message, "foo");
assertEquals(de.name, "bar");
});

View file

@ -35,18 +35,6 @@ unitTest(function constructedEventTargetCanBeUsedAsExpected(): void {
assertEquals(callCount, 2); assertEquals(callCount, 2);
}); });
// TODO(ry) Should AddEventListenerOptions and EventListenerOptions be exposed
// from the public API?
interface AddEventListenerOptions extends EventListenerOptions {
once?: boolean;
passive?: boolean;
}
interface EventListenerOptions {
capture?: boolean;
}
unitTest(function anEventTargetCanBeSubclassed(): void { unitTest(function anEventTargetCanBeSubclassed(): void {
class NicerEventTarget extends EventTarget { class NicerEventTarget extends EventTarget {
on( on(

View file

@ -48,10 +48,8 @@ unitTest(function eventStopImmediatePropagationSuccess(): void {
const event = new Event(type); const event = new Event(type);
assertEquals(event.cancelBubble, false); assertEquals(event.cancelBubble, false);
assertEquals(event.cancelBubbleImmediately, false);
event.stopImmediatePropagation(); event.stopImmediatePropagation();
assertEquals(event.cancelBubble, true); assertEquals(event.cancelBubble, true);
assertEquals(event.cancelBubbleImmediately, true);
}); });
unitTest(function eventPreventDefaultSuccess(): void { unitTest(function eventPreventDefaultSuccess(): void {

View file

@ -16,6 +16,7 @@ import "./custom_event_test.ts";
import "./dir_test.ts"; import "./dir_test.ts";
import "./dispatch_minimal_test.ts"; import "./dispatch_minimal_test.ts";
import "./dispatch_json_test.ts"; import "./dispatch_json_test.ts";
import "./dom_exception_test.ts";
import "./error_stack_test.ts"; import "./error_stack_test.ts";
import "./event_test.ts"; import "./event_test.ts";
import "./event_target_test.ts"; import "./event_target_test.ts";

View file

@ -1,5 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import * as domTypes from "./dom_types.ts"; import * as domTypes from "./dom_types.d.ts";
import { TextDecoder, TextEncoder } from "./text_encoding.ts"; import { TextDecoder, TextEncoder } from "./text_encoding.ts";
import { build } from "../build.ts"; import { build } from "../build.ts";
import { ReadableStream } from "./streams/mod.ts"; import { ReadableStream } from "./streams/mod.ts";

View file

@ -2,7 +2,7 @@ import * as formData from "./form_data.ts";
import * as blob from "./blob.ts"; import * as blob from "./blob.ts";
import * as encoding from "./text_encoding.ts"; import * as encoding from "./text_encoding.ts";
import * as headers from "./headers.ts"; import * as headers from "./headers.ts";
import * as domTypes from "./dom_types.ts"; import * as domTypes from "./dom_types.d.ts";
import { ReadableStream } from "./streams/mod.ts"; import { ReadableStream } from "./streams/mod.ts";
const { Headers } = headers; const { Headers } = headers;

View file

@ -1,44 +1,28 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import * as domTypes from "./dom_types.ts"; import { EventImpl as Event } from "./event.ts";
import * as event from "./event.ts";
import { requiredArguments } from "./util.ts"; import { requiredArguments } from "./util.ts";
export class CustomEvent extends event.Event implements domTypes.CustomEvent { // eslint-disable-next-line @typescript-eslint/no-explicit-any
// eslint-disable-next-line @typescript-eslint/no-explicit-any export class CustomEventImpl<T = any> extends Event implements CustomEvent {
#detail: any; #detail: T;
constructor( constructor(type: string, eventInitDict: CustomEventInit<T> = {}) {
type: string, super(type, eventInitDict);
customEventInitDict: domTypes.CustomEventInit = {}
) {
super(type, customEventInitDict);
requiredArguments("CustomEvent", arguments.length, 1); requiredArguments("CustomEvent", arguments.length, 1);
const { detail = null } = customEventInitDict; const { detail } = eventInitDict;
this.#detail = detail; this.#detail = detail as T;
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
get detail(): any { get detail(): T {
return this.#detail; return this.#detail;
} }
initCustomEvent(
_type: string,
_bubbles?: boolean,
_cancelable?: boolean,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
detail?: any
): void {
if (this.dispatched) {
return;
}
this.#detail = detail;
}
get [Symbol.toStringTag](): string { get [Symbol.toStringTag](): string {
return "CustomEvent"; return "CustomEvent";
} }
} }
Reflect.defineProperty(CustomEvent.prototype, "detail", { enumerable: true }); Reflect.defineProperty(CustomEventImpl.prototype, "detail", {
enumerable: true,
});

View file

@ -0,0 +1,14 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
export class DOMExceptionImpl extends Error implements DOMException {
#name: string;
constructor(message = "", name = "Error") {
super(message);
this.#name = name;
}
get name(): string {
return this.#name;
}
}

View file

@ -1,5 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import * as domTypes from "./dom_types.ts"; import * as domTypes from "./dom_types.d.ts";
import * as blob from "./blob.ts"; import * as blob from "./blob.ts";
export class DomFileImpl extends blob.DenoBlob implements domTypes.DomFile { export class DomFileImpl extends blob.DenoBlob implements domTypes.DomFile {

View file

@ -1,11 +1,21 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { DomIterable } from "./dom_types.ts";
import { requiredArguments } from "./util.ts"; import { requiredArguments } from "./util.ts";
import { exposeForTest } from "../internals.ts"; import { exposeForTest } from "../internals.ts";
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
type Constructor<T = {}> = new (...args: any[]) => T; export type Constructor<T = {}> = new (...args: any[]) => T;
export interface DomIterable<K, V> {
keys(): IterableIterator<K>;
values(): IterableIterator<V>;
entries(): IterableIterator<[K, V]>;
[Symbol.iterator](): IterableIterator<[K, V]>;
forEach(
callback: (value: V, key: K, parent: this) => void,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
thisArg?: any
): void;
}
export function DomIterableMixin<K, V, TBase extends Constructor>( export function DomIterableMixin<K, V, TBase extends Constructor>(
Base: TBase, Base: TBase,

View file

@ -23,7 +23,7 @@ export type HeadersInit =
| Headers | Headers
| Array<[string, string]> | Array<[string, string]>
| Record<string, string>; | Record<string, string>;
export type URLSearchParamsInit = string | string[][] | Record<string, string>;
type BodyInit = type BodyInit =
| Blob | Blob
| BufferSource | BufferSource
@ -31,7 +31,9 @@ type BodyInit =
| URLSearchParams | URLSearchParams
| ReadableStream | ReadableStream
| string; | string;
export type RequestInfo = Request | string; export type RequestInfo = Request | string;
type ReferrerPolicy = type ReferrerPolicy =
| "" | ""
| "no-referrer" | "no-referrer"
@ -39,21 +41,12 @@ type ReferrerPolicy =
| "origin-only" | "origin-only"
| "origin-when-cross-origin" | "origin-when-cross-origin"
| "unsafe-url"; | "unsafe-url";
export type BlobPart = BufferSource | Blob | string; export type BlobPart = BufferSource | Blob | string;
export type FormDataEntryValue = DomFile | string; export type FormDataEntryValue = DomFile | string;
export interface DomIterable<K, V> { export type EndingType = "transparent" | "native";
keys(): IterableIterator<K>;
values(): IterableIterator<V>;
entries(): IterableIterator<[K, V]>;
[Symbol.iterator](): IterableIterator<[K, V]>;
forEach(
callback: (value: V, key: K, parent: this) => void,
thisArg?: any
): void;
}
type EndingType = "transparent" | "native";
export interface BlobPropertyBag { export interface BlobPropertyBag {
type?: string; type?: string;
@ -64,67 +57,16 @@ interface AbortSignalEventMap {
abort: ProgressEvent; abort: ProgressEvent;
} }
// https://dom.spec.whatwg.org/#node
export enum NodeType {
ELEMENT_NODE = 1,
TEXT_NODE = 3,
DOCUMENT_FRAGMENT_NODE = 11,
}
export const eventTargetHost: unique symbol = Symbol();
export const eventTargetListeners: unique symbol = Symbol();
export const eventTargetMode: unique symbol = Symbol();
export const eventTargetNodeType: unique symbol = Symbol();
export interface EventListener {
// Different from lib.dom.d.ts. Added Promise<void>
(evt: Event): void | Promise<void>;
}
export interface EventListenerObject {
// Different from lib.dom.d.ts. Added Promise<void>
handleEvent(evt: Event): void | Promise<void>;
}
export type EventListenerOrEventListenerObject =
| EventListener
| EventListenerObject;
// This is actually not part of actual DOM types,
// but an implementation specific thing on our custom EventTarget
// (due to the presence of our custom symbols)
export interface EventTargetListener {
callback: EventListenerOrEventListenerObject;
options: AddEventListenerOptions;
}
export interface EventTarget {
// TODO: below 4 symbol props should not present on EventTarget WebIDL.
// They should be implementation specific details.
[eventTargetHost]: EventTarget | null;
[eventTargetListeners]: { [type in string]: EventTargetListener[] };
[eventTargetMode]: string;
[eventTargetNodeType]: NodeType;
addEventListener(
type: string,
listener: EventListenerOrEventListenerObject | null,
options?: boolean | AddEventListenerOptions
): void;
dispatchEvent(event: Event): boolean;
removeEventListener(
type: string,
listener: EventListenerOrEventListenerObject | null,
options?: EventListenerOptions | boolean
): void;
}
export interface ProgressEventInit extends EventInit { export interface ProgressEventInit extends EventInit {
lengthComputable?: boolean; lengthComputable?: boolean;
loaded?: number; loaded?: number;
total?: number; total?: number;
} }
export interface URLSearchParams extends DomIterable<string, string> { export class URLSearchParams {
constructor(
init?: string[][] | Record<string, string> | string | URLSearchParams
);
append(name: string, value: string): void; append(name: string, value: string): void;
delete(name: string): void; delete(name: string): void;
get(name: string): string | null; get(name: string): string | null;
@ -137,72 +79,229 @@ export interface URLSearchParams extends DomIterable<string, string> {
callbackfn: (value: string, key: string, parent: this) => void, callbackfn: (value: string, key: string, parent: this) => void,
thisArg?: any thisArg?: any
): void; ): void;
[Symbol.iterator](): IterableIterator<[string, string]>;
entries(): IterableIterator<[string, string]>;
keys(): IterableIterator<string>;
values(): IterableIterator<string>;
static toString(): string;
} }
export interface EventInit { export interface UIEventInit extends EventInit {
bubbles?: boolean; detail?: number;
cancelable?: boolean; // adjust Window -> Node
view?: Node | null;
}
export class UIEvent extends Event {
constructor(type: string, eventInitDict?: UIEventInit);
readonly detail: number;
// adjust Window -> Node
readonly view: Node | null;
}
export interface FocusEventInit extends UIEventInit {
relatedTarget?: EventTarget | null;
}
export class FocusEvent extends UIEvent {
constructor(type: string, eventInitDict?: FocusEventInit);
readonly relatedTarget: EventTarget | null;
}
export interface EventModifierInit extends UIEventInit {
altKey?: boolean;
ctrlKey?: boolean;
metaKey?: boolean;
modifierAltGraph?: boolean;
modifierCapsLock?: boolean;
modifierFn?: boolean;
modifierFnLock?: boolean;
modifierHyper?: boolean;
modifierNumLock?: boolean;
modifierScrollLock?: boolean;
modifierSuper?: boolean;
modifierSymbol?: boolean;
modifierSymbolLock?: boolean;
shiftKey?: boolean;
}
export interface MouseEventInit extends EventModifierInit {
button?: number;
buttons?: number;
clientX?: number;
clientY?: number;
movementX?: number;
movementY?: number;
relatedTarget?: EventTarget | null;
screenX?: number;
screenY?: number;
}
export class MouseEvent extends UIEvent {
constructor(type: string, eventInitDict?: MouseEventInit);
readonly altKey: boolean;
readonly button: number;
readonly buttons: number;
readonly clientX: number;
readonly clientY: number;
readonly ctrlKey: boolean;
readonly metaKey: boolean;
readonly movementX: number;
readonly movementY: number;
readonly offsetX: number;
readonly offsetY: number;
readonly pageX: number;
readonly pageY: number;
readonly relatedTarget: EventTarget | null;
readonly screenX: number;
readonly screenY: number;
readonly shiftKey: boolean;
readonly x: number;
readonly y: number;
getModifierState(keyArg: string): boolean;
}
interface GetRootNodeOptions {
composed?: boolean; composed?: boolean;
} }
export interface CustomEventInit extends EventInit { export class Node extends EventTarget {
detail?: any; readonly baseURI: string;
readonly childNodes: NodeListOf<ChildNode>;
readonly firstChild: ChildNode | null;
readonly isConnected: boolean;
readonly lastChild: ChildNode | null;
readonly nextSibling: ChildNode | null;
readonly nodeName: string;
readonly nodeType: number;
nodeValue: string | null;
// adjusted: Document -> Node
readonly ownerDocument: Node | null;
// adjusted: HTMLElement -> Node
readonly parentElement: Node | null;
readonly parentNode: (Node & ParentNode) | null;
readonly previousSibling: ChildNode | null;
textContent: string | null;
appendChild<T extends Node>(newChild: T): T;
cloneNode(deep?: boolean): Node;
compareDocumentPosition(other: Node): number;
contains(other: Node | null): boolean;
getRootNode(options?: GetRootNodeOptions): Node;
hasChildNodes(): boolean;
insertBefore<T extends Node>(newChild: T, refChild: Node | null): T;
isDefaultNamespace(namespace: string | null): boolean;
isEqualNode(otherNode: Node | null): boolean;
isSameNode(otherNode: Node | null): boolean;
lookupNamespaceURI(prefix: string | null): string | null;
lookupPrefix(namespace: string | null): string | null;
normalize(): void;
removeChild<T extends Node>(oldChild: T): T;
replaceChild<T extends Node>(newChild: Node, oldChild: T): T;
readonly ATTRIBUTE_NODE: number;
readonly CDATA_SECTION_NODE: number;
readonly COMMENT_NODE: number;
readonly DOCUMENT_FRAGMENT_NODE: number;
readonly DOCUMENT_NODE: number;
readonly DOCUMENT_POSITION_CONTAINED_BY: number;
readonly DOCUMENT_POSITION_CONTAINS: number;
readonly DOCUMENT_POSITION_DISCONNECTED: number;
readonly DOCUMENT_POSITION_FOLLOWING: number;
readonly DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: number;
readonly DOCUMENT_POSITION_PRECEDING: number;
readonly DOCUMENT_TYPE_NODE: number;
readonly ELEMENT_NODE: number;
readonly ENTITY_NODE: number;
readonly ENTITY_REFERENCE_NODE: number;
readonly NOTATION_NODE: number;
readonly PROCESSING_INSTRUCTION_NODE: number;
readonly TEXT_NODE: number;
static readonly ATTRIBUTE_NODE: number;
static readonly CDATA_SECTION_NODE: number;
static readonly COMMENT_NODE: number;
static readonly DOCUMENT_FRAGMENT_NODE: number;
static readonly DOCUMENT_NODE: number;
static readonly DOCUMENT_POSITION_CONTAINED_BY: number;
static readonly DOCUMENT_POSITION_CONTAINS: number;
static readonly DOCUMENT_POSITION_DISCONNECTED: number;
static readonly DOCUMENT_POSITION_FOLLOWING: number;
static readonly DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: number;
static readonly DOCUMENT_POSITION_PRECEDING: number;
static readonly DOCUMENT_TYPE_NODE: number;
static readonly ELEMENT_NODE: number;
static readonly ENTITY_NODE: number;
static readonly ENTITY_REFERENCE_NODE: number;
static readonly NOTATION_NODE: number;
static readonly PROCESSING_INSTRUCTION_NODE: number;
static readonly TEXT_NODE: number;
} }
export enum EventPhase { interface Slotable {
NONE = 0, // adjusted: HTMLSlotElement -> Node
CAPTURING_PHASE = 1, readonly assignedSlot: Node | null;
AT_TARGET = 2,
BUBBLING_PHASE = 3,
} }
export interface EventPath { interface ChildNode extends Node {
item: EventTarget; after(...nodes: Array<Node | string>): void;
itemInShadowTree: boolean; before(...nodes: Array<Node | string>): void;
relatedTarget: EventTarget | null; remove(): void;
rootOfClosedTree: boolean; replaceWith(...nodes: Array<Node | string>): void;
slotInClosedTree: boolean;
target: EventTarget | null;
touchTargetList: EventTarget[];
} }
export interface Event { interface ParentNode {
readonly type: string; readonly childElementCount: number;
target: EventTarget | null; // not currently supported
currentTarget: EventTarget | null; // readonly children: HTMLCollection;
composedPath(): EventPath[]; // adjusted: Element -> Node
readonly firstElementChild: Node | null;
eventPhase: number; // adjusted: Element -> Node
readonly lastElementChild: Node | null;
stopPropagation(): void; append(...nodes: Array<Node | string>): void;
stopImmediatePropagation(): void; prepend(...nodes: Array<Node | string>): void;
// not currently supported
readonly bubbles: boolean; // querySelector<K extends keyof HTMLElementTagNameMap>(
readonly cancelable: boolean; // selectors: K,
preventDefault(): void; // ): HTMLElementTagNameMap[K] | null;
readonly defaultPrevented: boolean; // querySelector<K extends keyof SVGElementTagNameMap>(
readonly composed: boolean; // selectors: K,
// ): SVGElementTagNameMap[K] | null;
isTrusted: boolean; // querySelector<E extends Element = Element>(selectors: string): E | null;
readonly timeStamp: Date; // querySelectorAll<K extends keyof HTMLElementTagNameMap>(
// selectors: K,
dispatched: boolean; // ): NodeListOf<HTMLElementTagNameMap[K]>;
readonly initialized: boolean; // querySelectorAll<K extends keyof SVGElementTagNameMap>(
inPassiveListener: boolean; // selectors: K,
cancelBubble: boolean; // ): NodeListOf<SVGElementTagNameMap[K]>;
cancelBubbleImmediately: boolean; // querySelectorAll<E extends Element = Element>(
path: EventPath[]; // selectors: string,
relatedTarget: EventTarget | null; // ): NodeListOf<E>;
} }
export interface CustomEvent extends Event { interface NodeList {
readonly detail: any; readonly length: number;
initCustomEvent( item(index: number): Node | null;
type: string, forEach(
bubbles?: boolean, callbackfn: (value: Node, key: number, parent: NodeList) => void,
cancelable?: boolean, thisArg?: any
detail?: any | null
): void; ): void;
[index: number]: Node;
[Symbol.iterator](): IterableIterator<Node>;
entries(): IterableIterator<[number, Node]>;
keys(): IterableIterator<number>;
values(): IterableIterator<Node>;
}
interface NodeListOf<TNode extends Node> extends NodeList {
length: number;
item(index: number): TNode;
forEach(
callbackfn: (value: TNode, key: number, parent: NodeListOf<TNode>) => void,
thisArg?: any
): void;
[index: number]: TNode;
[Symbol.iterator](): IterableIterator<TNode>;
entries(): IterableIterator<[number, TNode]>;
keys(): IterableIterator<number>;
values(): IterableIterator<TNode>;
} }
export interface DomFile extends Blob { export interface DomFile extends Blob {
@ -225,15 +324,6 @@ interface ProgressEvent extends Event {
readonly total: number; readonly total: number;
} }
export interface EventListenerOptions {
capture?: boolean;
}
export interface AddEventListenerOptions extends EventListenerOptions {
once?: boolean;
passive?: boolean;
}
export interface AbortSignal extends EventTarget { export interface AbortSignal extends EventTarget {
readonly aborted: boolean; readonly aborted: boolean;
onabort: ((this: AbortSignal, ev: ProgressEvent) => any) | null; onabort: ((this: AbortSignal, ev: ProgressEvent) => any) | null;
@ -259,18 +349,17 @@ export interface AbortSignal extends EventTarget {
): void; ): void;
} }
export interface FormData extends DomIterable<string, FormDataEntryValue> { export class FormData {
append(name: string, value: string | Blob, fileName?: string): void; append(name: string, value: string | Blob, fileName?: string): void;
delete(name: string): void; delete(name: string): void;
get(name: string): FormDataEntryValue | null; get(name: string): FormDataEntryValue | null;
getAll(name: string): FormDataEntryValue[]; getAll(name: string): FormDataEntryValue[];
has(name: string): boolean; has(name: string): boolean;
set(name: string, value: string | Blob, fileName?: string): void; set(name: string, value: string | Blob, fileName?: string): void;
} [Symbol.iterator](): IterableIterator<[string, FormDataEntryValue]>;
entries(): IterableIterator<[string, FormDataEntryValue]>;
export interface FormDataConstructor { keys(): IterableIterator<string>;
new (): FormData; values(): IterableIterator<FormDataEntryValue>;
prototype: FormData;
} }
export interface Blob { export interface Blob {
@ -493,6 +582,7 @@ export interface WritableStreamDefaultController {
error(error?: any): void; error(error?: any): void;
} }
*/ */
export interface QueuingStrategy<T = any> { export interface QueuingStrategy<T = any> {
highWaterMark?: number; highWaterMark?: number;
size?: QueuingStrategySizeCallback<T>; size?: QueuingStrategySizeCallback<T>;
@ -502,25 +592,21 @@ export interface QueuingStrategySizeCallback<T = any> {
(chunk: T): number; (chunk: T): number;
} }
export interface Headers extends DomIterable<string, string> { export class Headers {
constructor(init?: HeadersInit);
append(name: string, value: string): void; append(name: string, value: string): void;
delete(name: string): void; delete(name: string): void;
entries(): IterableIterator<[string, string]>;
get(name: string): string | null; get(name: string): string | null;
has(name: string): boolean; has(name: string): boolean;
keys(): IterableIterator<string>;
set(name: string, value: string): void; set(name: string, value: string): void;
values(): IterableIterator<string>;
forEach( forEach(
callbackfn: (value: string, key: string, parent: this) => void, callbackfn: (value: string, key: string, parent: this) => void,
thisArg?: any thisArg?: any
): void; ): void;
[Symbol.iterator](): IterableIterator<[string, string]>; [Symbol.iterator](): IterableIterator<[string, string]>;
} entries(): IterableIterator<[string, string]>;
keys(): IterableIterator<string>;
export interface HeadersConstructor { values(): IterableIterator<string>;
new (init?: HeadersInit): Headers;
prototype: Headers;
} }
type RequestCache = type RequestCache =
@ -582,11 +668,6 @@ export interface ResponseInit {
statusText?: string; statusText?: string;
} }
export interface RequestConstructor {
new (input: RequestInfo, init?: RequestInit): Request;
prototype: Request;
}
export interface Request extends Body { export interface Request extends Body {
readonly cache?: RequestCache; readonly cache?: RequestCache;
readonly credentials?: RequestCredentials; readonly credentials?: RequestCredentials;
@ -606,6 +687,11 @@ export interface Request extends Body {
clone(): Request; clone(): Request;
} }
export interface RequestConstructor {
new (input: RequestInfo, init?: RequestInit): Request;
prototype: Request;
}
export interface Response extends Body { export interface Response extends Body {
readonly headers: Headers; readonly headers: Headers;
readonly ok: boolean; readonly ok: boolean;
@ -618,14 +704,22 @@ export interface Response extends Body {
clone(): Response; clone(): Response;
} }
export interface DOMStringList { export interface ResponseConstructor {
prototype: Response;
new (body?: BodyInit | null, init?: ResponseInit): Response;
error(): Response;
redirect(url: string, status?: number): Response;
}
export class DOMStringList {
readonly length: number; readonly length: number;
contains(string: string): boolean; contains(string: string): boolean;
item(index: number): string | null; item(index: number): string | null;
[index: number]: string; [index: number]: string;
[Symbol.iterator](): IterableIterator<string>;
} }
export interface Location { export class Location {
readonly ancestorOrigins: DOMStringList; readonly ancestorOrigins: DOMStringList;
hash: string; hash: string;
host: string; host: string;
@ -642,7 +736,8 @@ export interface Location {
replace(url: string): void; replace(url: string): void;
} }
export interface URL { export class URL {
constructor(url: string, base?: string | URL);
hash: string; hash: string;
host: string; host: string;
hostname: string; hostname: string;
@ -657,54 +752,6 @@ export interface URL {
readonly searchParams: URLSearchParams; readonly searchParams: URLSearchParams;
username: string; username: string;
toJSON(): string; toJSON(): string;
} static createObjectURL(object: any): string;
static revokeObjectURL(url: string): void;
export interface URLSearchParams {
/**
* Appends a specified key/value pair as a new search parameter.
*/
append(name: string, value: string): void;
/**
* Deletes the given search parameter, and its associated value, from the list of all search parameters.
*/
delete(name: string): void;
/**
* Returns the first value associated to the given search parameter.
*/
get(name: string): string | null;
/**
* Returns all the values association with a given search parameter.
*/
getAll(name: string): string[];
/**
* Returns a Boolean indicating if such a search parameter exists.
*/
has(name: string): boolean;
/**
* Sets the value associated to a given search parameter to the given value. If there were several values, delete the others.
*/
set(name: string, value: string): void;
sort(): void;
/**
* Returns a string containing a query string suitable for use in a URL. Does not include the question mark.
*/
toString(): string;
forEach(
callbackfn: (value: string, key: string, parent: URLSearchParams) => void,
thisArg?: any
): void;
[Symbol.iterator](): IterableIterator<[string, string]>;
/**
* Returns an array of key, value pairs for every entry in the search params.
*/
entries(): IterableIterator<[string, string]>;
/**
* Returns a list of keys in the search params.
*/
keys(): IterableIterator<string>;
/**
* Returns a list of values in the search params.
*/
values(): IterableIterator<string>;
} }

View file

@ -1,6 +1,6 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
// Utility functions for DOM nodes
import * as domTypes from "./dom_types.ts"; import * as domTypes from "./dom_types.d.ts";
export function getDOMStringList(arr: string[]): domTypes.DOMStringList { export function getDOMStringList(arr: string[]): domTypes.DOMStringList {
Object.defineProperties(arr, { Object.defineProperties(arr, {
@ -16,87 +16,5 @@ export function getDOMStringList(arr: string[]): domTypes.DOMStringList {
}, },
}, },
}); });
return (arr as unknown) as domTypes.DOMStringList; return arr as string[] & domTypes.DOMStringList;
}
export function isNode(nodeImpl: domTypes.EventTarget | null): boolean {
return Boolean(nodeImpl && "nodeType" in nodeImpl);
}
export function isShadowRoot(nodeImpl: domTypes.EventTarget | null): boolean {
return Boolean(
nodeImpl &&
nodeImpl[domTypes.eventTargetNodeType] ===
domTypes.NodeType.DOCUMENT_FRAGMENT_NODE &&
nodeImpl[domTypes.eventTargetHost] != null
);
}
export function isSlotable(nodeImpl: domTypes.EventTarget | null): boolean {
return Boolean(
nodeImpl &&
(nodeImpl[domTypes.eventTargetNodeType] ===
domTypes.NodeType.ELEMENT_NODE ||
nodeImpl[domTypes.eventTargetNodeType] === domTypes.NodeType.TEXT_NODE)
);
}
// https://dom.spec.whatwg.org/#node-trees
// const domSymbolTree = Symbol("DOM Symbol Tree");
// https://dom.spec.whatwg.org/#concept-shadow-including-inclusive-ancestor
export function isShadowInclusiveAncestor(
ancestor: domTypes.EventTarget | null,
node: domTypes.EventTarget | null
): boolean {
while (isNode(node)) {
if (node === ancestor) {
return true;
}
if (isShadowRoot(node)) {
node = node && node[domTypes.eventTargetHost];
} else {
node = null; // domSymbolTree.parent(node);
}
}
return false;
}
export function getRoot(
node: domTypes.EventTarget | null
): domTypes.EventTarget | null {
const root = node;
// for (const ancestor of domSymbolTree.ancestorsIterator(node)) {
// root = ancestor;
// }
return root;
}
// https://dom.spec.whatwg.org/#retarget
export function retarget(
a: domTypes.EventTarget | null,
b: domTypes.EventTarget
): domTypes.EventTarget | null {
while (true) {
if (!isNode(a)) {
return a;
}
const aRoot = getRoot(a);
if (aRoot) {
if (
!isShadowRoot(aRoot) ||
(isNode(b) && isShadowInclusiveAncestor(aRoot, b))
) {
return a;
}
a = aRoot[domTypes.eventTargetHost];
}
}
} }

View file

@ -1,45 +1,153 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import * as domTypes from "./dom_types.ts";
import { getPrivateValue, requiredArguments } from "./util.ts";
// WeakMaps are recommended for private attributes (see MDN link below) import * as domTypes from "./dom_types.d.ts";
// https://developer.mozilla.org/en-US/docs/Archive/Add-ons/Add-on_SDK/Guides/Contributor_s_Guide/Private_Properties#Using_WeakMaps import { defineEnumerableProps, requiredArguments } from "./util.ts";
export const eventAttributes = new WeakMap(); import { assert } from "../util.ts";
function isTrusted(this: Event): boolean { /** Stores a non-accessible view of the event path which is used internally in
return getPrivateValue(this, eventAttributes, "isTrusted"); * the logic for determining the path of an event. */
export interface EventPath {
item: EventTarget;
itemInShadowTree: boolean;
relatedTarget: EventTarget | null;
rootOfClosedTree: boolean;
slotInClosedTree: boolean;
target: EventTarget | null;
touchTargetList: EventTarget[];
} }
export class Event implements domTypes.Event { interface EventAttributes {
type: string;
bubbles: boolean;
cancelable: boolean;
composed: boolean;
currentTarget: EventTarget | null;
eventPhase: number;
target: EventTarget | null;
timeStamp: number;
}
interface EventData {
dispatched: boolean;
inPassiveListener: boolean;
isTrusted: boolean;
path: EventPath[];
stopImmediatePropagation: boolean;
}
const eventData = new WeakMap<Event, EventData>();
// accessors for non runtime visible data
export function getDispatched(event: Event): boolean {
return Boolean(eventData.get(event)?.dispatched);
}
export function getPath(event: Event): EventPath[] {
return eventData.get(event)?.path ?? [];
}
export function getStopImmediatePropagation(event: Event): boolean {
return Boolean(eventData.get(event)?.stopImmediatePropagation);
}
export function setCurrentTarget(
event: Event,
value: EventTarget | null
): void {
(event as EventImpl).currentTarget = value;
}
export function setDispatched(event: Event, value: boolean): void {
const data = eventData.get(event as Event);
if (data) {
data.dispatched = value;
}
}
export function setEventPhase(event: Event, value: number): void {
(event as EventImpl).eventPhase = value;
}
export function setInPassiveListener(event: Event, value: boolean): void {
const data = eventData.get(event as Event);
if (data) {
data.inPassiveListener = value;
}
}
export function setPath(event: Event, value: EventPath[]): void {
const data = eventData.get(event as Event);
if (data) {
data.path = value;
}
}
export function setRelatedTarget<T extends Event>(
event: T,
value: EventTarget | null
): void {
if ("relatedTarget" in event) {
(event as T & {
relatedTarget: EventTarget | null;
}).relatedTarget = value;
}
}
export function setTarget(event: Event, value: EventTarget | null): void {
(event as EventImpl).target = value;
}
export function setStopImmediatePropagation(
event: Event,
value: boolean
): void {
const data = eventData.get(event as Event);
if (data) {
data.stopImmediatePropagation = value;
}
}
// Type guards that widen the event type
export function hasRelatedTarget(
event: Event
): event is domTypes.FocusEvent | domTypes.MouseEvent {
return "relatedTarget" in event;
}
function isTrusted(this: Event): boolean {
return eventData.get(this)!.isTrusted;
}
export class EventImpl implements Event {
// The default value is `false`. // The default value is `false`.
// Use `defineProperty` to define on each instance, NOT on the prototype. // Use `defineProperty` to define on each instance, NOT on the prototype.
isTrusted!: boolean; isTrusted!: boolean;
// Each event has the following associated flags
private _canceledFlag = false;
private _dispatchedFlag = false;
private _initializedFlag = false;
private _inPassiveListenerFlag = false;
private _stopImmediatePropagationFlag = false;
private _stopPropagationFlag = false;
// Property for objects on which listeners will be invoked #canceledFlag = false;
private _path: domTypes.EventPath[] = []; #stopPropagationFlag = false;
#attributes: EventAttributes;
constructor(type: string, eventInitDict: domTypes.EventInit = {}) { constructor(type: string, eventInitDict: EventInit = {}) {
requiredArguments("Event", arguments.length, 1); requiredArguments("Event", arguments.length, 1);
type = String(type); type = String(type);
this._initializedFlag = true; this.#attributes = {
eventAttributes.set(this, {
type, type,
bubbles: eventInitDict.bubbles || false, bubbles: eventInitDict.bubbles ?? false,
cancelable: eventInitDict.cancelable || false, cancelable: eventInitDict.cancelable ?? false,
composed: eventInitDict.composed || false, composed: eventInitDict.composed ?? false,
currentTarget: null, currentTarget: null,
eventPhase: domTypes.EventPhase.NONE, eventPhase: Event.NONE,
isTrusted: false,
relatedTarget: null,
target: null, target: null,
timeStamp: Date.now(), timeStamp: Date.now(),
};
eventData.set(this, {
dispatched: false,
inPassiveListener: false,
isTrusted: false,
path: [],
stopImmediatePropagation: false,
}); });
Reflect.defineProperty(this, "isTrusted", { Reflect.defineProperty(this, "isTrusted", {
enumerable: true, enumerable: true,
@ -48,151 +156,100 @@ export class Event implements domTypes.Event {
} }
get bubbles(): boolean { get bubbles(): boolean {
return getPrivateValue(this, eventAttributes, "bubbles"); return this.#attributes.bubbles;
} }
get cancelBubble(): boolean { get cancelBubble(): boolean {
return this._stopPropagationFlag; return this.#stopPropagationFlag;
} }
set cancelBubble(value: boolean) { set cancelBubble(value: boolean) {
this._stopPropagationFlag = value; this.#stopPropagationFlag = value;
}
get cancelBubbleImmediately(): boolean {
return this._stopImmediatePropagationFlag;
}
set cancelBubbleImmediately(value: boolean) {
this._stopImmediatePropagationFlag = value;
} }
get cancelable(): boolean { get cancelable(): boolean {
return getPrivateValue(this, eventAttributes, "cancelable"); return this.#attributes.cancelable;
} }
get composed(): boolean { get composed(): boolean {
return getPrivateValue(this, eventAttributes, "composed"); return this.#attributes.composed;
} }
get currentTarget(): domTypes.EventTarget { get currentTarget(): EventTarget | null {
return getPrivateValue(this, eventAttributes, "currentTarget"); return this.#attributes.currentTarget;
} }
set currentTarget(value: domTypes.EventTarget) { set currentTarget(value: EventTarget | null) {
eventAttributes.set(this, { this.#attributes = {
type: this.type, type: this.type,
bubbles: this.bubbles, bubbles: this.bubbles,
cancelable: this.cancelable, cancelable: this.cancelable,
composed: this.composed, composed: this.composed,
currentTarget: value, currentTarget: value,
eventPhase: this.eventPhase, eventPhase: this.eventPhase,
isTrusted: this.isTrusted,
relatedTarget: this.relatedTarget,
target: this.target, target: this.target,
timeStamp: this.timeStamp, timeStamp: this.timeStamp,
}); };
} }
get defaultPrevented(): boolean { get defaultPrevented(): boolean {
return this._canceledFlag; return this.#canceledFlag;
}
get dispatched(): boolean {
return this._dispatchedFlag;
}
set dispatched(value: boolean) {
this._dispatchedFlag = value;
} }
get eventPhase(): number { get eventPhase(): number {
return getPrivateValue(this, eventAttributes, "eventPhase"); return this.#attributes.eventPhase;
} }
set eventPhase(value: number) { set eventPhase(value: number) {
eventAttributes.set(this, { this.#attributes = {
type: this.type, type: this.type,
bubbles: this.bubbles, bubbles: this.bubbles,
cancelable: this.cancelable, cancelable: this.cancelable,
composed: this.composed, composed: this.composed,
currentTarget: this.currentTarget, currentTarget: this.currentTarget,
eventPhase: value, eventPhase: value,
isTrusted: this.isTrusted,
relatedTarget: this.relatedTarget,
target: this.target, target: this.target,
timeStamp: this.timeStamp, timeStamp: this.timeStamp,
}); };
} }
get initialized(): boolean { get initialized(): boolean {
return this._initializedFlag; return true;
} }
set inPassiveListener(value: boolean) { get target(): EventTarget | null {
this._inPassiveListenerFlag = value; return this.#attributes.target;
} }
get path(): domTypes.EventPath[] { set target(value: EventTarget | null) {
return this._path; this.#attributes = {
}
set path(value: domTypes.EventPath[]) {
this._path = value;
}
get relatedTarget(): domTypes.EventTarget {
return getPrivateValue(this, eventAttributes, "relatedTarget");
}
set relatedTarget(value: domTypes.EventTarget) {
eventAttributes.set(this, {
type: this.type, type: this.type,
bubbles: this.bubbles, bubbles: this.bubbles,
cancelable: this.cancelable, cancelable: this.cancelable,
composed: this.composed, composed: this.composed,
currentTarget: this.currentTarget, currentTarget: this.currentTarget,
eventPhase: this.eventPhase, eventPhase: this.eventPhase,
isTrusted: this.isTrusted,
relatedTarget: value,
target: this.target,
timeStamp: this.timeStamp,
});
}
get target(): domTypes.EventTarget {
return getPrivateValue(this, eventAttributes, "target");
}
set target(value: domTypes.EventTarget) {
eventAttributes.set(this, {
type: this.type,
bubbles: this.bubbles,
cancelable: this.cancelable,
composed: this.composed,
currentTarget: this.currentTarget,
eventPhase: this.eventPhase,
isTrusted: this.isTrusted,
relatedTarget: this.relatedTarget,
target: value, target: value,
timeStamp: this.timeStamp, timeStamp: this.timeStamp,
}); };
} }
get timeStamp(): Date { get timeStamp(): number {
return getPrivateValue(this, eventAttributes, "timeStamp"); return this.#attributes.timeStamp;
} }
get type(): string { get type(): string {
return getPrivateValue(this, eventAttributes, "type"); return this.#attributes.type;
} }
composedPath(): domTypes.EventPath[] { composedPath(): EventTarget[] {
if (this._path.length === 0) { const path = eventData.get(this)!.path;
if (path.length === 0) {
return []; return [];
} }
const composedPath: domTypes.EventPath[] = [ assert(this.currentTarget);
const composedPath: EventPath[] = [
{ {
item: this.currentTarget, item: this.currentTarget,
itemInShadowTree: false, itemInShadowTree: false,
@ -207,8 +264,8 @@ export class Event implements domTypes.Event {
let currentTargetIndex = 0; let currentTargetIndex = 0;
let currentTargetHiddenSubtreeLevel = 0; let currentTargetHiddenSubtreeLevel = 0;
for (let index = this._path.length - 1; index >= 0; index--) { for (let index = path.length - 1; index >= 0; index--) {
const { item, rootOfClosedTree, slotInClosedTree } = this._path[index]; const { item, rootOfClosedTree, slotInClosedTree } = path[index];
if (rootOfClosedTree) { if (rootOfClosedTree) {
currentTargetHiddenSubtreeLevel++; currentTargetHiddenSubtreeLevel++;
@ -228,7 +285,7 @@ export class Event implements domTypes.Event {
let maxHiddenLevel = currentTargetHiddenSubtreeLevel; let maxHiddenLevel = currentTargetHiddenSubtreeLevel;
for (let i = currentTargetIndex - 1; i >= 0; i--) { for (let i = currentTargetIndex - 1; i >= 0; i--) {
const { item, rootOfClosedTree, slotInClosedTree } = this._path[i]; const { item, rootOfClosedTree, slotInClosedTree } = path[i];
if (rootOfClosedTree) { if (rootOfClosedTree) {
currentHiddenLevel++; currentHiddenLevel++;
@ -258,12 +315,8 @@ export class Event implements domTypes.Event {
currentHiddenLevel = currentTargetHiddenSubtreeLevel; currentHiddenLevel = currentTargetHiddenSubtreeLevel;
maxHiddenLevel = currentTargetHiddenSubtreeLevel; maxHiddenLevel = currentTargetHiddenSubtreeLevel;
for ( for (let index = currentTargetIndex + 1; index < path.length; index++) {
let index = currentTargetIndex + 1; const { item, rootOfClosedTree, slotInClosedTree } = path[index];
index < this._path.length;
index++
) {
const { item, rootOfClosedTree, slotInClosedTree } = this._path[index];
if (slotInClosedTree) { if (slotInClosedTree) {
currentHiddenLevel++; currentHiddenLevel++;
@ -289,35 +342,65 @@ export class Event implements domTypes.Event {
} }
} }
} }
return composedPath.map((p) => p.item);
return composedPath;
} }
preventDefault(): void { preventDefault(): void {
if (this.cancelable && !this._inPassiveListenerFlag) { if (this.cancelable && !eventData.get(this)!.inPassiveListener) {
this._canceledFlag = true; this.#canceledFlag = true;
} }
} }
stopPropagation(): void { stopPropagation(): void {
this._stopPropagationFlag = true; this.#stopPropagationFlag = true;
} }
stopImmediatePropagation(): void { stopImmediatePropagation(): void {
this._stopPropagationFlag = true; this.#stopPropagationFlag = true;
this._stopImmediatePropagationFlag = true; eventData.get(this)!.stopImmediatePropagation = true;
}
get NONE(): number {
return Event.NONE;
}
get CAPTURING_PHASE(): number {
return Event.CAPTURING_PHASE;
}
get AT_TARGET(): number {
return Event.AT_TARGET;
}
get BUBBLING_PHASE(): number {
return Event.BUBBLING_PHASE;
}
static get NONE(): number {
return 0;
}
static get CAPTURING_PHASE(): number {
return 1;
}
static get AT_TARGET(): number {
return 2;
}
static get BUBBLING_PHASE(): number {
return 3;
} }
} }
Reflect.defineProperty(Event.prototype, "bubbles", { enumerable: true }); defineEnumerableProps(EventImpl, [
Reflect.defineProperty(Event.prototype, "cancelable", { enumerable: true }); "bubbles",
Reflect.defineProperty(Event.prototype, "composed", { enumerable: true }); "cancelable",
Reflect.defineProperty(Event.prototype, "currentTarget", { enumerable: true }); "composed",
Reflect.defineProperty(Event.prototype, "defaultPrevented", { "currentTarget",
enumerable: true, "defaultPrevented",
}); "eventPhase",
Reflect.defineProperty(Event.prototype, "dispatched", { enumerable: true }); "target",
Reflect.defineProperty(Event.prototype, "eventPhase", { enumerable: true }); "timeStamp",
Reflect.defineProperty(Event.prototype, "target", { enumerable: true }); "type",
Reflect.defineProperty(Event.prototype, "timeStamp", { enumerable: true }); ]);
Reflect.defineProperty(Event.prototype, "type", { enumerable: true });

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { assert, createResolvable, notImplemented } from "../util.ts"; import { assert, createResolvable, notImplemented } from "../util.ts";
import { isTypedArray } from "./util.ts"; import { isTypedArray } from "./util.ts";
import * as domTypes from "./dom_types.ts"; import * as domTypes from "./dom_types.d.ts";
import { TextDecoder, TextEncoder } from "./text_encoding.ts"; import { TextDecoder, TextEncoder } from "./text_encoding.ts";
import { DenoBlob, bytesSymbol as blobBytesSymbol } from "./blob.ts"; import { DenoBlob, bytesSymbol as blobBytesSymbol } from "./blob.ts";
import { Headers } from "./headers.ts"; import { Headers } from "./headers.ts";

View file

@ -1,5 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import * as domTypes from "./dom_types.ts"; import * as domTypes from "./dom_types.d.ts";
import * as blob from "./blob.ts"; import * as blob from "./blob.ts";
import * as domFile from "./dom_file.ts"; import * as domFile from "./dom_file.ts";
import { DomIterableMixin } from "./dom_iterable.ts"; import { DomIterableMixin } from "./dom_iterable.ts";

View file

@ -1,5 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import * as domTypes from "./dom_types.ts"; import * as domTypes from "./dom_types.d.ts";
import { DomIterableMixin } from "./dom_iterable.ts"; import { DomIterableMixin } from "./dom_iterable.ts";
import { requiredArguments } from "./util.ts"; import { requiredArguments } from "./util.ts";
import { customInspect } from "./console.ts"; import { customInspect } from "./console.ts";

View file

@ -1,7 +1,7 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { URL } from "./url.ts"; import { URL } from "./url.ts";
import { notImplemented } from "../util.ts"; import { notImplemented } from "../util.ts";
import { DOMStringList, Location } from "./dom_types.ts"; import { DOMStringList, Location } from "./dom_types.d.ts";
import { getDOMStringList } from "./dom_util.ts"; import { getDOMStringList } from "./dom_util.ts";
export class LocationImpl implements Location { export class LocationImpl implements Location {

View file

@ -1,7 +1,7 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import * as headers from "./headers.ts"; import * as headers from "./headers.ts";
import * as body from "./body.ts"; import * as body from "./body.ts";
import * as domTypes from "./dom_types.ts"; import * as domTypes from "./dom_types.d.ts";
import * as streams from "./streams/mod.ts"; import * as streams from "./streams/mod.ts";
const { Headers } = headers; const { Headers } = headers;

View file

@ -18,7 +18,7 @@
// import { ReadableStreamDefaultReader } from "./readable-stream-default-reader.ts"; // import { ReadableStreamDefaultReader } from "./readable-stream-default-reader.ts";
// import { WritableStreamDefaultWriter } from "./writable-stream-default-writer.ts"; // import { WritableStreamDefaultWriter } from "./writable-stream-default-writer.ts";
// import { PipeOptions } from "../dom_types.ts"; // import { PipeOptions } from "../dom_types.d.ts";
// import { Err } from "../errors.ts"; // import { Err } from "../errors.ts";
// // add a wrapper to handle falsy rejections // // add a wrapper to handle falsy rejections

View file

@ -9,7 +9,7 @@ import * as q from "./queue-mixin.ts";
import * as shared from "./shared-internals.ts"; import * as shared from "./shared-internals.ts";
import { ReadableStreamBYOBRequest } from "./readable-stream-byob-request.ts"; import { ReadableStreamBYOBRequest } from "./readable-stream-byob-request.ts";
import { Queue } from "./queue.ts"; import { Queue } from "./queue.ts";
import { UnderlyingByteSource } from "../dom_types.ts"; import { UnderlyingByteSource } from "../dom_types.d.ts";
export class ReadableByteStreamController export class ReadableByteStreamController
implements rs.SDReadableByteStreamController { implements rs.SDReadableByteStreamController {

View file

@ -11,7 +11,7 @@ import {
QueuingStrategySizeCallback, QueuingStrategySizeCallback,
UnderlyingSource, UnderlyingSource,
UnderlyingByteSource, UnderlyingByteSource,
} from "../dom_types.ts"; } from "../dom_types.d.ts";
// ReadableStreamDefaultController // ReadableStreamDefaultController
export const controlledReadableStream_ = Symbol("controlledReadableStream_"); export const controlledReadableStream_ = Symbol("controlledReadableStream_");

View file

@ -8,7 +8,10 @@ import * as rs from "./readable-internals.ts";
import * as shared from "./shared-internals.ts"; import * as shared from "./shared-internals.ts";
import * as q from "./queue-mixin.ts"; import * as q from "./queue-mixin.ts";
import { Queue } from "./queue.ts"; import { Queue } from "./queue.ts";
import { QueuingStrategySizeCallback, UnderlyingSource } from "../dom_types.ts"; import {
QueuingStrategySizeCallback,
UnderlyingSource,
} from "../dom_types.d.ts";
export class ReadableStreamDefaultController<OutputType> export class ReadableStreamDefaultController<OutputType>
implements rs.SDReadableStreamDefaultController<OutputType> { implements rs.SDReadableStreamDefaultController<OutputType> {

View file

@ -12,7 +12,7 @@ import {
QueuingStrategySizeCallback, QueuingStrategySizeCallback,
UnderlyingSource, UnderlyingSource,
UnderlyingByteSource, UnderlyingByteSource,
} from "../dom_types.ts"; } from "../dom_types.d.ts";
import { import {
ReadableStreamDefaultController, ReadableStreamDefaultController,

View file

@ -4,7 +4,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
// TODO don't disable this warning // TODO don't disable this warning
import { AbortSignal, QueuingStrategySizeCallback } from "../dom_types.ts"; import { AbortSignal, QueuingStrategySizeCallback } from "../dom_types.d.ts";
// common stream fields // common stream fields

View file

@ -4,7 +4,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
// TODO reenable this lint here // TODO reenable this lint here
import { QueuingStrategy } from "../dom_types.ts"; import { QueuingStrategy } from "../dom_types.d.ts";
export class ByteLengthQueuingStrategy export class ByteLengthQueuingStrategy
implements QueuingStrategy<ArrayBufferView> { implements QueuingStrategy<ArrayBufferView> {

View file

@ -19,7 +19,7 @@
// import { createReadableStream } from "./readable-stream.ts"; // import { createReadableStream } from "./readable-stream.ts";
// import { createWritableStream } from "./writable-stream.ts"; // import { createWritableStream } from "./writable-stream.ts";
// import { QueuingStrategy, QueuingStrategySizeCallback } from "../dom_types.ts"; // import { QueuingStrategy, QueuingStrategySizeCallback } from "../dom_types.d.ts";
// export const state_ = Symbol("transformState_"); // export const state_ = Symbol("transformState_");
// export const backpressure_ = Symbol("backpressure_"); // export const backpressure_ = Symbol("backpressure_");

View file

@ -17,7 +17,7 @@
// import * as ts from "./transform-internals.ts"; // import * as ts from "./transform-internals.ts";
// import * as shared from "./shared-internals.ts"; // import * as shared from "./shared-internals.ts";
// import { TransformStreamDefaultController } from "./transform-stream-default-controller.ts"; // import { TransformStreamDefaultController } from "./transform-stream-default-controller.ts";
// import { QueuingStrategy } from "../dom_types.ts"; // import { QueuingStrategy } from "../dom_types.d.ts";
// export class TransformStream<InputType, OutputType> { // export class TransformStream<InputType, OutputType> {
// [ts.backpressure_]: boolean | undefined; // Whether there was backpressure on [[readable]] the last time it was observed // [ts.backpressure_]: boolean | undefined; // Whether there was backpressure on [[readable]] the last time it was observed

View file

@ -15,7 +15,7 @@
// import * as shared from "./shared-internals.ts"; // import * as shared from "./shared-internals.ts";
// import * as q from "./queue-mixin.ts"; // import * as q from "./queue-mixin.ts";
// import { QueuingStrategy, QueuingStrategySizeCallback } from "../dom_types.ts"; // import { QueuingStrategy, QueuingStrategySizeCallback } from "../dom_types.d.ts";
// export const backpressure_ = Symbol("backpressure_"); // export const backpressure_ = Symbol("backpressure_");
// export const closeRequest_ = Symbol("closeRequest_"); // export const closeRequest_ = Symbol("closeRequest_");

View file

@ -16,7 +16,7 @@
// import * as shared from "./shared-internals.ts"; // import * as shared from "./shared-internals.ts";
// import * as q from "./queue-mixin.ts"; // import * as q from "./queue-mixin.ts";
// import { Queue } from "./queue.ts"; // import { Queue } from "./queue.ts";
// import { QueuingStrategySizeCallback } from "../dom_types.ts"; // import { QueuingStrategySizeCallback } from "../dom_types.d.ts";
// export class WritableStreamDefaultController<InputType> // export class WritableStreamDefaultController<InputType>
// implements ws.WritableStreamDefaultController<InputType> { // implements ws.WritableStreamDefaultController<InputType> {

View file

@ -16,7 +16,7 @@
// setUpWritableStreamDefaultControllerFromUnderlyingSink // setUpWritableStreamDefaultControllerFromUnderlyingSink
// } from "./writable-stream-default-controller.ts"; // } from "./writable-stream-default-controller.ts";
// import { WritableStreamDefaultWriter } from "./writable-stream-default-writer.ts"; // import { WritableStreamDefaultWriter } from "./writable-stream-default-writer.ts";
// import { QueuingStrategy, QueuingStrategySizeCallback } from "../dom_types.ts"; // import { QueuingStrategy, QueuingStrategySizeCallback } from "../dom_types.d.ts";
// export class WritableStream<InputType> { // export class WritableStream<InputType> {
// [shared.state_]: ws.WritableStreamState; // [shared.state_]: ws.WritableStreamState;

View file

@ -25,7 +25,7 @@
import * as base64 from "./base64.ts"; import * as base64 from "./base64.ts";
import { decodeUtf8 } from "./decode_utf8.ts"; import { decodeUtf8 } from "./decode_utf8.ts";
import * as domTypes from "./dom_types.ts"; import * as domTypes from "./dom_types.d.ts";
import { core } from "../core.ts"; import { core } from "../core.ts";
const CONTINUE = null; const CONTINUE = null;
@ -348,7 +348,7 @@ encodingIndexes.set("windows-1252", [
252, 252,
253, 253,
254, 254,
255 255,
]); ]);
for (const [key, index] of encodingIndexes) { for (const [key, index] of encodingIndexes) {
decoders.set( decoders.set(

View file

@ -1,6 +1,6 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { customInspect } from "./console.ts"; import { customInspect } from "./console.ts";
import * as domTypes from "./dom_types.ts"; import * as domTypes from "./dom_types.d.ts";
import { urls, URLSearchParams } from "./url_search_params.ts"; import { urls, URLSearchParams } from "./url_search_params.ts";
import { getRandomValues } from "../ops/get_random_values.ts"; import { getRandomValues } from "../ops/get_random_values.ts";

View file

@ -1,5 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import * as domTypes from "./dom_types.ts"; import * as domTypes from "./dom_types.d.ts";
import { URL, parts } from "./url.ts"; import { URL, parts } from "./url.ts";
import { isIterable, requiredArguments } from "./util.ts"; import { isIterable, requiredArguments } from "./util.ts";

View file

@ -11,6 +11,7 @@ export type TypedArray =
| Float32Array | Float32Array
| Float64Array; | Float64Array;
// @internal
export function isTypedArray(x: unknown): x is TypedArray { export function isTypedArray(x: unknown): x is TypedArray {
return ( return (
x instanceof Int8Array || x instanceof Int8Array ||
@ -54,19 +55,8 @@ export function immutableDefine(
}); });
} }
// Returns values from a WeakMap to emulate private properties in JavaScript // @internal
export function getPrivateValue< export function hasOwnProperty(obj: unknown, v: PropertyKey): boolean {
K extends object,
V extends object,
W extends keyof V
>(instance: K, weakMap: WeakMap<K, V>, key: W): V[W] {
if (weakMap.has(instance)) {
return weakMap.get(instance)![key];
}
throw new TypeError("Illegal invocation");
}
export function hasOwnProperty<T>(obj: T, v: PropertyKey): boolean {
if (obj == null) { if (obj == null) {
return false; return false;
} }
@ -87,3 +77,19 @@ export function isIterable<T, P extends keyof T, K extends T[P]>(
typeof ((o as unknown) as Iterable<[P, K]>)[Symbol.iterator] === "function" typeof ((o as unknown) as Iterable<[P, K]>)[Symbol.iterator] === "function"
); );
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
interface GenericConstructor<T = any> {
prototype: T;
}
/** A helper function which ensures accessors are enumerable, as they normally
* are not. */
export function defineEnumerableProps(
Ctor: GenericConstructor,
props: string[]
): void {
for (const prop of props) {
Reflect.defineProperty(Ctor.prototype, prop, { enumerable: true });
}
}

View file

@ -11,8 +11,8 @@ import { TextDecoder, TextEncoder } from "./text_encoding.ts";
/* /*
import { blobURLMap } from "./web/url.ts"; import { blobURLMap } from "./web/url.ts";
*/ */
import { Event } from "./event.ts"; import { EventImpl as Event } from "./event.ts";
import { EventTarget } from "./event_target.ts"; import { EventTargetImpl as EventTarget } from "./event_target.ts";
const encoder = new TextEncoder(); const encoder = new TextEncoder();
const decoder = new TextDecoder(); const decoder = new TextDecoder();