ruffle icon indicating copy to clipboard operation
ruffle copied to clipboard

Register the movie objects inserted by WASM-Bindgen to the JS DOM

Open sombraguerrero opened this issue 1 month ago • 10 comments

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

sombraguerrero avatar Dec 07 '25 21:12 sombraguerrero

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?

danielhjacobs avatar Dec 08 '25 05:12 danielhjacobs

Seems it's about the name, not the id.

danielhjacobs avatar Dec 08 '25 05:12 danielhjacobs

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.

danielhjacobs avatar Dec 08 '25 05:12 danielhjacobs

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.

danielhjacobs avatar Dec 08 '25 05:12 danielhjacobs

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......

sombraguerrero avatar Dec 08 '25 06:12 sombraguerrero

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.

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 name attribute is added as property on the document object (document.flName returns a reference to the element, document.flID returns undefined).

  • Removing the embed from the DOM also removes the corresponding property from document (document.hasOwnProperty("flName") then returns false).

  • If multiple embed elements share the same name, the value on document becomes an HTMLCollection object.

  • This does not override an existing user-defined property on document... but this can override native properties such as createElement (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.

Toad06 avatar Dec 08 '25 12:12 Toad06

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

danielhjacobs avatar Dec 08 '25 15:12 danielhjacobs

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.

sombraguerrero avatar Dec 08 '25 18:12 sombraguerrero

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.

danielhjacobs avatar Dec 09 '25 20:12 danielhjacobs

#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.

danielhjacobs avatar Dec 09 '25 21:12 danielhjacobs

I appreciate your diligence, Daniel, regardless of what comes of it!

sombraguerrero avatar Dec 10 '25 19:12 sombraguerrero