Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[WebIDL] Hoist protectedThis reference in JSEventListener::handleEvent()
https://commits.webkit.org/257027@main
  • Loading branch information
shvaikalesh authored Nov 28, 2022
1 parent 5c727b3 commit 22ecfc9
Show file tree
Hide file tree
Showing 12 changed files with 440 additions and 67 deletions.
83 changes: 83 additions & 0 deletions custom-elements/cross-realm-callback-report-exception.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<!doctype html>
<meta charset=utf-8>
<title>Exceptions raised in constructors / lifecycle callbacks are reported in their global objects</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<iframe></iframe>
<iframe></iframe>
<iframe></iframe>
<script>
setup({ allow_uncaught_exception: true });

window.onerror = () => { onerrorCalls.push("top"); };
frames[0].onerror = () => { onerrorCalls.push("frame0"); };
frames[1].onerror = () => { onerrorCalls.push("frame1"); };
frames[2].onerror = () => { onerrorCalls.push("frame2"); };

const sourceThrowError = `throw new parent.frames[2].Error("PASS")`;

test(t => {
window.onerrorCalls = [];

const XFoo = new frames[1].Function(sourceThrowError);
frames[0].customElements.define("x-foo-constructor", XFoo);

frames[0].document.createElement("x-foo-constructor");
assert_array_equals(onerrorCalls, ["frame1"]);
}, "constructor");

test(t => {
window.onerrorCalls = [];

const XFooConnected = class extends frames[0].HTMLElement {};
XFooConnected.prototype.connectedCallback = new frames[1].Function(sourceThrowError);
frames[0].customElements.define("x-foo-connected", XFooConnected);

const el = frames[0].document.createElement("x-foo-connected");
frames[0].document.body.append(el);

assert_array_equals(onerrorCalls, ["frame1"]);
}, "connectedCallback");

test(t => {
window.onerrorCalls = [];

const XFooDisconnected = class extends frames[0].HTMLElement {};
XFooDisconnected.prototype.disconnectedCallback = new frames[1].Function(sourceThrowError);
frames[0].customElements.define("x-foo-disconnected", XFooDisconnected);

const el = frames[0].document.createElement("x-foo-disconnected");
frames[0].document.body.append(el);
el.remove();

assert_array_equals(onerrorCalls, ["frame1"]);
}, "disconnectedCallback");

test(t => {
window.onerrorCalls = [];

const XFooAttributeChanged = class extends frames[0].HTMLElement {};
XFooAttributeChanged.observedAttributes = ["foo"];
XFooAttributeChanged.prototype.attributeChangedCallback = new frames[1].Function(sourceThrowError);
frames[0].customElements.define("x-foo-attribute-changed", XFooAttributeChanged);

const el = frames[0].document.createElement("x-foo-attribute-changed");
frames[0].document.body.append(el);
el.setAttribute("foo", "bar");

assert_array_equals(onerrorCalls, ["frame1"]);
}, "attributeChangedCallback");

test(t => {
window.onerrorCalls = [];

const XFooAdopted = class extends frames[0].HTMLElement {};
XFooAdopted.prototype.adoptedCallback = new frames[1].Function(sourceThrowError);
frames[0].customElements.define("x-foo-adopted", XFooAdopted);

const el = frames[0].document.createElement("x-foo-adopted");
document.body.append(el);

assert_array_equals(onerrorCalls, ["frame1"]);
}, "adoptedCallback");
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<!doctype html>
<meta charset=utf-8>
<title>MutationObserver reports the exception from its callback in the callback's global object</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<iframe></iframe>
<iframe></iframe>
<iframe></iframe>
<script>
setup({ allow_uncaught_exception: true });

const onerrorCalls = [];
window.onerror = () => { onerrorCalls.push("top"); };
frames[0].onerror = () => { onerrorCalls.push("frame0"); };
frames[1].onerror = () => { onerrorCalls.push("frame1"); };
frames[2].onerror = () => { onerrorCalls.push("frame2"); };

