Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Web API: CustomEvent (denoland#1505)
  • Loading branch information
acconrad authored and ry committed Jan 23, 2019
1 parent 77114fb commit e470f31
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 2 deletions.
1 change: 1 addition & 0 deletions BUILD.gn
Expand Up @@ -56,6 +56,7 @@ ts_sources = [
"js/compiler.ts",
"js/console.ts",
"js/copy_file.ts",
"js/custom_event.ts",
"js/deno.ts",
"js/dir.ts",
"js/dispatch.ts",
Expand Down
60 changes: 60 additions & 0 deletions 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 });
21 changes: 21 additions & 0 deletions 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);
});
17 changes: 17 additions & 0 deletions js/dom_types.ts
Expand Up @@ -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,
Expand Down Expand Up @@ -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.
*/
Expand Down
25 changes: 25 additions & 0 deletions js/event.ts
Expand Up @@ -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;
Expand All @@ -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,
Expand Down Expand Up @@ -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");
}
Expand Down
4 changes: 2 additions & 2 deletions js/event_target_test.ts
Expand Up @@ -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?) {
Expand Down
5 changes: 5 additions & 0 deletions js/globals.ts
Expand Up @@ -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";
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions js/unit_tests.ts
Expand Up @@ -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";
Expand Down

0 comments on commit e470f31

Please sign in to comment.