Register the movie objects inserted by WASM-Bindgen to the JS DOM
This was existing Flash functionality, so this is somewhere between an enhancement request and a bug report, but anyway....
Brought to light in manually testing #20434 --
We should create a bridge between WASM-BindGen and the WebIDL accessor properties so that when it's adding nodes to the tree, the movie object(s) (whether it's part of an embed or an object) are accessible via dot syntax and bracketed indexing.
Syntax such as window.document[movieName] or even just document.movieName should be valid.
Currently, because they only exist as nodes on the DOM tree, they are accessible by DOM methods like document.getElementById, but a lot of older Flash code leveraged Flash's built-in DOM registration to function, like the Sedea application in Onda Educa.
As an example, see JS DOM Play Test
On that page, window.movieemb works just fine (as that's a way to get elements by id without getElementById even on modern browsers). What W3C specification guarantees window.document["movieemb"] or document.movieemb to work for embeds, out of curiosity?
Seems it's about the name, not the id.
It's this in W3C, the rules are quite complex: https://html.spec.whatwg.org/multipage/nav-history-apis.html#named-access-on-the-window-object
As a general rule, relying on this will lead to brittle code. Which IDs end up mapping to this API can vary over time, as new features are added to the web platform, for example.
Most notably, the browser automatically assigns this for any embed, form, img, or object. A ruffle-embed, ruffle-object, and ruffle-player is none of those so we'd have to somehow handle this ourselves.
and that's really kind of the crux of this whole situation, something that has come up plenty of times, especially in #7868 I should probably just plug this build into Onda and see what happens. I know we still don't have all the properties and methods we need, but......
Most notably, the browser automatically assigns this for any embed, form, img, or object. A
ruffle-embed,ruffle-object, andruffle-playeris none of those so we'd have to somehow handle this ourselves.
If we decide to implement this behavior (which seems challenging if we want to match what browsers do for other tags), I think it should apply only to the polyfill elements (ruffle-object and ruffle-embed).
I ran some tests in Firefox and Chrome:
<embed type="application/x-shockwave-flash" src="test.swf" id="flID" name="flName" bgcolor="000000" width="300" height="300"/>
-
Only the
nameattribute is added as property on thedocumentobject (document.flNamereturns a reference to the element,document.flIDreturnsundefined). -
Removing the embed from the DOM also removes the corresponding property from
document(document.hasOwnProperty("flName")then returnsfalse). -
If multiple embed elements share the same name, the value on
documentbecomes anHTMLCollectionobject. -
This does not override an existing user-defined property on
document... but this can override native properties such ascreateElement(eek!).
Basilisk and Internet Explorer 11 (in Edge) differ in several ways from what is described above; most notably, they also take the id attribute into account.
I'm a bit less hesitant to do this though: https://github.com/ruffle-rs/ruffle/blob/master/web/packages/core/src/internal/register-element.ts#L88
window.customElements.define(externalName, elementClass);
if (elementName === "ruffle-embed") {
const orig = Object.getOwnPropertyDescriptor(
Document.prototype,
"embeds",
);
if (orig && orig.get) {
Object.defineProperty(Document.prototype, "embeds", {
get() {
const nodes = this.querySelectorAll(
"embed, ruffle-embed",
);
const list = Array.from(nodes) as Element[];
(list as unknown as HTMLCollection).item = (
i: number,
): Element | null => list[i] ?? null;
(list as unknown as HTMLCollection).namedItem =
(name: string): Element | null =>
list.find((el) => {
const htmlEl = el as HTMLElement;
return (
htmlEl.getAttribute("name") ===
name || htmlEl.id === name
);
}) ?? null;
return list;
},
});
}
}
https://developer.mozilla.org/en-US/docs/Web/API/Document/embeds
Daniel's snippet above is what I had in mind, and honestly, I don't think we should try to do any more than that unless we're prepared for a sizeable headache.
I wrote #22465 so we would know how complex full support of named accesses on document would be. The answer is fairly complex. I may close that PR unmerged depending on what others say, but I wanted to record the needed work nonetheless.
#22449 was written for document.embeds. #22465 would support the IDL selectors per Toad's findings, but may not wind up merged due to its complexity.
I appreciate your diligence, Daniel, regardless of what comes of it!