async_test(t => {
window.onload = t.step_func(() => {
const target = frames[0].document.body;
const mo = new frames[0].MutationObserver(new frames[1].Function(`throw new parent.frames[2].Error("PASS");`));

mo.observe(target, { childList: true, subtree: true });
target.append("foo");

t.step_timeout(() => {
assert_array_equals(onerrorCalls, ["frame1"]);
t.done();
}, 4);
});
});
</script>
67 changes: 0 additions & 67 deletions domxpath/resolver-callback-interface-cross-realm.html

This file was deleted.

94 changes: 94 additions & 0 deletions domxpath/resolver-callback-interface-cross-realm.tentative.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Cross-realm XPathNSResolver throws TypeError of its associated Realm</title>
<link rel="help" href="https://webidl.spec.whatwg.org/#ref-for-prepare-to-run-script">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>

<iframe name="evaluateGlobalObject" src="resources/empty-document.html"></iframe>
<iframe name="resolverGlobalObject" src="resources/empty-document.html"></iframe>
<iframe name="lookupNamespaceURIGlobalObject" src="resources/empty-document.html"></iframe>
<iframe name="relevantGlobalObject" src="resources/empty-document.html"></iframe>
<iframe name="incumbentGlobalObject" src="resources/empty-document.html"></iframe>

<script>
setup({ allow_uncaught_exception: true });

const expectedDOMExceptionType = "NAMESPACE_ERR";

test_onload(() => {
const resolver = new resolverGlobalObject.Object;

assert_reports_exception(() => {
assert_throws_dom(expectedDOMExceptionType, evaluateGlobalObject.DOMException, bind_evaluate(resolver));
});
}, "XPathNSResolver is cross-realm plain object without 'lookupNamespaceURI' property");

test_onload(() => {
const resolver = new resolverGlobalObject.Object;
resolver.lookupNamespaceURI = new lookupNamespaceURIGlobalObject.Object;

assert_reports_exception(() => {
assert_throws_dom(expectedDOMExceptionType, evaluateGlobalObject.DOMException, bind_evaluate(resolver));
});
}, "XPathNSResolver is cross-realm plain object with non-callable 'lookupNamespaceURI' property");

test_onload(() => {
const { proxy, revoke } = resolverGlobalObject.Proxy.revocable(new resolverGlobalObject.Object, {});
revoke();

assert_reports_exception(() => {
assert_throws_dom(expectedDOMExceptionType, evaluateGlobalObject.DOMException, bind_evaluate(proxy));
});
}, "XPathNSResolver is cross-realm non-callable revoked Proxy");

test_onload(() => {
const { proxy, revoke } = resolverGlobalObject.Proxy.revocable(new resolverGlobalObject.Function, {});
revoke();

assert_reports_exception(() => {
assert_throws_dom(expectedDOMExceptionType, evaluateGlobalObject.DOMException, bind_evaluate(proxy));
});
}, "XPathNSResolver is cross-realm callable revoked Proxy");

test_onload(() => {
const { proxy, revoke } = lookupNamespaceURIGlobalObject.Proxy.revocable(new lookupNamespaceURIGlobalObject.Function, {});
revoke();

const resolver = new resolverGlobalObject.Object;
resolver.lookupNamespaceURI = proxy;

assert_reports_exception(() => {
assert_throws_dom(expectedDOMExceptionType, evaluateGlobalObject.DOMException, bind_evaluate(resolver));
});
}, "XPathNSResolver is cross-realm plain object with revoked Proxy as 'lookupNamespaceURI' property");

function test_onload(fn, desc) {
async_test(t => { window.addEventListener("load", t.step_func_done(fn)); }, desc);
}

function assert_reports_exception(fn) {
let error;
const onErrorHandler = event => {
error = event.error;
event.preventDefault();
};

resolverGlobalObject.addEventListener("error", onErrorHandler);
fn();
resolverGlobalObject.removeEventListener("error", onErrorHandler);

assert_equals(typeof error, "object");
assert_equals(error.constructor, evaluateGlobalObject.TypeError);
}

