summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/decorators
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/jit-test/tests/decorators
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/jit-test/tests/decorators')
-rw-r--r--js/src/jit-test/tests/decorators/accessors.js70
-rw-r--r--js/src/jit-test/tests/decorators/field-decorators.js75
-rw-r--r--js/src/jit-test/tests/decorators/getter-setter-decorators.js64
-rw-r--r--js/src/jit-test/tests/decorators/method-decorators.js86
-rw-r--r--js/src/jit-test/tests/decorators/syntax.js68
5 files changed, 363 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/decorators/accessors.js b/js/src/jit-test/tests/decorators/accessors.js
new file mode 100644
index 0000000000..b96ae25961
--- /dev/null
+++ b/js/src/jit-test/tests/decorators/accessors.js
@@ -0,0 +1,70 @@
+// |jit-test| skip-if: !getBuildConfiguration()['decorators']
+
+load(libdir + "asserts.js");
+
+function assertAccessorDescriptor(object, name) {
+ var desc = Object.getOwnPropertyDescriptor(object, name);
+ assertEq(desc.configurable, true, "The value of `desc.configurable` is `true`");
+ assertEq(desc.enumerable, false, "The value of `desc.enumerable` is `false`");
+ assertEq(typeof desc.get, 'function', "`typeof desc.get` is `'function'`");
+ assertEq(typeof desc.set, 'function', "`typeof desc.set` is `'function'`");
+ assertEq(
+ 'prototype' in desc.get,
+ false,
+ "The result of `'prototype' in desc.get` is `false`"
+ );
+ assertEq(
+ 'prototype' in desc.set,
+ false,
+ "The result of `'prototype' in desc.set` is `false`"
+ );
+}
+
+class C {
+ accessor x;
+}
+
+assertAccessorDescriptor(C.prototype, 'x');
+
+let c = new C();
+assertEq(c.x, undefined, "The value of `c.x` is `undefined` after construction");
+c.x = 2;
+assertEq(c.x, 2, "The value of `c.x` is `2`, after executing `c.x = 2;`");
+
+class D {
+ accessor x = 1;
+}
+
+assertAccessorDescriptor(D.prototype, 'x');
+
+let d = new D();
+assertEq(d.x, 1, "The value of `d.x` is `1` after construction");
+d.x = 2;
+assertEq(d.x, 2, "The value of `d.x` is `2`, after executing `d.x = 2;`");
+
+class E {
+ accessor #x = 1;
+
+ getX() {
+ return this.#x;
+ }
+
+ setX(v) {
+ this.#x = v;
+ }
+}
+
+let e = new E();
+assertEq(e.getX(), 1, "The value of `e.x` is `1` after construction");
+e.setX(2);
+assertEq(e.getX(), 2, "The value of `e.x` is `2`, after executing `e.setX(2);`");
+
+class F {
+ static accessor x = 1;
+}
+
+assertEq(F.x, 1, "The value of `F.x` is `1` after construction");
+F.x = 2;
+assertEq(F.x, 2, "The value of `F.x` is `2`, after executing `F.x = 2;`");
+
+assertAccessorDescriptor(F, 'x');
diff --git a/js/src/jit-test/tests/decorators/field-decorators.js b/js/src/jit-test/tests/decorators/field-decorators.js
new file mode 100644
index 0000000000..3db9da534c
--- /dev/null
+++ b/js/src/jit-test/tests/decorators/field-decorators.js
@@ -0,0 +1,75 @@
+// |jit-test| skip-if: !getBuildConfiguration()['decorators']
+
+load(libdir + "asserts.js");
+
+let dec1Called = false;
+let dec2Called = false;
+
+// This explicitly tests the case where undefined is returned.
+function dec1(value, context) {
+ dec1Called = true;
+ // returns undefined
+}
+
+function dec2(value, context) {
+ dec2Called = true;
+ return (initialValue) => 2;
+}
+
+function dec3(value, context) {
+ return (initialValue) => initialValue*2;
+}
+
+function checkDecoratorContext(kind, isPrivate, isStatic, name) {
+ return (value, context) => {
+ assertEq(value, undefined);
+ assertEq(context.kind, kind);
+ assertEq(typeof context.access, "object");
+ assertEq(context.private, isPrivate);
+ assertEq(context.static, isStatic);
+ assertEq(context.name, name);
+ assertEq(typeof context.addInitializer, "object");
+ }
+}
+
+class C {
+ @dec1 x;
+ @dec1 x2 = 1;
+ @checkDecoratorContext("field", false, false, "x3") x3;
+ @checkDecoratorContext("field", false, true, "x4") static x4;
+ @checkDecoratorContext("field", true, false, "#x5") #x5;
+ @dec2 x6;
+ @dec3 x7 = 1;
+ @dec2 @dec3 x8 = 1;
+ @dec2 static x9;
+ @dec2 #x10;
+ getX10 = () => {
+ return this.#x10;
+ };
+ @dec3 #x11 = 2;
+ getX11 = () => {
+ return this.#x11;
+ };
+ @dec1 42 = 1;
+ @dec2 [43];
+}
+
+
+let c = new C();
+assertEq(dec1Called, true);
+assertEq(c.x2, 1);
+assertEq(dec2Called, true);
+assertEq(c.x6, 2);
+assertEq(c.x7, 2);
+assertEq(c.x8, 4);
+assertEq(c.x9, 2);
+assertEq(c.getX10(), 2);
+assertEq(c.getX11(), 4);
+assertEq(c[42], 1);
+assertEq(c[43], 2);
+
+assertThrowsInstanceOf(() => {
+ class D {
+ @(() => { return "hello!"; }) f(x) { return x; }
+ }
+}, TypeError), "Returning a value other than undefined or a callable throws.";
diff --git a/js/src/jit-test/tests/decorators/getter-setter-decorators.js b/js/src/jit-test/tests/decorators/getter-setter-decorators.js
new file mode 100644
index 0000000000..601e39138d
--- /dev/null
+++ b/js/src/jit-test/tests/decorators/getter-setter-decorators.js
@@ -0,0 +1,64 @@
+// |jit-test| skip-if: !getBuildConfiguration()['decorators']
+
+load(libdir + "asserts.js");
+
+let dec1Called = false;
+
+// This explicitly tests the case where undefined is returned.
+function dec(value, context) {
+ dec1Called = true;
+ // return undefined
+}
+
+function decorate_getter(value, context) {
+ return function() {
+ return 2 * value.call(this);
+ }
+}
+
+function decorate_setter(value, context) {
+ return function(x) {
+ return value.call(this, 2*x);
+ }
+}
+
+function checkDecoratorContext(kind, isPrivate, isStatic, name) {
+ return (value, context) => {
+ assertEq(typeof value.call, "function");
+ assertEq(context.kind, kind);
+ assertEq(typeof context.access, "object");
+ assertEq(context.private, isPrivate);
+ assertEq(context.static, isStatic);
+ assertEq(context.name, name);
+ assertEq(typeof context.addInitializer, "object");
+ }
+}
+
+class C {
+ setter5Value;
+
+ @dec get getter1() { return "unmodified"; }
+ @checkDecoratorContext("getter", false, false, "getter2") get getter2() { }
+ @checkDecoratorContext("getter", false, true, "getter3") static get getter3() { }
+ @checkDecoratorContext("getter", true, false, "#getter4") get #getter4() { }
+ @decorate_getter get getter5() { return 1; }
+
+ @dec set setter1(value) { }
+ @checkDecoratorContext("setter", false, false, "setter2") set setter2(value) { }
+ @checkDecoratorContext("setter", false, true, "setter3") static set setter3(value) { }
+ @checkDecoratorContext("setter", true, false, "#setter4") set #setter4(value) { }
+ @decorate_setter set setter5(value) { this.setter5Value = value; }
+}
+
+let c = new C();
+assertEq(dec1Called, true);
+assertEq(c.getter1, "unmodified");
+assertEq(c.getter5, 2);
+c.setter5 = 1;
+assertEq(c.setter5Value, 2);
+
+assertThrowsInstanceOf(() => {
+ class D {
+ @(() => { return "hello!"; }) get f() { return "unmodified"; }
+ }
+}, TypeError), "Returning a value other than undefined or a callable throws.";
diff --git a/js/src/jit-test/tests/decorators/method-decorators.js b/js/src/jit-test/tests/decorators/method-decorators.js
new file mode 100644
index 0000000000..ddf9b2eb50
--- /dev/null
+++ b/js/src/jit-test/tests/decorators/method-decorators.js
@@ -0,0 +1,86 @@
+// |jit-test| skip-if: !getBuildConfiguration()['decorators']
+
+load(libdir + "asserts.js");
+
+let dec1Called = false;
+
+// This explicitly tests the case where undefined is returned.
+function dec1(value, context) {
+ dec1Called = true;
+ // return undefined
+}
+
+function dec2(value, context) {
+ return (x) => "replaced: " + x;
+}
+
+function dec3(value, context) {
+ return (x) => "decorated: " + value.call(this, x);
+}
+
+function dec4(arg) {
+ return (value, context) => {
+ return (x) => arg + " decorated: " + value.call(this, x);
+ }
+}
+
+let decorators = {
+ "dec4": (value, context) => {
+ return (x) => "decorated: " + x;
+ },
+ "more": {
+ "deeply": {
+ "nested": {
+ "dec5": (value, context) => {
+ return (x) => "decorated: " + x;
+ }
+ }
+ }
+ }
+};
+
+function checkDecoratorContext(kind, isPrivate, isStatic, name) {
+ return (value, context) => {
+ assertEq(typeof value.call, "function");
+ assertEq(context.kind, kind);
+ assertEq(typeof context.access, "object");
+ assertEq(context.private, isPrivate);
+ assertEq(context.static, isStatic);
+ assertEq(context.name, name);
+ assertEq(typeof context.addInitializer, "object");
+ }
+}
+
+class C {
+ @dec1 f1(x) { return "called with: " + x; }
+ @dec2 f2(x) { return "called with: " + x; }
+ @dec1 @dec2 f3(x) { return "called with: " + x; }
+ @dec1 @dec2 @dec3 f4(x) { return "called with: " + x; }
+ @decorators.dec4 f5(x) { return "called with: " + x; }
+ @decorators.more.deeply.nested.dec5 f6(x) { return "called with: " + x; }
+ @(() => { }) f7(x) { return "called with: " + x; }
+ @((value, context) => { return (x) => "decorated: " + x; }) f8(x) { return "called with: " + x; }
+ @dec4("hello!") f9(x) { return "called with: " + x; }
+
+ @checkDecoratorContext("method", false, false, "f10") f10(x) { return x; }
+ @checkDecoratorContext("method", false, true, "f11") static f11(x) { return x; }
+ @checkDecoratorContext("method", true, false, "#f12") #f12(x) { return x; }
+}
+
+let c = new C();
+assertEq(dec1Called, true);
+assertEq(c.f1("value"), "called with: value");
+assertEq(c.f2("value"), "replaced: value");
+assertEq(c.f3("value"), "replaced: value");
+assertEq(c.f4("value"), "decorated: replaced: value");
+assertEq(c.f5("value"), "decorated: value");
+assertEq(c.f6("value"), "decorated: value");
+assertEq(c.f7("value"), "called with: value");
+assertEq(c.f8("value"), "decorated: value");
+assertEq(c.f9("value"), "hello! decorated: called with: value");
+
+assertThrowsInstanceOf(() => {
+ class D {
+ @(() => { return "hello!"; }) f(x) { return x; }
+ }
+}, TypeError), "Returning a value other than undefined or a callable throws.";
diff --git a/js/src/jit-test/tests/decorators/syntax.js b/js/src/jit-test/tests/decorators/syntax.js
new file mode 100644
index 0000000000..7a986d5124
--- /dev/null
+++ b/js/src/jit-test/tests/decorators/syntax.js
@@ -0,0 +1,68 @@
+// |jit-test| skip-if: !getBuildConfiguration()['decorators']
+
+load(libdir + "asserts.js");
+
+Reflect.parse("class c {@dec1 field = false;}");
+Reflect.parse("class c {@dec1 @dec2 @dec3 field = false;}");
+Reflect.parse("class c {@dec1 @dec2 @dec3('a') static field = false;}");
+Reflect.parse("class c {@dec1 method() {};}");
+Reflect.parse("class c {@dec1 @dec2 @dec3 method() {};}");
+Reflect.parse("class c {@dec1 @dec2 @dec3 static method() {};}");
+Reflect.parse("class c {@dec1 @dec2('a') @dec3 method(...args) {};}");
+Reflect.parse("class c {@((a, b, c) => {}) method(a, b) {};}");
+Reflect.parse("class c {@((a, b, c) => {}) @dec2('a', 'b') @dec3 method(a, b) {};}");
+Reflect.parse("@dec1 class c {}");
+Reflect.parse("@dec1 @dec2 @dec3 class c {}");
+Reflect.parse("@dec1('a') @(() => {}) @dec3 class c {}");
+Reflect.parse("@dec1('a') @(() => {}) @dec3 class c {@((a, b, c) => {}) @dec2('a', 'b') @dec3 method(a, b) {};}");
+Reflect.parse("x = @dec class { #x }");
+Reflect.parse("x = (class A { }, @dec class { })");
+Reflect.parse("@dec1 class A extends @dec2 class B extends @dec3 class {} {} {}");
+Reflect.parse("class c {@dec1.dec2.dec3 method() {};}");
+Reflect.parse("class c {@dec1 @dec2.dec3.dec4 @dec5 method() {};}");
+Reflect.parse("class c {@dec1('a') @dec2.dec3.dec4 @dec5 method() {};}");
+Reflect.parse("class c {@dec1('a') @dec2.dec3.dec4('b', 'c') @dec5 method() {};}");
+Reflect.parse("class c {@dec1('a') @dec2.dec3.dec4('b', 'c') @dec5.dec6 method() {};}");
+Reflect.parse("@dec1.dec2 class c {}");
+Reflect.parse("@dec1.dec2 @dec3.dec4 @dec5 class c {}");
+Reflect.parse("@dec1.dec2('a') @(() => {}) @dec4 class c {}");
+Reflect.parse("@dec1.dec2('a') @(() => {}) @dec4 class c {@((a, b, c) => {}) @dec5.dec6('a', 'b') @dec7 method(a, b) {};}");
+Reflect.parse("class c {accessor field = false;}");
+Reflect.parse("class c {static accessor field = false;}");
+Reflect.parse("class c {@dec1 @dec2 accessor field = false;}");
+Reflect.parse("class c {@dec1 @dec2 @dec3 static accessor field = false;}");
+Reflect.parse("let accessor = false;");
+Reflect.parse("class accessor {accessor = false;}");
+Reflect.parse("class c {accessor = false;}");
+Reflect.parse("class c {accessor\n= false;}");
+Reflect.parse("class c {accessor\nfield = false;}");
+Reflect.parse("class C {accessor\n foo() {}}");
+Reflect.parse("class c {accessor; }");
+Reflect.parse("class c {accessor\nset field(a) {}}");
+Reflect.parse("class c {accessor\nasync field(a) {}}");
+Reflect.parse("class c {accessor\n* field(a) {}}");
+Reflect.parse("{accessor, field(a)}");
+Reflect.parse("class c {static accessor x = 1;}");
+Reflect.parse("class c {accessor #y = 2;}");
+
+assertThrowsInstanceOf(() => Reflect.parse("class c {@ method() {};}"), SyntaxError);
+assertThrowsInstanceOf(() => Reflect.parse("class c {@((a, b, c => {}) method(a, b) {};}"), SyntaxError);
+assertThrowsInstanceOf(() => Reflect.parse("class c {@dec1 static @dec2 method(a, b) {};}"), SyntaxError);
+assertThrowsInstanceOf(() => Reflect.parse("@dec1 let x = 1"), SyntaxError);
+assertThrowsInstanceOf(() => Reflect.parse("@dec1 f(a) {}"), SyntaxError);
+assertThrowsInstanceOf(() => Reflect.parse("@dec1 () => {}"), SyntaxError);
+assertThrowsInstanceOf(() => Reflect.parse("@class class { x; }"), SyntaxError);
+assertThrowsInstanceOf(() => Reflect.parse("@for class { x; }"), SyntaxError);
+assertThrowsInstanceOf(() => Reflect.parse("class c {@dec1. method() {};}"), SyntaxError);
+assertThrowsInstanceOf(() => Reflect.parse("@dec1. class c {method() {};}"), SyntaxError);
+assertThrowsInstanceOf(() => Reflect.parse("@dec1.(a) class c {method() {};}"), SyntaxError);
+assertThrowsInstanceOf(() => Reflect.parse("class c {accessor method() {};}"), SyntaxError);
+assertThrowsInstanceOf(() => Reflect.parse("class c {accessor @dec1 field = false;}"), SyntaxError);
+assertThrowsInstanceOf(() => Reflect.parse("class c {accessor, }"), SyntaxError);
+assertThrowsInstanceOf(() => Reflect.parse("({ accessor field: 10 })"), SyntaxError);
+assertThrowsInstanceOf(() => Reflect.parse("({ accessor foo });"), SyntaxError);
+assertThrowsInstanceOf(() => Reflect.parse("({ accessor foo = 10 } = {});"), SyntaxError);
+assertThrowsInstanceOf(() => Reflect.parse("class c {async accessor foo() {}}"), SyntaxError);
+assertThrowsInstanceOf(() => Reflect.parse("class c {accessor set field(a) {}}"), SyntaxError);
+assertThrowsInstanceOf(() => Reflect.parse("class c {accessor *field(a) {}}"), SyntaxError);
+assertThrowsInstanceOf(() => Reflect.parse("class c {accessor *field(a) {}}"), SyntaxError);