summaryrefslogtreecommitdiffstats
path: root/js/src/tests/non262/PrivateName
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /js/src/tests/non262/PrivateName
parentInitial commit. (diff)
downloadfirefox-esr-upstream.tar.xz
firefox-esr-upstream.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--js/src/tests/non262/PrivateName/browser.js0
-rw-r--r--js/src/tests/non262/PrivateName/constructor-args.js23
-rw-r--r--js/src/tests/non262/PrivateName/error-locations.js34
-rw-r--r--js/src/tests/non262/PrivateName/error-outside-class.js13
-rw-r--r--js/src/tests/non262/PrivateName/home-object-when-preceded-by-computed-key.js34
-rw-r--r--js/src/tests/non262/PrivateName/illegal-delete.js94
-rw-r--r--js/src/tests/non262/PrivateName/illegal-in-class-context.js32
-rw-r--r--js/src/tests/non262/PrivateName/illegal-in-identifier-context.js45
-rw-r--r--js/src/tests/non262/PrivateName/illegal-in-object-context.js14
-rw-r--r--js/src/tests/non262/PrivateName/lexical-presence.js55
-rw-r--r--js/src/tests/non262/PrivateName/modify-non-extensible.js75
-rw-r--r--js/src/tests/non262/PrivateName/names.js30
-rw-r--r--js/src/tests/non262/PrivateName/nested-class-name-used.js32
-rw-r--r--js/src/tests/non262/PrivateName/not-iterable.js39
-rw-r--r--js/src/tests/non262/PrivateName/parse-utf8-non-ascii-identifier.js22
-rw-r--r--js/src/tests/non262/PrivateName/prototype-proxy.js32
-rw-r--r--js/src/tests/non262/PrivateName/proxy-1.js21
-rw-r--r--js/src/tests/non262/PrivateName/proxy-ccw.js66
-rw-r--r--js/src/tests/non262/PrivateName/proxy-init-set.js74
-rw-r--r--js/src/tests/non262/PrivateName/read-private-eval.js13
-rw-r--r--js/src/tests/non262/PrivateName/shell.js0
-rw-r--r--js/src/tests/non262/PrivateName/unicode-names.js11
22 files changed, 759 insertions, 0 deletions
diff --git a/js/src/tests/non262/PrivateName/browser.js b/js/src/tests/non262/PrivateName/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/PrivateName/browser.js
diff --git a/js/src/tests/non262/PrivateName/constructor-args.js b/js/src/tests/non262/PrivateName/constructor-args.js
new file mode 100644
index 0000000000..970d809921
--- /dev/null
+++ b/js/src/tests/non262/PrivateName/constructor-args.js
@@ -0,0 +1,23 @@
+class A {
+ #x = "hello";
+ constructor(o = this.#x) {
+ this.value = o;
+ }
+};
+
+var a = new A;
+assertEq(a.value, "hello");
+
+
+class B extends A {
+ constructor() {
+ // Cannot access 'this' until super() called.
+ super();
+ assertEq("value" in this, true);
+ assertEq(this.value, "hello");
+ }
+}
+
+var b = new B;
+
+if (typeof reportCompare === 'function') reportCompare(0, 0);
diff --git a/js/src/tests/non262/PrivateName/error-locations.js b/js/src/tests/non262/PrivateName/error-locations.js
new file mode 100644
index 0000000000..0536b5a1b2
--- /dev/null
+++ b/js/src/tests/non262/PrivateName/error-locations.js
@@ -0,0 +1,34 @@
+// |reftest|
+function assertLineAndColumn(str, line, column) {
+ try {
+ eval(str);
+ throw 'didn\'t syntaxerror, bad.'
+ } catch (e) {
+ assertEq(e instanceof SyntaxError, true);
+ assertEq(e.lineNumber, line);
+ assertEq(e.columnNumber, column);
+ }
+}
+
+assertLineAndColumn(`class A { g() { return this.#x; }}`, 1, 28);
+// Make sure we're reporting the first error, if there are multiple, in class
+// exit context;
+assertLineAndColumn(
+ `class A { g() { return this.#x; } y() { return this.#z + this.#y; } }`,
+ 1, 28);
+assertLineAndColumn(`this.#x`, 1, 5);
+// Make sure we're reporting the first error, if there are multiple, in
+// non-class context;
+assertLineAndColumn(`this.#x; this.#y; this.#z`, 1, 5);
+
+assertLineAndColumn(
+ `class A {
+g() { return this.#x; }}`,
+ 2, 18);
+assertLineAndColumn(
+ `class A {
+
+g() { return this.#x; } y() { return this.#y; }}`,
+ 3, 18);
+
+if (typeof reportCompare === 'function') reportCompare(0, 0);
diff --git a/js/src/tests/non262/PrivateName/error-outside-class.js b/js/src/tests/non262/PrivateName/error-outside-class.js
new file mode 100644
index 0000000000..8ddb380872
--- /dev/null
+++ b/js/src/tests/non262/PrivateName/error-outside-class.js
@@ -0,0 +1,13 @@
+
+// Can't reference a private field without an object
+assertThrowsInstanceOf(() => eval('#x'), SyntaxError);
+
+// Can't reference a private field without an enclosing class
+assertThrowsInstanceOf(() => eval('this.#x'), SyntaxError);
+
+// Can't reference a private field in a random function outside a class context
+assertThrowsInstanceOf(
+ () => eval('function foo() { return this.#x'), SyntaxError);
+
+
+if (typeof reportCompare === 'function') reportCompare(0, 0);
diff --git a/js/src/tests/non262/PrivateName/home-object-when-preceded-by-computed-key.js b/js/src/tests/non262/PrivateName/home-object-when-preceded-by-computed-key.js
new file mode 100644
index 0000000000..ef53a1304b
--- /dev/null
+++ b/js/src/tests/non262/PrivateName/home-object-when-preceded-by-computed-key.js
@@ -0,0 +1,34 @@
+class Base {
+ m() { return "pass"; }
+ static m() { return "fail"; }
+}
+
+var key = {
+ toString() {
+ return "computed";
+ }
+};
+
+let obj1 = new class extends Base {
+ [key]() {}
+
+ // Private method with a directly preceding method using a computed key led
+ // to assigning the wrong home object.
+ #m() { return super.m(); }
+ m() { return this.#m(); }
+};
+
+assertEq(obj1.m(), "pass");
+
+let obj2 = new class extends Base {
+ // Same test as above, but this time preceded by a static method.
+ static [key]() {}
+
+ #m() { return super.m(); }
+ m() { return this.#m(); }
+};
+
+assertEq(obj2.m(), "pass");
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/PrivateName/illegal-delete.js b/js/src/tests/non262/PrivateName/illegal-delete.js
new file mode 100644
index 0000000000..464b7dd685
--- /dev/null
+++ b/js/src/tests/non262/PrivateName/illegal-delete.js
@@ -0,0 +1,94 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs newGlobal()
+
+class A {
+ #x = {a: 1};
+ b = null;
+ es(s) {
+ eval(s);
+ }
+}
+
+var a = new A;
+a.b = new A;
+
+assertThrowsInstanceOf(() => a.es('delete this.#x'), SyntaxError);
+assertThrowsInstanceOf(() => a.es('delete (this.#x)'), SyntaxError);
+assertThrowsInstanceOf(() => a.es('delete this?.#x'), SyntaxError);
+assertThrowsInstanceOf(() => a.es('delete this?.b.#x'), SyntaxError);
+// Should be OK
+a.es('delete (0, this.#x.a)')
+a.es('delete this?.b.#x.a')
+
+
+// Make sure the above works in a different context, with emphasis on
+// lazy/syntax parsing.
+function eval_and_report(str) {
+ var classTest = `
+ class B {
+ #x = {a: 1};
+ b = null;
+ test() {
+ ${str};
+ }
+ }
+ var b = new B;
+ b.b = new B;
+ b.test();
+ `;
+
+ var str = `
+ function f(run) {
+ if (run) {
+ ${classTest}
+ }
+ }
+ f(run)`;
+
+
+ var throws = [];
+ // Evalutate in a new global; has the advantage that it makes successes
+ // idempotent.
+ var g = newGlobal();
+ g.run = false;
+
+ try {
+ // The idea is that this is a full parse
+ evaluate(classTest, {global: g});
+ } catch (e) {
+ throws.push(e);
+ }
+
+ try {
+ // The idea is this is a lazy parse; however, fields currently
+ // disable lazy parsing, so right now
+ evaluate(str, {global: g});
+ } catch (e) {
+ throws.push(e);
+ }
+
+ return throws;
+}
+
+function assertSyntaxError(str) {
+ var exceptions = eval_and_report(str);
+ assertEq(exceptions.length, 2);
+ for (var e of exceptions) {
+ assertEq(/SyntaxError/.test(e.name), true);
+ }
+}
+
+function assertNoSyntaxError(str) {
+ var exceptions = eval_and_report(str);
+ assertEq(exceptions.length, 0);
+}
+
+assertSyntaxError('delete this.#x');
+assertSyntaxError('delete (this.#x)');
+assertSyntaxError('delete this?.#x');
+assertSyntaxError('delete this?.b.#x');
+// Should be OK
+assertNoSyntaxError('delete (0, this.#x.a)')
+assertNoSyntaxError('delete this?.b.#x.a')
+
+
+if (typeof reportCompare === 'function') reportCompare(0, 0);
diff --git a/js/src/tests/non262/PrivateName/illegal-in-class-context.js b/js/src/tests/non262/PrivateName/illegal-in-class-context.js
new file mode 100644
index 0000000000..85b34563ec
--- /dev/null
+++ b/js/src/tests/non262/PrivateName/illegal-in-class-context.js
@@ -0,0 +1,32 @@
+// |reftest| skip-if(!xulRuntime.shell)
+
+assertThrowsInstanceOf(() => eval(`class A { #x; #x; }`), SyntaxError);
+
+// No computed private fields
+assertThrowsInstanceOf(
+ () => eval(`var x = "foo"; class A { #[x] = 20; }`), SyntaxError);
+
+function assertThrowsWithMessage(f, msg) {
+ var fullmsg;
+ try {
+ f();
+ } catch (exc) {
+ if (exc.message.normalize() === msg.normalize())
+ return;
+
+ fullmsg = `Assertion failed: expected message '${msg}', got '${exc.message}'`;
+ }
+
+ if (fullmsg === undefined)
+ fullmsg = `Assertion failed: expected exception, no exception thrown`;
+
+ throw new Error(fullmsg);
+}
+
+assertThrowsWithMessage(() => eval(`class A { #x; h(o) { return !#x; }}`),
+ "invalid use of private name in unary expression without object reference");
+assertThrowsWithMessage(() => eval(`class A { #x; h(o) { return 1 + #x in o; }}`),
+ "invalid use of private name due to operator precedence");
+
+
+if (typeof reportCompare === 'function') reportCompare(0, 0);
diff --git a/js/src/tests/non262/PrivateName/illegal-in-identifier-context.js b/js/src/tests/non262/PrivateName/illegal-in-identifier-context.js
new file mode 100644
index 0000000000..e7e232bf69
--- /dev/null
+++ b/js/src/tests/non262/PrivateName/illegal-in-identifier-context.js
@@ -0,0 +1,45 @@
+// |reftest| skip-if(!xulRuntime.shell)
+
+// Private names can't appear in contexts where plain identifiers are expected.
+
+// Private names as binding identifiers.
+assertThrowsInstanceOf(() => eval(`var #a;`), SyntaxError);
+assertThrowsInstanceOf(() => eval(`let #a;`), SyntaxError);
+assertThrowsInstanceOf(() => eval(`const #a = 0;`), SyntaxError);
+assertThrowsInstanceOf(() => eval(`function #a(){}`), SyntaxError);
+assertThrowsInstanceOf(() => eval(`function f(#a){}`), SyntaxError);
+
+// With escape sequences (leading and non-leading case).
+assertThrowsInstanceOf(() => eval(String.raw`var #\u0061;`), SyntaxError);
+assertThrowsInstanceOf(() => eval(String.raw`var #a\u0061;`), SyntaxError);
+assertThrowsInstanceOf(() => eval(String.raw`let #\u0061;`), SyntaxError);
+assertThrowsInstanceOf(() => eval(String.raw`let #a\u0061;`), SyntaxError);
+assertThrowsInstanceOf(() => eval(String.raw`const #\u0061 = 0;`), SyntaxError);
+assertThrowsInstanceOf(() => eval(String.raw`const #a\u0061 = 0;`), SyntaxError);
+assertThrowsInstanceOf(() => eval(String.raw`function #\u0061(){}`), SyntaxError);
+assertThrowsInstanceOf(() => eval(String.raw`function #a\u0061(){}`), SyntaxError);
+assertThrowsInstanceOf(() => eval(String.raw`function f(#\u0061){}`), SyntaxError);
+assertThrowsInstanceOf(() => eval(String.raw`function f(#a\u0061){}`), SyntaxError);
+
+
+// Private names as label identifiers.
+assertThrowsInstanceOf(() => eval(`#a: ;`), SyntaxError);
+
+// With escape sequences (leading and non-leading case).
+assertThrowsInstanceOf(() => eval(String.raw`#\u0061: ;`), SyntaxError);
+assertThrowsInstanceOf(() => eval(String.raw`#a\u0061: ;`), SyntaxError);
+
+
+// Private names as identifier references.
+assertThrowsInstanceOf(() => eval(`#a = 0;`), SyntaxError);
+assertThrowsInstanceOf(() => eval(`typeof #a;`), SyntaxError);
+
+// With escape sequences (leading and non-leading case).
+assertThrowsInstanceOf(() => eval(String.raw`#\u0061 = 0;`), SyntaxError);
+assertThrowsInstanceOf(() => eval(String.raw`#a\u0061 = 0;`), SyntaxError);
+assertThrowsInstanceOf(() => eval(String.raw`typeof #\u0061;`), SyntaxError);
+assertThrowsInstanceOf(() => eval(String.raw`typeof #a\u0061;`), SyntaxError);
+
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/PrivateName/illegal-in-object-context.js b/js/src/tests/non262/PrivateName/illegal-in-object-context.js
new file mode 100644
index 0000000000..9cc1488376
--- /dev/null
+++ b/js/src/tests/non262/PrivateName/illegal-in-object-context.js
@@ -0,0 +1,14 @@
+// |reftest| skip-if(!xulRuntime.shell)
+
+// Private names aren't valid in object literals.
+
+assertThrowsInstanceOf(() => eval(`var o = {#a: 0};`), SyntaxError);
+assertThrowsInstanceOf(() => eval(`var o = {#a};`), SyntaxError);
+assertThrowsInstanceOf(() => eval(`var o = {#a(){}};`), SyntaxError);
+assertThrowsInstanceOf(() => eval(`var o = {get #a(){}};`), SyntaxError);
+assertThrowsInstanceOf(() => eval(`var o = {set #a(v){}};`), SyntaxError);
+assertThrowsInstanceOf(() => eval(`var o = {*#a(v){}};`), SyntaxError);
+assertThrowsInstanceOf(() => eval(`var o = {async #a(v){}};`), SyntaxError);
+assertThrowsInstanceOf(() => eval(`var o = {async *#a(v){}};`), SyntaxError);
+
+if (typeof reportCompare === 'function') reportCompare(0, 0);
diff --git a/js/src/tests/non262/PrivateName/lexical-presence.js b/js/src/tests/non262/PrivateName/lexical-presence.js
new file mode 100644
index 0000000000..ce8588a0f1
--- /dev/null
+++ b/js/src/tests/non262/PrivateName/lexical-presence.js
@@ -0,0 +1,55 @@
+// |reftest|
+
+// Verify that private fields are enabled.
+class A {
+ #x;
+};
+
+function assertThrowsSyntaxError(str) {
+ assertThrowsInstanceOf(() => eval(str), SyntaxError); // Direct Eval
+ assertThrowsInstanceOf(() => (1, eval)(str), SyntaxError); // Indirect Eval
+ assertThrowsInstanceOf(() => Function(str), SyntaxError); // Function
+}
+
+assertThrowsSyntaxError(`
+ class B {
+ g() {
+ return this.#x;
+ }
+ };
+`);
+
+assertThrowsSyntaxError(`
+with (new class A { #x; }) {
+ class B {
+ #y;
+ constructor() { return this.#x; }
+ }
+ }
+`);
+
+// Make sure we don't create a generic binding for #x.
+with (new class {
+ #x = 12;
+}) {
+ assertEq('#x' in this, false);
+}
+
+// Try to fetch a non-existing field using different
+// compilation contexts
+function assertNonExisting(fetchCode) {
+ source = `var X = class {
+ b() {
+ ${fetchCode}
+ }
+ }
+ var a = new X;
+ a.b()`
+ assertThrowsInstanceOf(() => eval(source), SyntaxError);
+}
+
+assertNonExisting(`return eval("this.#x")"`);
+assertNonExisting(`return (1,eval)("this.#x")`);
+assertNonExisting(`var f = Function("this.#x"); return f();`);
+
+if (typeof reportCompare === 'function') reportCompare(0, 0); \ No newline at end of file
diff --git a/js/src/tests/non262/PrivateName/modify-non-extensible.js b/js/src/tests/non262/PrivateName/modify-non-extensible.js
new file mode 100644
index 0000000000..7e9af31895
--- /dev/null
+++ b/js/src/tests/non262/PrivateName/modify-non-extensible.js
@@ -0,0 +1,75 @@
+// |reftest|
+
+// Returns the argument in the constructor to allow stamping private fields into
+// arbitrary objects.
+class OverrideBase {
+ constructor(o) {
+ return o;
+ }
+};
+
+class A extends OverrideBase {
+ #a = 1;
+ g() {
+ return this.#a
+ }
+
+ static gs(o) {
+ return o.#a;
+ }
+ static inca(obj) {
+ obj.#a++;
+ }
+}
+
+var obj = {};
+Object.seal(obj);
+new A(obj); // Add #a to obj, but not g.
+assertEq('g' in obj, false);
+assertEq(A.gs(obj), 1);
+A.inca(obj);
+assertEq(A.gs(obj), 2);
+
+// Ensure that the object remains non-extensible
+obj.h = 'hi'
+assertEq('h' in obj, false);
+
+
+Object.freeze(obj);
+A.inca(obj); // Despite being frozen, private names are modifiable.
+assertEq(A.gs(obj), 3);
+assertEq(Object.isFrozen(obj), true);
+
+var proxy = new Proxy({}, {});
+assertEq(Object.isFrozen(proxy), false);
+
+new A(proxy);
+assertEq(A.gs(proxy), 1);
+
+// Note: this doesn't exercise the non-native object
+// path in TestIntegrityLevel like you might expect.
+//
+// For that see below.
+Object.freeze(proxy);
+assertEq(Object.isFrozen(proxy), true);
+
+A.inca(proxy);
+assertEq(A.gs(proxy), 2)
+
+var target = { a: 10 };
+Object.freeze(target);
+new A(target);
+assertEq(Object.isFrozen(target), true)
+
+var getOwnKeys = [];
+var proxy = new Proxy(target, {
+ getOwnPropertyDescriptor: function (target, key) {
+ getOwnKeys.push(key);
+ return Reflect.getOwnPropertyDescriptor(target, key);
+ },
+});
+
+Object.isFrozen(proxy);
+assertEq(getOwnKeys.length, 1);
+
+if (typeof reportCompare === 'function') reportCompare(0, 0);
diff --git a/js/src/tests/non262/PrivateName/names.js b/js/src/tests/non262/PrivateName/names.js
new file mode 100644
index 0000000000..39d5128b2e
--- /dev/null
+++ b/js/src/tests/non262/PrivateName/names.js
@@ -0,0 +1,30 @@
+// |reftest|
+var C = class {
+ static #field = () => 'Test262';
+ static field = () => 'Test262';
+ #instance = () => 'Test262';
+ instance = () => 'Test262';
+
+ static accessPrivateField() {
+ return this.#field;
+ }
+
+ accessPrivateInstanceField() {
+ return this.#instance;
+ }
+
+ static accessField() {
+ return this.field;
+ }
+
+ accessInstanceField() {
+ return this.instance;
+ }
+}
+assertEq(C.accessPrivateField().name, '#field')
+assertEq(C.accessField().name, 'field');
+var c = new C;
+assertEq(c.accessPrivateInstanceField().name, '#instance');
+assertEq(c.accessInstanceField().name, 'instance');
+
+if (typeof reportCompare === 'function') reportCompare(0, 0);
diff --git a/js/src/tests/non262/PrivateName/nested-class-name-used.js b/js/src/tests/non262/PrivateName/nested-class-name-used.js
new file mode 100644
index 0000000000..416a1aff36
--- /dev/null
+++ b/js/src/tests/non262/PrivateName/nested-class-name-used.js
@@ -0,0 +1,32 @@
+// |reftest|
+// AllPrivateIdentifiersValid uses only lexical string names, not
+// the dynamic private names; which means the below is not a syntax
+// error but is instead a TypeError on access.
+
+class A {
+ #x = 10;
+ f() {
+ class B {
+ g() {
+ return this.#x; // note: #x isn't declared in this class, but
+ // the enclosing.
+ }
+ };
+ this.y = new B;
+ }
+ constructor() {
+ this.f();
+ }
+ g() {
+ return this.y.g();
+ }
+};
+
+a = new A;
+try {
+ a.g();
+} catch (e) {
+ assertEq(e instanceof TypeError, true);
+}
+
+if (typeof reportCompare === 'function') reportCompare(0, 0); \ No newline at end of file
diff --git a/js/src/tests/non262/PrivateName/not-iterable.js b/js/src/tests/non262/PrivateName/not-iterable.js
new file mode 100644
index 0000000000..0e9a76f569
--- /dev/null
+++ b/js/src/tests/non262/PrivateName/not-iterable.js
@@ -0,0 +1,39 @@
+// |reftest|
+//
+// Ensure PrivateNames aren't iterable.
+
+class O {
+ #x = 123;
+ gx() {
+ return this.#x;
+ }
+}
+var o = new O;
+
+assertEq(o.gx(), 123);
+
+assertEq(Object.keys(o).length, 0);
+assertEq(Object.getOwnPropertyNames(o).length, 0);
+assertEq(Object.getOwnPropertySymbols(o).length, 0);
+assertEq(Reflect.ownKeys(o).length, 0);
+
+var forIn = [];
+for (var pk in o) {
+ forIn.push(pk);
+}
+assertEq(forIn.length, 0);
+
+// Proxy case
+var proxy = new Proxy(o, {});
+assertEq(Object.keys(proxy).length, 0);
+assertEq(Object.getOwnPropertyNames(proxy).length, 0);
+assertEq(Object.getOwnPropertySymbols(proxy).length, 0);
+assertEq(Reflect.ownKeys(proxy).length, 0);
+
+for (var pk in proxy) {
+ forIn.push(pk);
+}
+assertEq(forIn.length, 0);
+
+if (typeof reportCompare === 'function')
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/PrivateName/parse-utf8-non-ascii-identifier.js b/js/src/tests/non262/PrivateName/parse-utf8-non-ascii-identifier.js
new file mode 100644
index 0000000000..7f4b15f2dc
--- /dev/null
+++ b/js/src/tests/non262/PrivateName/parse-utf8-non-ascii-identifier.js
@@ -0,0 +1,22 @@
+// Test that non-ASCII identifier names are correctly parsed in the Utf-8 parser.
+
+// Utf-8 encoding for U+05EF is (0xD7 0xAF), the first code unit isn't a valid
+// Ascii ID_START code unit.
+class NonAscii {
+ // U+05EF HEBREW YOD TRIANGLE
+ #ׯ;
+}
+
+// Also check using Unicode escapes works.
+class NonAsciiUnicodeEscape1 {
+ // U+05EF HEBREW YOD TRIANGLE
+ #\u05ef;
+}
+
+class NonAsciiUnicodeEscape2 {
+ // U+05EF HEBREW YOD TRIANGLE
+ #\u{5ef};
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/PrivateName/prototype-proxy.js b/js/src/tests/non262/PrivateName/prototype-proxy.js
new file mode 100644
index 0000000000..55c8abab13
--- /dev/null
+++ b/js/src/tests/non262/PrivateName/prototype-proxy.js
@@ -0,0 +1,32 @@
+// |reftest| skip-if(!this.hasOwnProperty("wrapWithProto"))
+
+const o0 = {};
+const v2 = new Proxy(o0, o0);
+
+// v8 is a forwarding proxy with "prototype" behaviour;
+// see the comment for mHasPrototype on BaseProxyHandler
+// in Proxy.h.
+//
+// Private Fields don't interact with the hasPrototype
+// behaviour (to minimize the overhead, and since private
+// fields are always own properties).
+const v8 = this.wrapWithProto(v2, {});
+function f9(a10) {
+ return v8;
+}
+class C11 extends f9 {
+ #b = 12;
+ static {
+ const v13 = new this();
+
+ const val = v8.#b; // Get
+ assertEq(val, 12);
+
+ v8.#b = 0; // Set
+ assertEq(v8.#b, 0);
+
+ assertEq(#b in v8, true); // HasOwn.
+ }
+}
+
+if (typeof reportCompare === 'function') reportCompare(0, 0);
diff --git a/js/src/tests/non262/PrivateName/proxy-1.js b/js/src/tests/non262/PrivateName/proxy-1.js
new file mode 100644
index 0000000000..21f8f0ef08
--- /dev/null
+++ b/js/src/tests/non262/PrivateName/proxy-1.js
@@ -0,0 +1,21 @@
+// |reftest|
+
+class A {
+ #x = 10;
+ g() {
+ return this.#x;
+ }
+};
+
+var p = new Proxy(new A, {});
+var completed = false;
+try {
+ p.g();
+ completed = true;
+} catch (e) {
+ assertEq(e instanceof TypeError, true);
+}
+assertEq(completed, false);
+
+
+if (typeof reportCompare === 'function') reportCompare(0, 0);
diff --git a/js/src/tests/non262/PrivateName/proxy-ccw.js b/js/src/tests/non262/PrivateName/proxy-ccw.js
new file mode 100644
index 0000000000..94778489b6
--- /dev/null
+++ b/js/src/tests/non262/PrivateName/proxy-ccw.js
@@ -0,0 +1,66 @@
+// |reftest|
+
+// Validate CCWs and proxies
+class Base {
+ constructor(o) {
+ return o;
+ }
+}
+
+class A extends Base {
+ x1 = 12;
+ #x = 10;
+ static gx(o) {
+ return o.#x;
+ }
+ static sx(o, x) {
+ o.#x = x;
+ }
+ static hasx(o) {
+ try {
+ o.#x;
+ return true;
+ } catch {
+ return false;
+ }
+ }
+}
+
+
+var g = newGlobal({newCompartment: true});
+g.A = A;
+
+// cross_compartment_target is a cross compartment wrapper to an empty object.
+var cross_compartment_target = g.eval('this.x = {}; this.x');
+
+// #x gets stamped into the target of the CCW.
+new A(cross_compartment_target);
+assertEq(A.hasx(cross_compartment_target), true);
+
+// Can we update and read from this compartment?
+assertEq(A.gx(cross_compartment_target), 10);
+var o = {test: 12};
+A.sx(cross_compartment_target, o);
+assertEq(A.gx(cross_compartment_target), o);
+
+// Can we read and update from the other compartment?
+assertEq(g.eval('this.A.gx(this.x)'), o);
+var y = g.eval('this.y = {test: 13}; this.A.sx(this.x, this.y); this.y');
+assertEq(g.eval('this.A.gx(this.x)'), y);
+assertEq(A.gx(cross_compartment_target), y);
+
+
+if (typeof nukeCCW === 'function') {
+ // Nuke the CCW. Now things should throw.
+ nukeCCW(cross_compartment_target);
+ var threw = true;
+ try {
+ A.gx(cross_compartment_target);
+ threw = false;
+ } catch (e) {
+ }
+ assertEq(threw, true);
+}
+
+
+if (typeof reportCompare === 'function') reportCompare(0, 0); \ No newline at end of file
diff --git a/js/src/tests/non262/PrivateName/proxy-init-set.js b/js/src/tests/non262/PrivateName/proxy-init-set.js
new file mode 100644
index 0000000000..bc78f50a09
--- /dev/null
+++ b/js/src/tests/non262/PrivateName/proxy-init-set.js
@@ -0,0 +1,74 @@
+// |reftest|
+// Ensure that the distinction between Proxy Init and Proxy Set holds
+
+function assertThrowsTypeError(f) {
+ var type;
+ try {
+ f();
+ } catch (ex) {
+ type = ex.name;
+ }
+ assertEq(type, 'TypeError');
+}
+
+
+
+var target = {};
+var p1 = new Proxy(target, {});
+var p2 = new Proxy(target, {});
+
+class Base {
+ constructor(o) {
+ return o;
+ }
+}
+
+class A extends Base {
+ #field = 10;
+ static gf(o) {
+ return o.#field;
+ }
+ static sf(o) {
+ o.#field = 15;
+ }
+}
+
+class B extends Base {
+ #field = 25;
+ static gf(o) {
+ return o.#field;
+ }
+ static sf(o) {
+ o.#field = 20;
+ }
+}
+
+// Verify field handling on the proxy we install it on.
+new A(p1);
+assertEq(A.gf(p1), 10);
+A.sf(p1)
+assertEq(A.gf(p1), 15);
+
+// Despite P1 being stamped with A's field, it shouldn't
+// be sufficient to set B's field.
+assertThrowsTypeError(() => B.sf(p1));
+assertThrowsTypeError(() => B.gf(p1));
+assertThrowsTypeError(() => B.sf(p1));
+new B(p1);
+assertEq(B.gf(p1), 25);
+B.sf(p1);
+assertEq(B.gf(p1), 20);
+
+// A's field should't be on the target
+assertThrowsTypeError(() => A.gf(target));
+
+// Can't set the field, doesn't exist
+assertThrowsTypeError(() => A.sf(p2));
+
+// Definitely can't get the field, doesn't exist.
+assertThrowsTypeError(() => A.gf(p2));
+
+// Still should't be on the target.
+assertThrowsTypeError(() => A.gf(target));
+
+if (typeof reportCompare === 'function') reportCompare(0, 0); \ No newline at end of file
diff --git a/js/src/tests/non262/PrivateName/read-private-eval.js b/js/src/tests/non262/PrivateName/read-private-eval.js
new file mode 100644
index 0000000000..2c68e1c5d2
--- /dev/null
+++ b/js/src/tests/non262/PrivateName/read-private-eval.js
@@ -0,0 +1,13 @@
+// |reftest|
+
+class A {
+ #x = 14;
+ g() {
+ return eval('this.#x');
+ }
+}
+
+a = new A;
+assertEq(a.g(), 14);
+
+if (typeof reportCompare === 'function') reportCompare(0, 0); \ No newline at end of file
diff --git a/js/src/tests/non262/PrivateName/shell.js b/js/src/tests/non262/PrivateName/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/PrivateName/shell.js
diff --git a/js/src/tests/non262/PrivateName/unicode-names.js b/js/src/tests/non262/PrivateName/unicode-names.js
new file mode 100644
index 0000000000..ff8d1fa2ff
--- /dev/null
+++ b/js/src/tests/non262/PrivateName/unicode-names.js
@@ -0,0 +1,11 @@
+// |reftest| skip-if(!xulRuntime.shell)
+
+source = `class A {
+ // Ensure this name parses. Failure would be an InternalError: Buffer too
+ // small
+ #℘;
+}`;
+
+Function(source);
+
+if (typeof reportCompare === 'function') reportCompare(0, 0); \ No newline at end of file