function bind_evaluate(resolver) {
const boundEvaluate = new incumbentGlobalObject.Function("evaluate", "relevantDocument", "resolver", `
evaluate.call(relevantDocument, "/foo:bar", relevantDocument.documentElement, resolver);
`);

return () => {
boundEvaluate(evaluateGlobalObject.document.evaluate, relevantGlobalObject.document, resolver);
};
}
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!doctype html>
<meta charset=utf-8>
<title>toBlob() reports the exception from its callback in the callback's global object</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<iframe srcdoc="<canvas></canvas>"></iframe>
<iframe></iframe>
<iframe></iframe>
<script>
setup({ allow_uncaught_exception: true });

const onerrorCalls = [];
window.onerror = () => { onerrorCalls.push("top"); };
frames[0].onerror = () => { onerrorCalls.push("frame0"); };
frames[1].onerror = () => { onerrorCalls.push("frame1"); };
frames[2].onerror = () => { onerrorCalls.push("frame2"); };

async_test(t => {
window.onload = t.step_func(() => {
const canvas = frames[0].document.querySelector("canvas");
canvas.toBlob(new frames[1].Function(`throw new parent.frames[2].Error("PASS");`));

t.step_timeout(() => {
assert_array_equals(onerrorCalls, ["frame1"]);
t.done();
}, 25);
});
});
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!doctype html>
<meta charset=utf-8>
<title>requestAnimationFrame() reports the exception from its callback in the callback's global object</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<iframe></iframe>
<iframe></iframe>
<iframe></iframe>
<script>
setup({ allow_uncaught_exception: true });

const onerrorCalls = [];
window.onerror = () => { onerrorCalls.push("top"); };
frames[0].onerror = () => { onerrorCalls.push("frame0"); };
frames[1].onerror = () => { onerrorCalls.push("frame1"); };
frames[2].onerror = () => { onerrorCalls.push("frame2"); };

async_test(t => {
window.onload = t.step_func(() => {
frames[0].requestAnimationFrame(new frames[1].Function(`throw new parent.frames[2].Error("PASS");`));
document.querySelector("iframe").height = 200;

t.step_timeout(() => {
assert_array_equals(onerrorCalls, ["frame1"]);
t.done();
}, 100);
});
});
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!doctype html>
<meta charset=utf-8>
<title>queueMicrotask() reports the exception from its callback in the callback's global object</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<iframe></iframe>
<iframe></iframe>
<iframe></iframe>
<script>
setup({ allow_uncaught_exception: true });

const onerrorCalls = [];
window.onerror = () => { onerrorCalls.push("top"); };
frames[0].onerror = () => { onerrorCalls.push("frame0"); };
frames[1].onerror = () => { onerrorCalls.push("frame1"); };
frames[2].onerror = () => { onerrorCalls.push("frame2"); };

async_test(t => {
window.onload = t.step_func(() => {
frames[0].queueMicrotask(new frames[1].Function(`throw new parent.frames[2].Error("PASS");`));

t.step_timeout(() => {
assert_array_equals(onerrorCalls, ["frame1"]);
t.done();
}, 4);
});
});
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!doctype html>
<meta charset=utf-8>
<title>window.onerror listener reports the exception in global object of its callback</title>
<link rel=help href="https://dom.spec.whatwg.org/#concept-event-listener-inner-invoke">
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<iframe></iframe>
<iframe></iframe>
<iframe></iframe>
<script>
setup({ allow_uncaught_exception: true });

window.onload = () => {
test(() => {
window.onerrorCalls = [];
window.onerror = () => { onerrorCalls.push("top"); };
frames[0].onerror = new frames[1].Function(`top.onerrorCalls.push("frame0"); throw new parent.frames[2].Error("PASS");`);
frames[1].onerror = () => { onerrorCalls.push("frame1"); };
frames[2].onerror = () => { onerrorCalls.push("frame2"); };

frames[0].dispatchEvent(new ErrorEvent("error", { error: new Error("foo") }));
assert_array_equals(onerrorCalls, ["frame0", "frame1"]);
});
};
</script>
Loading

0 comments on commit 22ecfc9

Please sign in to comment.