diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /js/src/jit-test/tests/decorators | |
parent | Initial commit. (diff) | |
download | firefox-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.js | 70 | ||||
-rw-r--r-- | js/src/jit-test/tests/decorators/field-decorators.js | 75 | ||||
-rw-r--r-- | js/src/jit-test/tests/decorators/getter-setter-decorators.js | 64 | ||||
-rw-r--r-- | js/src/jit-test/tests/decorators/method-decorators.js | 86 | ||||
-rw-r--r-- | js/src/jit-test/tests/decorators/syntax.js | 68 |
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); |