diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /js/src/tests/non262/ShadowRealms | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | js/src/tests/non262/ShadowRealms/ccw-2.js | 22 | ||||
-rw-r--r-- | js/src/tests/non262/ShadowRealms/ccw.js | 33 | ||||
-rw-r--r-- | js/src/tests/non262/ShadowRealms/error.js | 102 | ||||
-rw-r--r-- | js/src/tests/non262/ShadowRealms/function-copy-name-and-length-fails-error-realm.js | 27 | ||||
-rw-r--r-- | js/src/tests/non262/ShadowRealms/function-return.js | 73 | ||||
-rw-r--r-- | js/src/tests/non262/ShadowRealms/interrupt-request.js | 16 | ||||
-rw-r--r-- | js/src/tests/non262/ShadowRealms/syntax-error.js | 33 | ||||
-rw-r--r-- | js/src/tests/non262/ShadowRealms/unwrap-wrap-with-proto.js | 12 |
8 files changed, 318 insertions, 0 deletions
diff --git a/js/src/tests/non262/ShadowRealms/ccw-2.js b/js/src/tests/non262/ShadowRealms/ccw-2.js new file mode 100644 index 0000000000..5a60341a65 --- /dev/null +++ b/js/src/tests/non262/ShadowRealms/ccw-2.js @@ -0,0 +1,22 @@ +// |reftest| shell-option(--enable-shadow-realms) skip-if(!xulRuntime.shell) + +var g = newGlobal({newCompartment: true}); + +var sr = new ShadowRealm(); + +var f = sr.evaluate(` + var wrappedCCW; + (f => { wrappedCCW = f; }); +`); + +f(g.evaluate(`x => x()`)); + +var h = sr.evaluate(` + // Pass an object from the ShadowRealm's compartment to the CCW function. + wrappedCCW(() => { return "ok"; }) +`); + +assertEq(h, "ok"); + +if (typeof reportCompare === 'function') + reportCompare(true, true); diff --git a/js/src/tests/non262/ShadowRealms/ccw.js b/js/src/tests/non262/ShadowRealms/ccw.js new file mode 100644 index 0000000000..7596f15823 --- /dev/null +++ b/js/src/tests/non262/ShadowRealms/ccw.js @@ -0,0 +1,33 @@ +// |reftest| shell-option(--enable-shadow-realms) skip-if(!xulRuntime.shell) + +var g = newGlobal({ newCompartment: true }); + +var sr = g.evaluate(`new ShadowRealm()`); + + +// sr should be a CCW to a ShadowRealm. +ShadowRealm.prototype.evaluate.call(sr, "var x = 10"); +assertEq(sr.evaluate("x"), 10); + +// wrappedf should *not* be a CCW, because we're using this realm's ShadowRealm.prototype.evaluate, +// and so the active realm when invoking will be this current realm. +// +// However, the target function (wrappedf's f) comes from another compartment, and will have to be a CCW. +var wrappedf = ShadowRealm.prototype.evaluate.call(sr, "function f() { return 10; }; f"); +assertEq(wrappedf(), 10); + +var evaluate_from_other_realm = g.evaluate('ShadowRealm.prototype.evaluate'); + +// wrappedb should be a CCW, since the callee of the .call comes from the other +// compartment. +var wrappedb = evaluate_from_other_realm.call(sr, "function b() { return 12; }; b"); +assertEq(wrappedb(), 12); + +nukeAllCCWs() +// This throws, but the dead object message is lost and replaced with the wrapped function +// object message. +assertThrowsInstanceOf(() => wrappedf(), TypeError); +assertThrowsInstanceOf(() => wrappedb(), TypeError); + +if (typeof reportCompare === 'function') + reportCompare(true, true);
\ No newline at end of file diff --git a/js/src/tests/non262/ShadowRealms/error.js b/js/src/tests/non262/ShadowRealms/error.js new file mode 100644 index 0000000000..0d0a559b28 --- /dev/null +++ b/js/src/tests/non262/ShadowRealms/error.js @@ -0,0 +1,102 @@ +// |reftest| shell-option(--enable-shadow-realms) skip-if(!xulRuntime.shell) + +let sr = new ShadowRealm(); + +try { + sr.evaluate("throw new Error('hi')"); + assertEq(true, false, "Should have thrown"); +} catch (e) { + assertEq(e instanceof TypeError, true, "Correct type of error") + assertEq(/Error: hi/.test(e.message), true, "Should have included information from thrown error"); +} + +try { + sr.evaluate("throw new Error('∂å∂')"); + assertEq(true, false, "Should have thrown"); +} catch (e) { + assertEq(e instanceof TypeError, true, "Correct type of error") + assertEq(/Error: ∂å∂/.test(e.message), true, "Should have included information from thrown error, UTF-8 Pass through."); +} + +try { + sr.evaluate("throw {name: 'Hello', message: 'goodbye'}"); + assertEq(true, false, "Should have thrown"); +} catch (e) { + assertEq(e instanceof TypeError, true, "Correct type of error") + assertEq(/uncaught exception: Object/.test(e.message), true, "Should get generic fillin message, non-string"); +} + +try { + sr.evaluate("throw {name: 10, message: 11}"); + assertEq(true, false, "Should have thrown"); +} catch (e) { + assertEq(e instanceof TypeError, true, "Correct type of error") + assertEq(/uncaught exception: Object/.test(e.message), true, "Should get generic fillin message, non-string"); +} + + +try { + sr.evaluate("throw { get name() { return 'holy'; }, get message() { return 'smokes' } }"); + assertEq(true, false, "Should have thrown"); +} catch (e) { + assertEq(e instanceof TypeError, true, "Correct type of error") + assertEq(/uncaught exception: Object/.test(e.message), true, "Should get generic error message, getters"); +} + +// Wrapped Functions +try { + var wrapped = sr.evaluate("() => { throw new Error('hi') }"); + assertEq(!!wrapped, true, "Wrapped created"); + wrapped(); + assertEq(true, false, "Should have thrown"); +} catch (e) { + assertEq(e instanceof TypeError, true, "Correct type of error") + assertEq(/Error: hi/.test(e.message), true, "Should have included information from thrown error"); +} + +try { + var wrapped = sr.evaluate("() => { throw new Error('∂å∂') } "); + assertEq(!!wrapped, true, "Wrapped created"); + wrapped(); + assertEq(true, false, "Should have thrown"); +} catch (e) { + assertEq(e instanceof TypeError, true, "Correct type of error") + assertEq(/Error: ∂å∂/.test(e.message), true, "Should have included information from thrown error, UTF-8 Pass through."); +} + +try { + var wrapped = sr.evaluate("() => { throw {name: 'Hello', message: 'goodbye'} } "); + assertEq(!!wrapped, true, "Wrapped created"); + wrapped(); + assertEq(true, false, "Should have thrown"); +} catch (e) { + assertEq(e instanceof TypeError, true, "Correct type of error") + assertEq(/uncaught exception: Object/.test(e.message), true, "Should get generic error message"); +} + +try { + var wrapped = sr.evaluate("() => { throw {name: 10, message: 11} } "); + assertEq(!!wrapped, true, "Wrapped created"); + wrapped(); + assertEq(true, false, "Should have thrown"); +} catch (e) { + assertEq(e instanceof TypeError, true, "Correct type of error") + print(e.message) + assertEq(/uncaught exception: Object/.test(e.message), true, "Should get generic error message"); +} + + +try { + var wrapped = sr.evaluate("() => { throw { get name() { return 'holy'; }, get message() { return 'smokes' } } } "); + assertEq(!!wrapped, true, "Wrapped created"); + wrapped(); + assertEq(true, false, "Should have thrown"); +} catch (e) { + assertEq(e instanceof TypeError, true, "Correct type of error") + assertEq(/uncaught exception: Object/.test(e.message), true, "Should get generic error message"); +} + + + +if (typeof reportCompare === 'function') + reportCompare(true, true);
\ No newline at end of file diff --git a/js/src/tests/non262/ShadowRealms/function-copy-name-and-length-fails-error-realm.js b/js/src/tests/non262/ShadowRealms/function-copy-name-and-length-fails-error-realm.js new file mode 100644 index 0000000000..23040c9fb3 --- /dev/null +++ b/js/src/tests/non262/ShadowRealms/function-copy-name-and-length-fails-error-realm.js @@ -0,0 +1,27 @@ +// |reftest| shell-option(--enable-shadow-realms) skip-if(!xulRuntime.shell) + +var sr = new ShadowRealm(); + +var id = sr.evaluate(`x => x()`); + +// |id| is a Function from the current realm and _not_ from ShadowRealm. +assertEq(id instanceof Function, true); + +function f() { + return 1; +} + +// Smoke test: Ensure calling |f| through the ShadowRealm works correctly. +assertEq(id(f), 1); + +// Add an accessor for "name" which throws. This will lead to throwing an +// exception in CopyNameAndLength. The thrown exception should be from the +// realm of |id|, i.e. the current realm. +Object.defineProperty(f, "name", { + get() { throw new Error; } +}); + +assertThrowsInstanceOf(() => id(f), TypeError); + +if (typeof reportCompare === 'function') + reportCompare(true, true); diff --git a/js/src/tests/non262/ShadowRealms/function-return.js b/js/src/tests/non262/ShadowRealms/function-return.js new file mode 100644 index 0000000000..d0853bcbb3 --- /dev/null +++ b/js/src/tests/non262/ShadowRealms/function-return.js @@ -0,0 +1,73 @@ +// |reftest| shell-option(--enable-shadow-realms) skip-if(!xulRuntime.shell) + +// The output of Function.prototype.toString must match the |NativeFunction| production. +// https://tc39.es/ecma262/#sec-function.prototype.tostring +// +// NativeFunction : +// function NativeFunctionAccessor? PropertyName[~Yield, ~Await]? ( FormalParameters[~Yield, ~Await] ) { [ native code ] } +// +// NativeFunctionAccessor : +// get +// set + +function assertMatchesNativeFunction(f) { + var source = f.toString(); + + // Starts with "function". + assertEq(/^function\b/.test(source), true); + + // Remove the optional |NativeFunctionAccessor| part. + var nativeAccesorRe = /^(?<start>\s*function)(?<accessor>\s+[gs]et)(?<end>\s+[^(].*)$/; + var match = nativeAccesorRe.exec(source); + if (match) { + source = match.groups.start + match.groups.end; + } + + // The body must include the string "[native code". + var closeCurly = source.lastIndexOf("}"); + var openCurly = source.lastIndexOf("{"); + assertEq(openCurly < closeCurly, true); + + var body = source.slice(openCurly + 1, closeCurly); + assertEq(/^\s*\[native code\]\s*$/.test(body), true); + + // Verify |PropertyName| and |FormalParameters| are syntactically correct by parsing the source + // code. But we first need to replace the "[native code]" substring. + source = source.slice(0, openCurly) + "{}"; + + // Also prepend "void" to parse the function source code as a FunctionExpression, because we + // don't necessarily have a name part. + source = "void " + source; + + try { + Function(source); + } catch { + assertEq(true, false, `${source} doesn't match NativeFunction`); + } +} + +let sr = new ShadowRealm(); +var f = sr.evaluate("function f() { }; f"); + +assertMatchesNativeFunction(f); + +f.name = "koala" +assertMatchesNativeFunction(f); + +Object.defineProperty(f, "name", { writable: true, value: "koala" }); +assertMatchesNativeFunction(f); + +f.name = "panda" +assertMatchesNativeFunction(f); + +f.name = "has whitespace, therefore shouldn't match the PropertyName production"; +assertMatchesNativeFunction(f); + +f.name = 123; +assertMatchesNativeFunction(f); + +Object.defineProperty(f, "name", { get() { throw new Error("unexpected side-effect"); } }); +assertMatchesNativeFunction(f); + +if (typeof reportCompare === 'function') + reportCompare(true, true); diff --git a/js/src/tests/non262/ShadowRealms/interrupt-request.js b/js/src/tests/non262/ShadowRealms/interrupt-request.js new file mode 100644 index 0000000000..160a861135 --- /dev/null +++ b/js/src/tests/non262/ShadowRealms/interrupt-request.js @@ -0,0 +1,16 @@ +// |reftest| shell-option(--enable-shadow-realms) skip-if(!xulRuntime.shell) + +// Request interrupt from shadow realm evaluation. + +expectExitCode(6); + +new ShadowRealm().evaluate(` + (interruptIf => { + interruptIf(true); + + for (;;) {} // Wait for interrupt. + }); +`)(interruptIf); + +if (typeof reportCompare === 'function') + reportCompare(true, true); diff --git a/js/src/tests/non262/ShadowRealms/syntax-error.js b/js/src/tests/non262/ShadowRealms/syntax-error.js new file mode 100644 index 0000000000..8cae199f50 --- /dev/null +++ b/js/src/tests/non262/ShadowRealms/syntax-error.js @@ -0,0 +1,33 @@ +// |reftest| shell-option(--enable-shadow-realms) skip-if(!xulRuntime.shell) + +let sr = new ShadowRealm(); + +try { + sr.evaluate("var x /"); + assertEq(true, false, "Should have thrown"); +} catch (e) { + assertEq(e instanceof SyntaxError, true, "Same Global Error") + assertEq(/unterminated regular expression literal/.test(e.message), true, "Should have reported a sensible error message"); +} + +try { + sr.evaluate("var x ="); + assertEq(true, false, "Should have thrown"); +} catch (e) { + assertEq(e instanceof SyntaxError, true, "Same Global Error") + assertEq(/expected expression/.test(e.message), true, "Should have reported a sensible error message"); +} + + +try { + sr.evaluate("#x in this"); + assertEq(true, false, "Should have thrown"); +} catch (e) { + assertEq(e instanceof SyntaxError, true, "Same Global Error") + assertEq(/reference to undeclared private field or method/.test(e.message), true, "Should have reported a sensible error message"); +} + + + +if (typeof reportCompare === 'function') + reportCompare(true, true);
\ No newline at end of file diff --git a/js/src/tests/non262/ShadowRealms/unwrap-wrap-with-proto.js b/js/src/tests/non262/ShadowRealms/unwrap-wrap-with-proto.js new file mode 100644 index 0000000000..f4e07e67b5 --- /dev/null +++ b/js/src/tests/non262/ShadowRealms/unwrap-wrap-with-proto.js @@ -0,0 +1,12 @@ +// |reftest| shell-option(--enable-shadow-realms) skip-if(!xulRuntime.shell) + +var sr = new ShadowRealm(); + +var w = wrapWithProto(sr, null); + +var r = ShadowRealm.prototype.evaluate.call(w, `"ok"`); + +assertEq(r, "ok"); + +if (typeof reportCompare === 'function') + reportCompare(true, true); |