Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUGFIX stable] EmberComponent's element is an Element #20491

Merged
merged 1 commit into from
Jun 30, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import {
validateTag,
valueForTag,
} from '@glimmer/validator';
import type { SimpleElement } from '@simple-dom/interface';
import type Component from '../component';
import type { DynamicScope } from '../renderer';
import type RuntimeResolver from '../resolver';
Expand Down Expand Up @@ -365,7 +364,7 @@ export default class CurlyComponentManager

didCreateElement(
{ component, classRef, isInteractive, rootRef }: ComponentStateBucket,
element: SimpleElement,
element: Element,
operations: ElementOperations
): void {
setViewElement(component, element);
Expand Down
4 changes: 2 additions & 2 deletions packages/@ember/-internals/glimmer/lib/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { isUpdatableRef, updateRef } from '@glimmer/reference';
import { normalizeProperty } from '@glimmer/runtime';
import type { DirtyableTag } from '@glimmer/validator';
import { createTag, dirtyTag } from '@glimmer/validator';
import { Namespace } from '@simple-dom/interface';
import { Namespace, type SimpleElement } from '@simple-dom/interface';
import {
ARGS,
BOUNDS,
Expand Down Expand Up @@ -1001,7 +1001,7 @@ class Component<S = unknown>

let element = _element;
let isSVG = element.namespaceURI === Namespace.SVG;
let { type, normalized } = normalizeProperty(element, name);
let { type, normalized } = normalizeProperty(element as unknown as SimpleElement, name);

if (isSVG || type === 'attr') {
return element.getAttribute(normalized);
Expand Down
2 changes: 1 addition & 1 deletion packages/@ember/-internals/glimmer/lib/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ export class Renderer {
this._clearAllRoots();
}

getElement(view: View): Option<SimpleElement> {
getElement(view: View): Option<Element> {
if (this._isInteractive) {
return getViewElement(view);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ function K(this: unknown) {
*/
interface ViewMixin {
rerender(): unknown;
element: SimpleElement;
element: Element;
appendTo(selector: string | Element | SimpleElement): this;
append(): this;
elementId: string | null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import ActionManager from './action_manager';
import type { BootEnvironment } from '@ember/-internals/glimmer/lib/views/outlet';
import type Component from '@ember/component';
import type { ActionState } from '@ember/-internals/glimmer/lib/modifiers/action';
import type { SimpleElement } from '@simple-dom/interface';

/**
@module ember
Expand Down Expand Up @@ -255,9 +254,7 @@ export default class EventDispatcher extends EmberObject {
}

let viewHandler = (target: Element, event: Event) => {
// SAFETY: SimpleElement is supposed to be a subset of Element so this _should_ be safe.
// However, the types are more specific in some places which necessitates the `as`.
let view = getElementView(target as unknown as SimpleElement);
let view = getElementView(target);
let result = true;

if (view) {
Expand Down Expand Up @@ -325,9 +322,7 @@ export default class EventDispatcher extends EmberObject {
);

do {
// SAFETY: SimpleElement is supposed to be a subset of Element so this _should_ be safe.
// However, the types are more specific in some places which necessitates the `as`.
if (getElementView(target as unknown as SimpleElement)) {
if (getElementView(target)) {
if (viewHandler(target, event) === false) {
event.preventDefault();
event.stopPropagation();
Expand Down
15 changes: 7 additions & 8 deletions packages/@ember/-internals/views/lib/system/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { getOwner } from '@ember/-internals/owner';
import { guidFor } from '@ember/-internals/utils';
import { assert } from '@ember/debug';
import type { Dict, Option } from '@glimmer/interfaces';
import type { SimpleElement } from '@simple-dom/interface';

/**
@module ember
Expand Down Expand Up @@ -68,10 +67,10 @@ export function getViewId(view: View): string {
}
}

const ELEMENT_VIEW: WeakMap<SimpleElement, View> = new WeakMap();
const VIEW_ELEMENT: WeakMap<View, SimpleElement> = new WeakMap();
const ELEMENT_VIEW: WeakMap<Element, View> = new WeakMap();
const VIEW_ELEMENT: WeakMap<View, Element> = new WeakMap();

export function getElementView(element: SimpleElement): Option<View> {
export function getElementView(element: Element): Option<View> {
return ELEMENT_VIEW.get(element) || null;
}

Expand All @@ -80,15 +79,15 @@ export function getElementView(element: SimpleElement): Option<View> {
@method getViewElement
@param {Ember.View} view
*/
export function getViewElement(view: View): Option<SimpleElement> {
export function getViewElement(view: View): Option<Element> {
return VIEW_ELEMENT.get(view) || null;
}

export function setElementView(element: SimpleElement, view: View): void {
export function setElementView(element: Element, view: View): void {
ELEMENT_VIEW.set(element, view);
}

export function setViewElement(view: View, element: SimpleElement): void {
export function setViewElement(view: View, element: Element): void {
VIEW_ELEMENT.set(view, element);
}

Expand All @@ -97,7 +96,7 @@ export function setViewElement(view: View, element: SimpleElement): void {
// this case, we want to prevent access to the element (and vice verse) during
// destruction.

export function clearElementView(element: SimpleElement): void {
export function clearElementView(element: Element): void {
ELEMENT_VIEW.delete(element);
}

Expand Down
7 changes: 7 additions & 0 deletions type-tests/@ember/component-test/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,10 @@ class SigExample extends Component<MySig> {
return `${name} is ${age} years old`;
}
}

// There is no type safety mapping `Element` here
class ElementOnComponent extends Component<{ Element: HTMLDivElement }> {
get hmm(): boolean {
return this.element.dispatchEvent(new Event('mousedown'));
}
}
Loading