Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/calm-types-erase.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@remote-dom/polyfill': patch
---

Make the Polyfill source compatible with type stripping by replacing TypeScript enums and a parameter property with erasable syntax.
7 changes: 4 additions & 3 deletions packages/polyfill/source/Attr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ import {
VALUE,
OWNER_ELEMENT,
NAME,
NamespaceURI,
NodeType,
NODE_TYPE_ATTRIBUTE,
type NamespaceURI,
type NodeType,
HOOKS,
} from './constants.ts';
import {Node} from './Node.ts';
import type {Element} from './Element.ts';

export class Attr extends Node {
nodeType = NodeType.ATTRIBUTE_NODE;
nodeType: NodeType = NODE_TYPE_ATTRIBUTE;
[NS]: NamespaceURI | null = null;
[NEXT]: Attr | null = null;
[VALUE]: string;
Expand Down
4 changes: 2 additions & 2 deletions packages/polyfill/source/Comment.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {NAME} from './constants.ts';
import {NAME, NODE_TYPE_COMMENT, type NodeType} from './constants.ts';
import {CharacterData} from './CharacterData.ts';

export class Comment extends CharacterData {
nodeType = 8;
nodeType: NodeType = NODE_TYPE_COMMENT;
[NAME] = '#comment';
}
10 changes: 6 additions & 4 deletions packages/polyfill/source/Document.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import {
NS,
NAME,
NamespaceURI,
NodeType,
NODE_TYPE_DOCUMENT,
SVG_NAMESPACE,
type NamespaceURI,
type NodeType,
OWNER_DOCUMENT,
HOOKS,
IS_CONNECTED,
Expand All @@ -28,7 +30,7 @@ import {HTMLHeadElement} from './HTMLHeadElement.ts';
import {HTMLHtmlElement} from './HTMLHtmlElement.ts';

export class Document extends ParentNode {
nodeType = NodeType.DOCUMENT_NODE;
nodeType: NodeType = NODE_TYPE_DOCUMENT;
[NAME] = '#document';
body: HTMLBodyElement;
head: HTMLHeadElement;
Expand Down Expand Up @@ -115,7 +117,7 @@ export function createElement<T extends Element>(
let element: T;
const lowerName = String(name).toLowerCase();

if (namespace === NamespaceURI.SVG) {
if (namespace === SVG_NAMESPACE) {
element = new SVGElement() as any;
} else if (lowerName === 'template') {
element = new HTMLTemplateElement() as any;
Expand Down
9 changes: 7 additions & 2 deletions packages/polyfill/source/DocumentFragment.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import {NAME, OWNER_DOCUMENT, NodeType} from './constants.ts';
import {
NAME,
OWNER_DOCUMENT,
NODE_TYPE_DOCUMENT_FRAGMENT,
type NodeType,
} from './constants.ts';
import {ParentNode} from './ParentNode.ts';
import {getElementById as findElementById} from './shared.ts';

export class DocumentFragment extends ParentNode {
nodeType = NodeType.DOCUMENT_FRAGMENT_NODE;
nodeType: NodeType = NODE_TYPE_DOCUMENT_FRAGMENT;
[NAME] = '#document-fragment';
[OWNER_DOCUMENT] = (typeof window !== 'undefined'
? window.document
Expand Down
13 changes: 10 additions & 3 deletions packages/polyfill/source/Element.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import {NS, ATTRIBUTES, NamespaceURI, NodeType} from './constants.ts';
import {
NS,
ATTRIBUTES,
HTML_NAMESPACE,
NODE_TYPE_ELEMENT,
type NamespaceURI,
type NodeType,
} from './constants.ts';
import {ParentNode} from './ParentNode.ts';
import {NamedNodeMap} from './NamedNodeMap.ts';
import {Attr} from './Attr.ts';
Expand All @@ -8,9 +15,9 @@ import {getElementsByTagName as findElementsByTagName} from './shared.ts';
export class Element extends ParentNode {
static readonly observedAttributes?: string[];

nodeType = NodeType.ELEMENT_NODE;
nodeType: NodeType = NODE_TYPE_ELEMENT;

[NS] = NamespaceURI.XHTML;
[NS]: NamespaceURI = HTML_NAMESPACE;
get namespaceURI() {
return this[NS];
}
Expand Down
48 changes: 21 additions & 27 deletions packages/polyfill/source/Event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@ import {
} from './constants.ts';
import type {EventTarget} from './EventTarget.ts';

// TODO: Replace this enum with one-way constants, matching the DOM and Web IDL.
// @ts-expect-error -- Legacy enum; keep this exception scoped to this declaration.
export const enum EventPhase {
NONE = 0,
CAPTURING_PHASE = 1,
AT_TARGET = 2,
BUBBLING_PHASE = 3,
}
export const EVENT_PHASE_NONE = 0;
export const EVENT_PHASE_CAPTURING = 1;
export const EVENT_PHASE_AT_TARGET = 2;
export const EVENT_PHASE_BUBBLING = 3;

export type EventPhase = number;

export const CAPTURE_MARKER = '@';

Expand All @@ -29,16 +27,17 @@ const now =
: performance.now.bind(performance);

export class Event {
static NONE = EventPhase.NONE;
static CAPTURING_PHASE = EventPhase.CAPTURING_PHASE;
static AT_TARGET = EventPhase.AT_TARGET;
static BUBBLING_PHASE = EventPhase.BUBBLING_PHASE;
static NONE: EventPhase = EVENT_PHASE_NONE;
static CAPTURING_PHASE: EventPhase = EVENT_PHASE_CAPTURING;
static AT_TARGET: EventPhase = EVENT_PHASE_AT_TARGET;
static BUBBLING_PHASE: EventPhase = EVENT_PHASE_BUBBLING;

// NONE = EventPhase.NONE;
// CAPTURING_PHASE = EventPhase.CAPTURING_PHASE;
// AT_TARGET = EventPhase.AT_TARGET;
// BUBBLING_PHASE = EventPhase.BUBBLING_PHASE;
// NONE = EVENT_PHASE_NONE;
// CAPTURING_PHASE = EVENT_PHASE_CAPTURING;
// AT_TARGET = EVENT_PHASE_AT_TARGET;
// BUBBLING_PHASE = EVENT_PHASE_BUBBLING;

type: string;
timeStamp = now();
target: EventTarget | null = null;
currentTarget: EventTarget | null = null;
Expand All @@ -48,18 +47,15 @@ export class Event {
composed = false;
defaultPrevented = false;
cancelBubble = false;
eventPhase: EventPhase = 0;
eventPhase: EventPhase = EVENT_PHASE_NONE;
// private inPassiveListener = false;
data?: any;
[PATH]: EventTarget[] = [];
[IS_TRUSTED]!: boolean;
[STOP_IMMEDIATE_PROPAGATION] = false;

constructor(
// @ts-expect-error -- Legacy parameter property; keep this exception scoped to this declaration.
public type: string,
options?: EventInit,
) {
constructor(type: string, options?: EventInit) {
this.type = type;
Object.defineProperty(this, IS_TRUSTED, {writable: true, value: false});
if (options) {
if (options.bubbles) this.bubbles = options.bubbles;
Expand Down Expand Up @@ -108,20 +104,18 @@ export class Event {
export function fireEvent(
event: Event,
currentTarget: EventTarget,
phase: EventPhase.BUBBLING_PHASE | EventPhase.CAPTURING_PHASE,
phase: typeof EVENT_PHASE_BUBBLING | typeof EVENT_PHASE_CAPTURING,
): void {
const listeners = currentTarget[LISTENERS];
const list = listeners?.get(
`${event.type}${
phase === EventPhase.CAPTURING_PHASE ? CAPTURE_MARKER : ''
}`,
`${event.type}${phase === EVENT_PHASE_CAPTURING ? CAPTURE_MARKER : ''}`,
);

if (!list) return;

for (const listener of list) {
event.eventPhase =
event.target === currentTarget ? EventPhase.AT_TARGET : phase;
event.target === currentTarget ? EVENT_PHASE_AT_TARGET : phase;
event.currentTarget = currentTarget;

try {
Expand Down
10 changes: 7 additions & 3 deletions packages/polyfill/source/EventTarget.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import {HOOKS, PATH, LISTENERS, OWNER_DOCUMENT} from './constants.ts';
import {fireEvent, EventPhase} from './Event.ts';
import {
EVENT_PHASE_BUBBLING,
EVENT_PHASE_CAPTURING,
fireEvent,
} from './Event.ts';
import {CAPTURE_MARKER, type Event} from './Event.ts';
import type {ChildNode} from './ChildNode.ts';
import type {Document} from './Document.ts';
Expand Down Expand Up @@ -114,14 +118,14 @@ export class EventTarget {
event[PATH] = path;

for (let i = path.length; i--; ) {
fireEvent(event, path[i]!, EventPhase.CAPTURING_PHASE);
fireEvent(event, path[i]!, EVENT_PHASE_CAPTURING);
if (event.cancelBubble) return event.defaultPrevented;
}

const bubblePath = event.bubbles ? path : path.slice(0, 1);

for (let i = 0; i < bubblePath.length; i++) {
fireEvent(event, bubblePath[i]!, EventPhase.BUBBLING_PHASE);
fireEvent(event, bubblePath[i]!, EVENT_PHASE_BUBBLING);
if (event.cancelBubble) return event.defaultPrevented;
}

Expand Down
2 changes: 1 addition & 1 deletion packages/polyfill/source/NamedNodeMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
OWNER_ELEMENT,
NS,
NEXT,
NamespaceURI,
type NamespaceURI,
HOOKS,
} from './constants.ts';
import type {Attr} from './Attr.ts';
Expand Down
11 changes: 6 additions & 5 deletions packages/polyfill/source/Node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import {
CHILD,
PREV,
NEXT,
NamespaceURI,
NodeType,
HTML_NAMESPACE,
NODE_TYPE_NODE,
type NodeType,
HOOKS,
IS_CONNECTED,
} from './constants.ts';
Expand All @@ -22,7 +23,7 @@ import {
} from './shared.ts';

export class Node extends EventTarget {
nodeType = NodeType.NODE;
nodeType: NodeType = NODE_TYPE_NODE;

[OWNER_DOCUMENT]!: Document;
[NAME] = '';
Expand Down Expand Up @@ -52,8 +53,8 @@ export class Node extends EventTarget {
return this[IS_CONNECTED];
}

isDefaultNamespace(namespace: string) {
return namespace === NamespaceURI.XHTML;
isDefaultNamespace(namespace: string): namespace is typeof HTML_NAMESPACE {
return namespace === HTML_NAMESPACE;
}

get parentNode() {
Expand Down
11 changes: 6 additions & 5 deletions packages/polyfill/source/ParentNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import {
PREV,
PARENT,
OWNER_DOCUMENT,
NodeType,
NODE_TYPE_DOCUMENT_FRAGMENT,
NODE_TYPE_ELEMENT,
HOOKS,
IS_CONNECTED,
} from './constants.ts';
Expand Down Expand Up @@ -81,7 +82,7 @@ export class ParentNode extends ChildNode {
}
}

if (this.nodeType === NodeType.ELEMENT_NODE) {
if (this.nodeType === NODE_TYPE_ELEMENT) {
this[HOOKS].removeChild?.(this as any, child as any, childNodesIndex);
}
}
Expand All @@ -105,7 +106,7 @@ export class ParentNode extends ChildNode {

private insertInto(child: Node, before: Node | null) {
// append the children of a DocumentFragment:
if (child.nodeType === NodeType.DOCUMENT_FRAGMENT_NODE) {
if (child.nodeType === NODE_TYPE_DOCUMENT_FRAGMENT) {
let node = child[CHILD];
while (node) {
const next = node[NEXT];
Expand Down Expand Up @@ -144,7 +145,7 @@ export class ParentNode extends ChildNode {
}

const ownerDocument = this[OWNER_DOCUMENT];
const isElement = child.nodeType === NodeType.ELEMENT_NODE;
const isElement = child.nodeType === NODE_TYPE_ELEMENT;

child[PARENT] = this;
child[OWNER_DOCUMENT] = ownerDocument;
Expand Down Expand Up @@ -179,7 +180,7 @@ export class ParentNode extends ChildNode {
}
}

if (this.nodeType === NodeType.ELEMENT_NODE) {
if (this.nodeType === NODE_TYPE_ELEMENT) {
this[HOOKS].insertChild?.(this as any, child as any, insertIndex);
}
}
Expand Down
4 changes: 2 additions & 2 deletions packages/polyfill/source/SVGElement.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {NS, NamespaceURI} from './constants.ts';
import {NS, SVG_NAMESPACE, type NamespaceURI} from './constants.ts';
import {Element} from './Element.ts';

export class SVGElement extends Element {
[NS] = NamespaceURI.SVG;
[NS]: NamespaceURI = SVG_NAMESPACE;

get ownerSVGElement() {
let root: SVGElement | null = null;
Expand Down
4 changes: 2 additions & 2 deletions packages/polyfill/source/Text.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {NAME, NodeType} from './constants.ts';
import {NAME, NODE_TYPE_TEXT, type NodeType} from './constants.ts';
import {CharacterData} from './CharacterData.ts';

export class Text extends CharacterData {
nodeType = NodeType.TEXT_NODE;
nodeType: NodeType = NODE_TYPE_TEXT;
[NAME] = '#text';
}
40 changes: 18 additions & 22 deletions packages/polyfill/source/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,22 @@ export const CONTENT = Symbol('content');
export const HOOKS = Symbol('hooks');
export const IS_CONNECTED = Symbol('is_connected');

// TODO: Replace this enum with one-way constants, matching the DOM and Web IDL.
// @ts-expect-error -- Legacy enum; keep this exception scoped to this declaration.
export const enum NodeType {
NODE = 0,
ELEMENT_NODE = 1,
ATTRIBUTE_NODE = 2,
TEXT_NODE = 3,
CDATA_SECTION_NODE = 4,
ENTITY_REFERENCE_NODE = 5,
ENTITY_NODE = 6,
PROCESSING_INSTRUCTION_NODE = 7,
COMMENT_NODE = 8,
DOCUMENT_NODE = 9,
DOCUMENT_TYPE_NODE = 10,
DOCUMENT_FRAGMENT_NODE = 11,
}
export const NODE_TYPE_NODE = 0;
export const NODE_TYPE_ELEMENT = 1;
export const NODE_TYPE_ATTRIBUTE = 2;
export const NODE_TYPE_TEXT = 3;
export const NODE_TYPE_CDATA_SECTION = 4;
export const NODE_TYPE_ENTITY_REFERENCE = 5;
export const NODE_TYPE_ENTITY = 6;
export const NODE_TYPE_PROCESSING_INSTRUCTION = 7;
export const NODE_TYPE_COMMENT = 8;
export const NODE_TYPE_DOCUMENT = 9;
export const NODE_TYPE_DOCUMENT_TYPE = 10;
export const NODE_TYPE_DOCUMENT_FRAGMENT = 11;

// TODO: Replace this enum with namespace string constants, matching the DOM.
// @ts-expect-error -- Legacy enum; keep this exception scoped to this declaration.
export const enum NamespaceURI {
XHTML = 'http://www.w3.org/1999/xhtml',
SVG = 'http://www.w3.org/2000/svg',
}
export type NodeType = number;

export const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
export const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';

export type NamespaceURI = typeof HTML_NAMESPACE | typeof SVG_NAMESPACE;
Loading
Loading