summaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
authorAdam Conrad <422184+acconrad@users.noreply.github.com>2019-01-23 12:20:53 +0000
committerRyan Dahl <ry@tinyclouds.org>2019-01-23 06:20:53 -0600
commite470f31d328884303e56f2f15a4121b8ffe097a6 (patch)
tree84e878d3c53db4f969c29357c7f5985b59c7d9f2 /js
parent77114fbda49382e397095d8214bd76996b0cfb57 (diff)
Web API: CustomEvent (#1505)
Diffstat (limited to 'js')
-rw-r--r--js/custom_event.ts60
-rw-r--r--js/custom_event_test.ts21
-rw-r--r--js/dom_types.ts17
-rw-r--r--js/event.ts25
-rw-r--r--js/event_target_test.ts4
-rw-r--r--js/globals.ts5
-rw-r--r--js/unit_tests.ts1
7 files changed, 131 insertions, 2 deletions
diff --git a/js/custom_event.ts b/js/custom_event.ts
new file mode 100644
index 000000000..dd1c33d58
--- /dev/null
+++ b/js/custom_event.ts
@@ -0,0 +1,60 @@
+// Copyright 2018 the Deno authors. All rights reserved. MIT license.
+import * as domTypes from "./dom_types";
+import * as event from "./event";
+import { getPrivateValue } from "./util";
+
+// WeakMaps are recommended for private attributes (see MDN link below)
+// tslint:disable-next-line:max-line-length
+// https://developer.mozilla.org/en-US/docs/Archive/Add-ons/Add-on_SDK/Guides/Contributor_s_Guide/Private_Properties#Using_WeakMaps
+export const customEventAttributes = new WeakMap();
+
+export class CustomEventInit extends event.EventInit
+ implements domTypes.CustomEventInit {
+ // tslint:disable-next-line:no-any
+ detail: any;
+
+ constructor({
+ bubbles = false,
+ cancelable = false,
+ composed = false,
+ detail = null
+ }: domTypes.CustomEventInit) {
+ super({ bubbles, cancelable, composed });
+ this.detail = detail;
+ }
+}
+
+export class CustomEvent extends event.Event implements domTypes.CustomEvent {
+ constructor(
+ type: string,
+ customEventInitDict: domTypes.CustomEventInit = {}
+ ) {
+ super(type, customEventInitDict);
+ const { detail = null } = customEventInitDict;
+ customEventAttributes.set(this, { detail });
+ }
+
+ // tslint:disable-next-line:no-any
+ get detail(): any {
+ return getPrivateValue(this, customEventAttributes, "detail");
+ }
+
+ initCustomEvent(
+ type: string,
+ bubbles?: boolean,
+ cancelable?: boolean,
+ // tslint:disable-next-line:no-any
+ detail?: any
+ ) {
+ if (this.dispatched) {
+ return;
+ }
+
+ customEventAttributes.set(this, { detail });
+ }
+}
+
+/** Built-in objects providing `get` methods for our
+ * interceptable JavaScript operations.
+ */
+Reflect.defineProperty(CustomEvent.prototype, "detail", { enumerable: true });
diff --git a/js/custom_event_test.ts b/js/custom_event_test.ts
new file mode 100644
index 000000000..4a9572780
--- /dev/null
+++ b/js/custom_event_test.ts
@@ -0,0 +1,21 @@
+// Copyright 2018 the Deno authors. All rights reserved. MIT license.
+import { test, assertEqual } from "./test_util.ts";
+
+test(function customEventInitializedWithDetail() {
+ const type = "touchstart";
+ const detail = { message: "hello" };
+ const customEventDict = new CustomEventInit({
+ bubbles: true,
+ cancelable: true,
+ detail
+ });
+ const event = new CustomEvent(type, customEventDict);
+
+ assertEqual(event.bubbles, true);
+ assertEqual(event.cancelable, true);
+ assertEqual(event.currentTarget, null);
+ assertEqual(event.detail, detail);
+ assertEqual(event.isTrusted, false);
+ assertEqual(event.target, null);
+ assertEqual(event.type, type);
+});
diff --git a/js/dom_types.ts b/js/dom_types.ts
index 068ae9cfd..0c6814dae 100644
--- a/js/dom_types.ts
+++ b/js/dom_types.ts
@@ -144,6 +144,11 @@ export interface EventInit {
composed?: boolean;
}
+export interface CustomEventInit extends EventInit {
+ // tslint:disable-next-line:no-any
+ detail?: any;
+}
+
export enum EventPhase {
NONE = 0,
CAPTURING_PHASE = 1,
@@ -182,6 +187,18 @@ export interface Event {
readonly timeStamp: Date;
}
+export interface CustomEvent extends Event {
+ // tslint:disable-next-line:no-any
+ readonly detail: any;
+ initCustomEvent(
+ type: string,
+ bubbles?: boolean,
+ cancelable?: boolean,
+ // tslint:disable-next-line:no-any
+ detail?: any | null
+ ): void;
+}
+
/* TODO(ry) Re-expose this interface. There is currently some interference
* between deno's File and this one.
*/
diff --git a/js/event.ts b/js/event.ts
index b0d16ff0a..1cc711b32 100644
--- a/js/event.ts
+++ b/js/event.ts
@@ -22,6 +22,8 @@ export class EventInit implements domTypes.EventInit {
export class Event implements domTypes.Event {
// 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;
@@ -30,6 +32,7 @@ export class Event implements domTypes.Event {
private _path: domTypes.EventPath[] = [];
constructor(type: string, eventInitDict: domTypes.EventInit = {}) {
+ this._initializedFlag = true;
eventAttributes.set(this, {
type,
bubbles: eventInitDict.bubbles || false,
@@ -71,14 +74,36 @@ export class Event implements domTypes.Event {
return this._canceledFlag;
}
+ get dispatched(): boolean {
+ return this._dispatchedFlag;
+ }
+
get eventPhase(): number {
return getPrivateValue(this, eventAttributes, "eventPhase");
}
+ get initialized(): boolean {
+ return this._initializedFlag;
+ }
+
get isTrusted(): boolean {
return getPrivateValue(this, eventAttributes, "isTrusted");
}
+ set isTrusted(value) {
+ eventAttributes.set(this, {
+ type: this.type,
+ bubbles: this.bubbles,
+ cancelable: this.cancelable,
+ composed: this.composed,
+ currentTarget: this.currentTarget,
+ eventPhase: this.eventPhase,
+ isTrusted: value,
+ target: this.target,
+ timeStamp: this.timeStamp
+ });
+ }
+
get target(): domTypes.EventTarget {
return getPrivateValue(this, eventAttributes, "target");
}
diff --git a/js/event_target_test.ts b/js/event_target_test.ts
index 6065c875a..c6477f2c7 100644
--- a/js/event_target_test.ts
+++ b/js/event_target_test.ts
@@ -34,8 +34,8 @@ test(function constructedEventTargetCanBeUsedAsExpected() {
test(function anEventTargetCanBeSubclassed() {
class NicerEventTarget extends EventTarget {
- on(type, listener?, options?) {
- this.addEventListener(type, listener, options);
+ on(type, callback?, options?) {
+ this.addEventListener(type, callback, options);
}
off(type, callback?, options?) {
diff --git a/js/globals.ts b/js/globals.ts
index edf7fae8f..706d6cd15 100644
--- a/js/globals.ts
+++ b/js/globals.ts
@@ -9,6 +9,7 @@
// can be expressed as a namespace in the type library.
import * as blob from "./blob";
import * as consoleTypes from "./console";
+import * as customEvent from "./custom_event";
import * as domTypes from "./dom_types";
import * as event from "./event";
import * as eventTarget from "./event_target";
@@ -64,6 +65,10 @@ export type Blob = blob.DenoBlob;
// window.File = file.DenoFile;
// export type File = file.DenoFile;
+window.CustomEventInit = customEvent.CustomEventInit;
+export type CustomEventInit = customEvent.CustomEventInit;
+window.CustomEvent = customEvent.CustomEvent;
+export type CustomEvent = customEvent.CustomEvent;
window.EventInit = event.EventInit;
export type EventInit = event.EventInit;
window.Event = event.Event;
diff --git a/js/unit_tests.ts b/js/unit_tests.ts
index 51027c387..68fa20d07 100644
--- a/js/unit_tests.ts
+++ b/js/unit_tests.ts
@@ -9,6 +9,7 @@ import "./chmod_test.ts";
import "./compiler_test.ts";
import "./console_test.ts";
import "./copy_file_test.ts";
+import "./custom_event_test.ts";
import "./dir_test.ts";
import "./event_test.ts";
import "./event_target_test.ts";