Repository navigation
fix: native functions read through window run with the global as receiver - #355
Open
jonasporto wants to merge 1 commit into
Open
jonasporto wants to merge 1 commit into
jonasporto wants to merge 1 commit into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #345
document.defaultViewis a Proxy overglobalThis. A native function read through it (window.setTimeout,window.queueMicrotask,window.requestAnimationFrame) is called with the proxy as receiver, and browsers reject that withTypeError: Illegal invocation. It shows up withlinkedom/worker: d3-timer captureswindow.requestAnimationFrame.bind(window)at load time, so any d3 transition created while linkedom'swindowis the global throws. Still the case on 0.18.14 andmain(e2ee208).Change
In the proxy's
get, a value that comes fromglobalThisand is a function without aprototype(a native that cannot be constructed) is returned bound toglobalThis, once per function (WeakMap), sowindow.setTimeout === window.setTimeout. Constructors have aprototypeand are returned as they are:new window.URL(...),instanceofand identity are unchanged. Values from theglobalsargument and linkedom's own exports are untouched.Proxyhas noprototypeand gets bound; a bound function keeps [[Construct]], sonew window.Proxy({}, {})still works.cjs/interface/document.jsis regenerated withnpm run cjs. The test intest/html/document.jssets a method (noprototype) onglobalThisand checks it runs withglobalThisas receiver throughwindow, that the bound function is cached, and thatwindow.URLkeeps its identity. In Node the timer functions are plain functions with aprototype, so they are not bound there; only real natives are.npm testpasses with the same coverage asmain.In Chrome
The issue's test case, run in Chrome 156 (headless) against a
worker.jsbuilt from this branch withrollup -c rollup/es.config.js, beside the bundle committed onmain:mainbundlewindow.setTimeout(f)window.queueMicrotask(f)window.requestAnimationFrame(f)window.requestAnimationFrame.bind(window)(f)new window.URL(...),window.URL === URL,new window.Proxy({}, {}),window.fetch(...)worker.jsis not rebuilt in this PR.