From e1a63fedb722a0dd03a49a6fd5be72ee99d79ef1 Mon Sep 17 00:00:00 2001
From: Evan Wallace <4257481+bonbonman74@users.noreply.github.com>
Date: Sun, 12 May 2024 16:03:36 -0400
Subject: [PATCH] test: https://github.com/evanw/esbuild/issues/3761
---
README.md | 89 ++++++++++++++++++++++++++++-
decorator-tests.js | 138 +++++++++++++++++++++++++++------------------
decorator-tests.ts | 132 ++++++++++++++++++++++++++-----------------
3 files changed, 249 insertions(+), 110 deletions(-)
diff --git a/README.md b/README.md
index 4228754..121573d 100644
--- a/README.md
+++ b/README.md
@@ -15,7 +15,94 @@ You can use `node run.mjs` after `npm install` to run and update the tests below
### esbuild (`esbuild@0.21.0`)
-✅ All checks passed
+
+❌ 16 checks failed (click for details)
+
+```
+❌ Field decorators: Shim (instance field)
+ Code: this instanceof Foo2
+ Expected: true
+ Observed: false
+
+❌ Field decorators: Shim (instance field)
+ Code: this instanceof Foo2
+ Expected: true
+ Observed: false
+
+❌ Field decorators: Shim (instance field)
+ Code: log + ""
+ Expected: "false,false,123,true,false,"
+ Observed: "false,false,123,false,false,"
+
+❌ Field decorators: Shim (static field)
+ Code: this
+ Expected: class
+ Observed: [object global]
+
+❌ Field decorators: Shim (static field)
+ Code: this
+ Expected: class
+ Observed: [object global]
+
+❌ Field decorators: Shim (static field)
+ Code: log + ""
+ Expected: "false,false,123,true,false,"
+ Observed: "false,false,123,false,false,"
+
+❌ Field decorators: Shim (private instance field)
+ Code: this instanceof Foo2
+ Expected: true
+ Observed: false
+
+❌ Field decorators: Shim (private instance field)
+ Code: this instanceof Foo2
+ Expected: true
+ Observed: false
+
+❌ Field decorators: Shim (private instance field)
+ Code: log + ""
+ Expected: "false,false,123,true,false,"
+ Observed: "false,false,123,false,false,"
+
+❌ Field decorators: Shim (private static field)
+ Code: this
+ Expected: class
+ Observed: [object global]
+
+❌ Field decorators: Shim (private static field)
+ Code: this
+ Expected: class
+ Observed: [object global]
+
+❌ Field decorators: Shim (private static field)
+ Code: log + ""
+ Expected: "false,false,123,true,false,"
+ Observed: "false,false,123,false,false,"
+
+❌ Auto-accessor decorators: Shim (instance auto-accessor)
+ Code: this instanceof Foo2
+ Expected: true
+ Observed: false
+
+❌ Auto-accessor decorators: Shim (static auto-accessor)
+ Code: this
+ Expected: class
+ Observed: [object global]
+
+❌ Auto-accessor decorators: Shim (private instance auto-accessor)
+ Code: this instanceof Foo2
+ Expected: true
+ Observed: false
+
+❌ Auto-accessor decorators: Shim (private static auto-accessor)
+ Code: this
+ Expected: class
+ Observed: [object global]
+
+❌ 16 checks failed
+```
+
+
### Babel (`@babel/plugin-proposal-decorators@7.24.1`)
diff --git a/decorator-tests.js b/decorator-tests.js
index 3418b2a..2f12b1a 100644
--- a/decorator-tests.js
+++ b/decorator-tests.js
@@ -916,7 +916,10 @@ const tests = {
'Field decorators: Shim (instance field)': () => {
let log = [];
const dec = (value, ctx) => {
- return (x) => log.push(x);
+ return function (x) {
+ assertEq(() => this instanceof Foo, true);
+ return log.push('foo' in this, 'bar' in this, x);
+ };
};
class Foo {
@dec
@@ -926,40 +929,43 @@ const tests = {
}
assertEq(() => log + '', '');
var obj = new Foo;
- assertEq(() => obj.foo, 1);
- assertEq(() => obj.bar, 2);
- assertEq(() => log + '', '123,');
- var obj = new Foo;
assertEq(() => obj.foo, 3);
- assertEq(() => obj.bar, 4);
- assertEq(() => log + '', '123,,123,');
+ assertEq(() => obj.bar, 6);
+ assertEq(() => log + '', 'false,false,123,true,false,');
},
'Field decorators: Shim (static field)': () => {
+ let foo;
let log = [];
const dec = (value, ctx) => {
- return (x) => log.push(x);
- };
- const fn = (foo, bar) => {
- class Foo {
- @dec
- static foo = 123;
- @dec
- static bar;
- }
- assertEq(() => Foo.foo, foo);
- assertEq(() => Foo.bar, bar);
+ return function (x) {
+ assertEq(() => this, foo);
+ return log.push('foo' in this, 'bar' in this, x);
+ };
};
assertEq(() => log + '', '');
- fn(1, 2);
- assertEq(() => log + '', '123,');
- fn(3, 4);
- assertEq(() => log + '', '123,,123,');
+ class Foo {
+ static {
+ foo = Foo;
+ }
+ @dec
+ static foo = 123;
+ @dec
+ static bar;
+ }
+ assertEq(() => Foo.foo, 3);
+ assertEq(() => Foo.bar, 6);
+ assertEq(() => log + '', 'false,false,123,true,false,');
},
'Field decorators: Shim (private instance field)': () => {
let log = [];
const dec = (value, ctx) => {
- return (x) => log.push(x);
+ return function (x) {
+ assertEq(() => this instanceof Foo, true);
+ return log.push(has$foo(this), has$bar(this), x);
+ };
};
+ let has$foo;
+ let has$bar;
let get$foo;
let get$bar;
class Foo {
@@ -968,46 +974,48 @@ const tests = {
@dec
#bar;
static {
+ has$foo = x => #foo in x;
+ has$bar = x => #bar in x;
get$foo = x => x.#foo;
get$bar = x => x.#bar;
}
}
assertEq(() => log + '', '');
var obj = new Foo;
- assertEq(() => get$foo(obj), 1);
- assertEq(() => get$bar(obj), 2);
- assertEq(() => log + '', '123,');
- var obj = new Foo;
assertEq(() => get$foo(obj), 3);
- assertEq(() => get$bar(obj), 4);
- assertEq(() => log + '', '123,,123,');
+ assertEq(() => get$bar(obj), 6);
+ assertEq(() => log + '', 'false,false,123,true,false,');
},
'Field decorators: Shim (private static field)': () => {
+ let foo;
let log = [];
const dec = (value, ctx) => {
- return (x) => log.push(x);
- };
- const fn = (foo, bar) => {
- let get$foo;
- let get$bar;
- class Foo {
- @dec
- static #foo = 123;
- @dec
- static #bar;
- static {
- get$foo = x => x.#foo;
- get$bar = x => x.#bar;
- }
- }
- assertEq(() => get$foo(Foo), foo);
- assertEq(() => get$bar(Foo), bar);
+ return function (x) {
+ assertEq(() => this, foo);
+ return log.push(has$foo(this), has$bar(this), x);
+ };
};
assertEq(() => log + '', '');
- fn(1, 2);
- assertEq(() => log + '', '123,');
- fn(3, 4);
- assertEq(() => log + '', '123,,123,');
+ let has$foo;
+ let has$bar;
+ let get$foo;
+ let get$bar;
+ class Foo {
+ static {
+ foo = Foo;
+ has$foo = x => #foo in x;
+ has$bar = x => #bar in x;
+ get$foo = x => x.#foo;
+ get$bar = x => x.#bar;
+ }
+ @dec
+ static #foo = 123;
+ @dec
+ static #bar;
+ }
+ assertEq(() => get$foo(Foo), 3);
+ assertEq(() => get$bar(Foo), 6);
+ assertEq(() => log + '', 'false,false,123,true,false,');
},
'Field decorators: Order (instance field)': () => {
const log = [];
@@ -2386,7 +2394,10 @@ const tests = {
let get;
let set;
const dec = (target, ctx) => {
- const init = (x) => x + 1;
+ function init(x) {
+ assertEq(() => this instanceof Foo, true);
+ return x + 1;
+ }
get = function () { return target.get.call(this) * 10; };
set = function (x) { target.set.call(this, x * 2); };
return { get, set, init };
@@ -2403,15 +2414,22 @@ const tests = {
assertEq(() => obj.foo, (321 * 2) * 10);
},
'Auto-accessor decorators: Shim (static auto-accessor)': () => {
+ let foo;
let get;
let set;
const dec = (target, ctx) => {
- const init = (x) => x + 1;
+ function init(x) {
+ assertEq(() => this, foo);
+ return x + 1;
+ }
get = function () { return target.get.call(this) * 10; };
set = function (x) { target.set.call(this, x * 2); };
return { get, set, init };
};
class Foo {
+ static {
+ foo = Foo;
+ }
@dec
static accessor foo = 123;
}
@@ -2425,7 +2443,10 @@ const tests = {
let get;
let set;
const dec = (target, ctx) => {
- const init = (x) => x + 1;
+ function init(x) {
+ assertEq(() => this instanceof Foo, true);
+ return x + 1;
+ }
get = function () { return target.get.call(this) * 10; };
set = function (x) { target.set.call(this, x * 2); };
return { get, set, init };
@@ -2446,10 +2467,14 @@ const tests = {
assertEq(() => get$foo(obj), (321 * 2) * 10);
},
'Auto-accessor decorators: Shim (private static auto-accessor)': () => {
+ let foo;
let get;
let set;
const dec = (target, ctx) => {
- const init = (x) => x + 1;
+ function init(x) {
+ assertEq(() => this, foo);
+ return x + 1;
+ }
get = function () { return target.get.call(this) * 10; };
set = function (x) { target.set.call(this, x * 2); };
return { get, set, init };
@@ -2457,12 +2482,13 @@ const tests = {
let get$foo;
let set$foo;
class Foo {
- @dec
- static accessor #foo = 123;
static {
+ foo = Foo;
get$foo = x => x.#foo;
set$foo = (x, y) => { x.#foo = y; };
}
+ @dec
+ static accessor #foo = 123;
}
assertEq(() => get$foo(Foo), (123 + 1) * 10);
assertEq(() => set$foo(Foo, 321), undefined);
diff --git a/decorator-tests.ts b/decorator-tests.ts
index 9e0adf7..294e1ec 100644
--- a/decorator-tests.ts
+++ b/decorator-tests.ts
@@ -799,9 +799,12 @@ const tests: Record Promise | void> = {
lateAsserts!()
},
'Field decorators: Shim (instance field)': () => {
- let log: number[] = []
+ let log: (boolean | number)[] = []
const dec = (value: undefined, ctx: ClassFieldDecoratorContext) => {
- return (x: number) => log.push(x)
+ return function (this: Foo, x: number) {
+ assertEq(() => this instanceof Foo, true)
+ return log.push('foo' in this, 'bar' in this, x)
+ }
}
class Foo {
@dec foo = 123
@@ -809,82 +812,87 @@ const tests: Record Promise | void> = {
}
assertEq(() => log + '', '')
var obj = new Foo
- assertEq(() => obj.foo, 1)
- assertEq(() => obj.bar, 2)
- assertEq(() => log + '', '123,')
- var obj = new Foo
assertEq(() => obj.foo, 3)
- assertEq(() => obj.bar, 4)
- assertEq(() => log + '', '123,,123,')
+ assertEq(() => obj.bar, 6)
+ assertEq(() => log + '', 'false,false,123,true,false,')
},
'Field decorators: Shim (static field)': () => {
- let log: number[] = []
+ let foo: typeof Foo
+ let log: (boolean | number)[] = []
const dec = (value: undefined, ctx: ClassFieldDecoratorContext) => {
- return (x: number) => log.push(x)
- }
- const fn = (foo: number, bar: number) => {
- class Foo {
- @dec static foo = 123
- @dec static bar: number
+ return function (this: typeof Foo, x: number) {
+ assertEq(() => this, foo)
+ return log.push('foo' in this, 'bar' in this, x)
}
- assertEq(() => Foo.foo, foo)
- assertEq(() => Foo.bar, bar)
}
assertEq(() => log + '', '')
- fn(1, 2)
- assertEq(() => log + '', '123,')
- fn(3, 4)
- assertEq(() => log + '', '123,,123,')
+ class Foo {
+ static {
+ foo = Foo
+ }
+ @dec static foo = 123
+ @dec static bar: number
+ }
+ assertEq(() => Foo.foo, 3)
+ assertEq(() => Foo.bar, 6)
+ assertEq(() => log + '', 'false,false,123,true,false,')
},
'Field decorators: Shim (private instance field)': () => {
- let log: number[] = []
+ let log: (boolean | number)[] = []
const dec = (value: undefined, ctx: ClassFieldDecoratorContext) => {
- return (x: number) => log.push(x)
+ return function (this: Foo, x: number) {
+ assertEq(() => this instanceof Foo, true)
+ return log.push(has$foo(this), has$bar(this), x)
+ }
}
+ let has$foo: (x: Foo) => boolean
+ let has$bar: (x: Foo) => boolean
let get$foo: (x: Foo) => number
let get$bar: (x: Foo) => number
class Foo {
@dec #foo = 123
@dec #bar!: number
static {
+ has$foo = x => #foo in x
+ has$bar = x => #bar in x
get$foo = x => x.#foo
get$bar = x => x.#bar
}
}
assertEq(() => log + '', '')
var obj = new Foo
- assertEq(() => get$foo(obj), 1)
- assertEq(() => get$bar(obj), 2)
- assertEq(() => log + '', '123,')
- var obj = new Foo
assertEq(() => get$foo(obj), 3)
- assertEq(() => get$bar(obj), 4)
- assertEq(() => log + '', '123,,123,')
+ assertEq(() => get$bar(obj), 6)
+ assertEq(() => log + '', 'false,false,123,true,false,')
},
'Field decorators: Shim (private static field)': () => {
- let log: number[] = []
+ let foo: typeof Foo
+ let log: (boolean | number)[] = []
const dec = (value: undefined, ctx: ClassFieldDecoratorContext) => {
- return (x: number) => log.push(x)
- }
- const fn = (foo: number, bar: number) => {
- let get$foo: (x: typeof Foo) => number
- let get$bar: (x: typeof Foo) => number
- class Foo {
- @dec static #foo = 123
- @dec static #bar: number
- static {
- get$foo = x => x.#foo
- get$bar = x => x.#bar
- }
+ return function (this: typeof Foo, x: number) {
+ assertEq(() => this, foo)
+ return log.push(has$foo(this), has$bar(this), x)
}
- assertEq(() => get$foo(Foo), foo)
- assertEq(() => get$bar(Foo), bar)
}
assertEq(() => log + '', '')
- fn(1, 2)
- assertEq(() => log + '', '123,')
- fn(3, 4)
- assertEq(() => log + '', '123,,123,')
+ let has$foo: (x: typeof Foo) => boolean
+ let has$bar: (x: typeof Foo) => boolean
+ let get$foo: (x: typeof Foo) => number
+ let get$bar: (x: typeof Foo) => number
+ class Foo {
+ static {
+ foo = Foo
+ has$foo = x => #foo in x
+ has$bar = x => #bar in x
+ get$foo = x => x.#foo
+ get$bar = x => x.#bar
+ }
+ @dec static #foo = 123
+ @dec static #bar: number
+ }
+ assertEq(() => get$foo(Foo), 3)
+ assertEq(() => get$bar(Foo), 6)
+ assertEq(() => log + '', 'false,false,123,true,false,')
},
'Field decorators: Order (instance field)': () => {
const log: number[] = []
@@ -2084,7 +2092,10 @@ const tests: Record Promise | void> = {
let get: (this: Foo) => number
let set: (this: Foo, x: number) => void
const dec = (target: ClassAccessorDecoratorTarget, ctx: ClassAccessorDecoratorContext): ClassAccessorDecoratorResult => {
- const init = (x: number) => x + 1
+ function init(this: Foo, x: number): number {
+ assertEq(() => this instanceof Foo, true)
+ return x + 1
+ }
get = function () { return target.get.call(this) * 10 }
set = function (x) { target.set.call(this, x * 2) }
return { get, set, init }
@@ -2100,15 +2111,22 @@ const tests: Record Promise | void> = {
assertEq(() => obj.foo, (321 * 2) * 10)
},
'Auto-accessor decorators: Shim (static auto-accessor)': () => {
+ let foo: typeof Foo
let get: (this: typeof Foo) => number
let set: (this: typeof Foo, x: number) => void
const dec = (target: ClassAccessorDecoratorTarget, ctx: ClassAccessorDecoratorContext): ClassAccessorDecoratorResult => {
- const init = (x: number) => x + 1
+ function init(this: typeof Foo, x: number): number {
+ assertEq(() => this, foo)
+ return x + 1
+ }
get = function () { return target.get.call(this) * 10 }
set = function (x) { target.set.call(this, x * 2) }
return { get, set, init }
}
class Foo {
+ static {
+ foo = Foo
+ }
@dec static accessor foo = 123
}
assertEq(() => Object.getOwnPropertyDescriptor(Foo, 'foo')!.get, get!)
@@ -2121,7 +2139,10 @@ const tests: Record Promise | void> = {
let get: (this: Foo) => number
let set: (this: Foo, x: number) => void
const dec = (target: ClassAccessorDecoratorTarget, ctx: ClassAccessorDecoratorContext): ClassAccessorDecoratorResult => {
- const init = (x: number) => x + 1
+ function init(this: Foo, x: number): number {
+ assertEq(() => this instanceof Foo, true)
+ return x + 1
+ }
get = function () { return target.get.call(this) * 10 }
set = function (x) { target.set.call(this, x * 2) }
return { get, set, init }
@@ -2141,10 +2162,14 @@ const tests: Record Promise | void> = {
assertEq(() => get$foo(obj), (321 * 2) * 10)
},
'Auto-accessor decorators: Shim (private static auto-accessor)': () => {
+ let foo: typeof Foo
let get: (this: typeof Foo) => number
let set: (this: typeof Foo, x: number) => void
const dec = (target: ClassAccessorDecoratorTarget, ctx: ClassAccessorDecoratorContext): ClassAccessorDecoratorResult => {
- const init = (x: number) => x + 1
+ function init(this: typeof Foo, x: number): number {
+ assertEq(() => this, foo)
+ return x + 1
+ }
get = function () { return target.get.call(this) * 10 }
set = function (x) { target.set.call(this, x * 2) }
return { get, set, init }
@@ -2152,11 +2177,12 @@ const tests: Record Promise | void> = {
let get$foo: (x: typeof Foo) => number
let set$foo: (x: typeof Foo, y: number) => void
class Foo {
- @dec static accessor #foo = 123
static {
+ foo = Foo
get$foo = x => x.#foo
set$foo = (x, y) => { x.#foo = y }
}
+ @dec static accessor #foo = 123
}
assertEq(() => get$foo(Foo), (123 + 1) * 10)
assertEq(() => set$foo(Foo, 321), undefined)