Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: swc-project/swc
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 13b0476da3a114be01df1dca50b242d12b24ced3
Choose a base ref
...
head repository: swc-project/swc
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: d17a6653c4f52aa1899b7396113408915103dcb6
Choose a head ref

Commits on Aug 23, 2022

  1. 1
    Copy the full SHA
    e2fedb9 View commit details
  2. chore: Publish crates

    swc-bot committed Aug 23, 2022
    Copy the full SHA
    94080df View commit details
  3. chore: Publish crates

    kdy1 committed Aug 23, 2022
    Copy the full SHA
    c760622 View commit details
  4. 1
    Copy the full SHA
    e211ad6 View commit details
  5. chore: Publish crates

    swc-bot committed Aug 23, 2022
    Copy the full SHA
    48e5cf2 View commit details
  6. chore: Publish v1.2.242

    kdy1 committed Aug 23, 2022
    Copy the full SHA
    2bc63e8 View commit details
  7. 1
    Copy the full SHA
    633a23a View commit details
  8. chore: Publish crates

    swc-bot committed Aug 23, 2022
    Copy the full SHA
    e6f9c6c View commit details
  9. 1
    Copy the full SHA
    52117f7 View commit details
  10. chore: Publish crates

    swc-bot committed Aug 23, 2022
    Copy the full SHA
    9ed7fcd View commit details
  11. 1
    Copy the full SHA
    7fcecb8 View commit details
  12. chore: Publish crates

    swc-bot committed Aug 23, 2022
    Copy the full SHA
    860f253 View commit details

Commits on Aug 24, 2022

  1. 1
    Copy the full SHA
    7461e40 View commit details
  2. chore: Publish crates

    swc-bot committed Aug 24, 2022
    Copy the full SHA
    7fc8e6c View commit details
  3. 1
    Copy the full SHA
    3d485d2 View commit details
  4. chore: Publish crates

    swc-bot committed Aug 24, 2022
    Copy the full SHA
    fa7a13a View commit details
  5. 1
    Copy the full SHA
    fad1367 View commit details
  6. chore: Publish crates

    swc-bot committed Aug 24, 2022
    Copy the full SHA
    c71f62b View commit details
  7. 1
    Copy the full SHA
    1181d0f View commit details
  8. chore: Publish crates

    swc-bot committed Aug 24, 2022
    Copy the full SHA
    8d44b71 View commit details
  9. 1
    Copy the full SHA
    35d3558 View commit details
  10. chore: Publish crates

    swc-bot committed Aug 24, 2022
    Copy the full SHA
    77ae3cf View commit details

Commits on Aug 25, 2022

  1. 1
    Copy the full SHA
    3d2ee6d View commit details
  2. chore: Publish crates

    swc-bot committed Aug 25, 2022
    Copy the full SHA
    87fa49c View commit details
  3. 1
    Copy the full SHA
    2aa0090 View commit details
  4. chore: Publish crates

    swc-bot committed Aug 25, 2022
    Copy the full SHA
    3ea433b View commit details
  5. Copy the full SHA
    d17a665 View commit details
Showing 1,030 changed files with 28,718 additions and 20,854 deletions.
47 changes: 47 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -5,6 +5,47 @@



- **(es/compat)** Ignore invalid class method names (#5612) ([1181d0f](https://github.com/swc-project/swc/commit/1181d0ffe2b432a202398dfc99dcc89da7480b84))


- **(es/compat)** Handle `super` in a private method (#5613) ([35d3558](https://github.com/swc-project/swc/commit/35d3558535c3bee2cbbd8adec162f9c4cb9a4bbc))


- **(es/fixer)** Wrap expressions in the left of a binary expression (#5586) ([3d485d2](https://github.com/swc-project/swc/commit/3d485d26814516351bd5591502c64811f77f5385))


- **(swc_core)** Re-export `swc_cached` (#5605) ([7fcecb8](https://github.com/swc-project/swc/commit/7fcecb8e63faa64226b87e34b8cd4fdd0a6a7ab7))

### Features



- **(cli)** Enable LTO by default for the plugins (#5617) ([3d2ee6d](https://github.com/swc-project/swc/commit/3d2ee6d0ae29899ae3a492a0e4b963e40b1d60ff))


- **(es/generator)** Replace generator implementation with one from tsc (#5173) ([2aa0090](https://github.com/swc-project/swc/commit/2aa009018f9bdbe4de6d59f9226b7ddd320db127))


- **(swc_core)** Expand features (#5602) ([633a23a](https://github.com/swc-project/swc/commit/633a23a13438cb3891ea1cdef349cde882672bec))


- **(swc_core)** Add css features (#5609) ([7461e40](https://github.com/swc-project/swc/commit/7461e404b1946cb8b421c314f4b57dc8d836721a))


- **(swc_core)** Update dependencies and fix build script (#5610) ([fad1367](https://github.com/swc-project/swc/commit/fad1367e137288dd0e15591d7ecb4aaee222d327))

### Build



- **(swc_core)** Bump `swc_core` (#5604) ([52117f7](https://github.com/swc-project/swc/commit/52117f71e3f710af9f6095e4022b393abf7bb050))

## [1.2.242] - 2022-08-23

### Bug Fixes



- **(es)** Improve sourcemap (#5569) ([2f7e322](https://github.com/swc-project/swc/commit/2f7e3222140aba2a0e13e307f18b42f6b39f084d))


@@ -38,6 +79,9 @@



- **(bindings)** Update `swc_core` (#5594) ([e211ad6](https://github.com/swc-project/swc/commit/e211ad6d10f9e05e1ccade2c3cba60e3a53dbee7))


- **(css/ast)** Make `keyword` optional (#5543) ([a3c1ac6](https://github.com/swc-project/swc/commit/a3c1ac67d708b6c95ef9a9b0892df90bdb26ffe5))


@@ -58,6 +102,9 @@

- **(es/transforms)** Enable tests for fixed issues (#5583) ([0f6649c](https://github.com/swc-project/swc/commit/0f6649c44fbd35cbb7f0b64bf9b5a175f002fdd9))


- **(es/transforms)** Copy execution tests from babel (#5578) ([e2fedb9](https://github.com/swc-project/swc/commit/e2fedb93452e54f4146f725ae07c6c2f0a4067a5))

### Build


51 changes: 28 additions & 23 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

98 changes: 49 additions & 49 deletions bindings/Cargo.lock
2 changes: 1 addition & 1 deletion bindings/binding_core_node/Cargo.toml
Original file line number Diff line number Diff line change
@@ -48,7 +48,7 @@ tracing-chrome = "0.5.0"
tracing-futures = "0.2.5"
tracing-subscriber = { version = "0.3.9", features = ["env-filter"] }

swc_core = { version = "0.8.1", features = [
swc_core = { version = "0.11.7", features = [
"ast",
"common_concurrent",
"bundler",
4 changes: 2 additions & 2 deletions bindings/binding_core_wasm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ license = "Apache-2.0"
name = "binding_core_wasm"
publish = false
repository = "https://github.com/swc-project/swc.git"
version = "1.2.241"
version = "1.2.242"

[lib]
bench = false
@@ -20,7 +20,7 @@ swc_v2 = []
plugin = ["swc_core/plugin_transform_host_js"]

[dependencies]
swc_core = { version = "0.8.1", features = [
swc_core = { version = "0.11.7", features = [
"common_perf",
"binding_macro_wasm",
] }
2 changes: 1 addition & 1 deletion bindings/swc_cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@ rayon = "1"
relative-path = "1.6.1"
serde = { version = "1", features = ["derive"] }
serde_json = { version = "1", features = ["unbounded_depth"] }
swc_core = { version = "0.8.1", features = [
swc_core = { version = "0.11.7", features = [
"trace_macro",
"common_concurrent",
"base",
3 changes: 3 additions & 0 deletions bindings/swc_cli/src/commands/plugin.rs
Original file line number Diff line number Diff line change
@@ -159,6 +159,9 @@ edition = "2021"
[lib]
crate-type = ["cdylib"]
[profile.release]
lto = true
[dependencies]
serde = "1"
swc_core = {{ version = "{}", features = ["plugin_transform"] }}
6 changes: 3 additions & 3 deletions crates/binding_macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ edition = "2021"
license = "Apache-2.0"
name = "binding_macros"
repository = "https://github.com/swc-project/swc.git"
version = "0.6.1"
version = "0.7.0"

[lib]
bench = false
@@ -30,10 +30,10 @@ binding_wasm = [

[dependencies]
# Common deps for the SWC imports
swc = { optional = true, version = "0.218.0", path = "../swc" }
swc = { optional = true, version = "0.219.0", path = "../swc" }
swc_common = { optional = true, version = "0.27.13", path = "../swc_common" }
swc_ecma_ast = { optional = true, version = "0.90.12", path = "../swc_ecma_ast" }
swc_ecma_transforms = { optional = true, version = "0.185.0", path = "../swc_ecma_transforms" }
swc_ecma_transforms = { optional = true, version = "0.186.0", path = "../swc_ecma_transforms" }

# Optional deps for the wasm binding macro
anyhow = { optional = true, version = "1.0.58" }
4 changes: 2 additions & 2 deletions crates/dbg-swc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ edition = "2021"
license = "Apache-2.0"
name = "dbg-swc"
repository = "https://github.com/kdy1/dbg-swc.git"
version = "0.45.0"
version = "0.46.0"

[[bin]]
bench = false
@@ -22,7 +22,7 @@ swc_common = { version = "0.27.13", features = [
], path = "../swc_common" }
swc_ecma_ast = { version = "0.90.12", path = "../swc_ecma_ast" }
swc_ecma_codegen = { version = "0.122.0", path = "../swc_ecma_codegen" }
swc_ecma_minifier = { version = "0.146.0", path = "../swc_ecma_minifier", features = [
swc_ecma_minifier = { version = "0.147.0", path = "../swc_ecma_minifier", features = [
"concurrent",
] }
swc_ecma_parser = { version = "0.118.0", path = "../swc_ecma_parser" }
14 changes: 7 additions & 7 deletions crates/swc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@ include = ["Cargo.toml", "src/**/*.rs"]
license = "Apache-2.0"
name = "swc"
repository = "https://github.com/swc-project/swc.git"
version = "0.218.2"
version = "0.219.0"

[lib]
bench = false
@@ -71,20 +71,20 @@ swc_ecma_loader = { version = "0.39.4", path = "../swc_ecma_loader", features =
"node",
"tsc",
] }
swc_ecma_minifier = { version = "0.146.0", path = "../swc_ecma_minifier" }
swc_ecma_minifier = { version = "0.147.0", path = "../swc_ecma_minifier" }
swc_ecma_parser = { version = "0.118.0", path = "../swc_ecma_parser" }
swc_ecma_preset_env = { version = "0.161.0", path = "../swc_ecma_preset_env" }
swc_ecma_transforms = { version = "0.185.0", path = "../swc_ecma_transforms", features = [
swc_ecma_preset_env = { version = "0.162.0", path = "../swc_ecma_preset_env" }
swc_ecma_transforms = { version = "0.186.0", path = "../swc_ecma_transforms", features = [
"compat",
"module",
"optimization",
"proposal",
"react",
"typescript",
] }
swc_ecma_transforms_base = { version = "0.104.0", path = "../swc_ecma_transforms_base" }
swc_ecma_transforms_compat = { version = "0.124.0", path = "../swc_ecma_transforms_compat" }
swc_ecma_transforms_optimization = { version = "0.154.0", path = "../swc_ecma_transforms_optimization" }
swc_ecma_transforms_base = { version = "0.104.1", path = "../swc_ecma_transforms_base" }
swc_ecma_transforms_compat = { version = "0.125.0", path = "../swc_ecma_transforms_compat" }
swc_ecma_transforms_optimization = { version = "0.155.0", path = "../swc_ecma_transforms_optimization" }
swc_ecma_utils = { version = "0.100.2", path = "../swc_ecma_utils" }
swc_ecma_visit = { version = "0.76.6", path = "../swc_ecma_visit" }
swc_error_reporters = { version = "0.11.4", path = "../swc_error_reporters" }
3 changes: 3 additions & 0 deletions crates/swc/tests/babel-exec/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## Execution tests copied from babel

See https://github.com/babel/babel/blob/main/LICENSE for license
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
class Bar {
test() {
// pass
(() => {
expect(this.constructor).toBe(Bar);
})();

// pass
(() => {
expect(this.constructor).toBe(Bar);
}).call(this);

(async () => {
expect(this.constructor).toBe(Bar);
})();

(async () => {
expect(this.constructor).toBe(Bar);
}).call(this);
}
}

(new Bar()).test();
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
function* foo(bar = "bar") {
return bar;
}

expect(foo().next().value).toBe("bar");
expect(foo("foo").next().value).toBe("foo");
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
function* foo({ bar }) {
return bar;
}

expect(foo({ bar: "bar" }).next().value).toBe("bar");
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
function* foo() {
var { bar } = { bar: "bar" };
return bar;
}

expect(foo().next().value).toBe("bar");;

function* foo2({ bar = 0 }) {
return bar;
}

expect(foo2({ bar: undefined }).next().value).toBe(0);
expect(foo2({ bar: 3 }).next().value).toBe(3);

function* foo3() {
loop:
while(true) {
// Changing "let" to "var" makes the tests pass.
let { what, value } = yield "iteration";

switch(what) {
case "one":
// Removing these 5 lines makes the tests pass.
if(value === 1) {
break loop;
} else if(value === 2) {
break loop;
}
break;
case "two":
// Removing these 3 lines makes the tests pass.
["a", "b"].map(function(v) {
return value + v;
});

break loop;
break;
case "three":
break loop;
break;
}
}
}

var gen3 = foo3();

expect(gen3.next().value).toBe("iteration");
expect(gen3.next({what: "one", value: 3}).done).toBe(false);
expect(gen3.next({what: "one", value: 2}).done).toBe(true);

var gen4 = foo3();
expect(gen4.next().value).toBe("iteration");
expect(gen4.next({what: "two", value: "sometext"}).done).toBe(true);

var gen5 = foo3();
expect(gen5.next().value).toBe("iteration");
expect(gen5.next({what: "three"}).done).toBe(true);
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
function* foo(...items) {
return items;
}

expect(foo(1, 2, 3).next().value).toEqual([1, 2, 3]);
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
const actualOrder = [];

const track = i => {
actualOrder.push(i);
return i;
};

class MyClass {
static [track(1)] = track(10);
[track(2)] = track(13);
get [track(3)]() {
return "foo";
}
set [track(4)](value) {
this.bar = value;
}
[track(5)] = track(14);
static [track(6)] = track(11);
static [track(7)] = track(12);
[track(8)]() {}
[track(9)] = track(15);
}

const inst = new MyClass();

const expectedOrder = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
expect(actualOrder).toEqual(expectedOrder);

expect(MyClass[1]).toBe(10);
expect(inst[2]).toBe(13);
expect(inst[3]).toBe("foo");
inst[4] = "baz";
expect(inst.bar).toBe("baz");
expect(inst[5]).toBe(14);
expect(MyClass[6]).toBe(11);
expect(MyClass[7]).toBe(12);
expect(typeof inst[8]).toBe("function");
expect(inst[9]).toBe(15);
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
function test(x) {
class F {
[x] = 1;
constructor() {}
}

x = 'deadbeef';
expect(new F().foo).toBe(1);
x = 'wrong';
expect(new F().foo).toBe(1);
}

test('foo');
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class A {
static prop = 1;
}

class B extends A {
static prop = 2;
static propA = super.prop;
static getPropA = () => super.prop;
}

const { prop, propA, getPropA } = B;

expect(prop).toBe(2);
expect(propA).toBe(1);
expect(getPropA()).toBe(1);
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class A {
static self = this;
static getA = () => this;
}

const { self, getA } = A;

expect(self).toBe(A);
expect(getA()).toBe(A);
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class Foo {
static num;
}

expect("num" in Foo).toBe(true);
expect(Foo.num).toBeUndefined();
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class Foo {
static num = 0;
static str = "foo";
}

expect(Foo.num).toBe(0);
expect(Foo.num = 1).toBe(1);
expect(Foo.str).toBe("foo");
expect(Foo.str = "bar").toBe("bar");
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"use strict";
class Hello {
constructor() {
return {
toString() {
return 'hello';
},
};
}
}

class Outer extends Hello {
constructor() {
class Inner {
[super()] = "hello";
}

return new Inner();
}
}

expect(new Outer().hello).toBe('hello');
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class Foo {
#foo = function() {
return this;
}

test(other) {
return [this.#foo(), other.#foo()];
}
}

const f = new Foo;
const o = new Foo;
const test = f.test(o);
expect(test[0]).toBe(f);
expect(test[1]).toBe(o);
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
class Point {
#x;
#y;

constructor(x = 0, y = 0) {
this.#x = +x;
this.#y = +y;
}

get x() { return this.#x }
set x(value) { this.#x = +value }

get y() { return this.#y }
set y(value) { this.#y = +value }

equals(p) { return this.#x === p.#x && this.#y === p.#y }

toString() { return `Point<${ this.#x },${ this.#y }>` }

}

const p1 = new Point(1, 2);
const p2 = new Point(2, 3);
const p3 = new Point(1, 2);

expect(p1.x).toBe(1);
expect(p1.y).toBe(2);
expect(p2.x).toBe(2);
expect(p2.y).toBe(3);
expect(p3.x).toBe(1);
expect(p3.y).toBe(2);

expect(p1.equals(p1)).toBe(true)
expect(p1.equals(p2)).toBe(false)
expect(p1.equals(p3)).toBe(true)
expect(p2.equals(p1)).toBe(false)
expect(p2.equals(p2)).toBe(true)
expect(p2.equals(p3)).toBe(false)
expect(p3.equals(p1)).toBe(true)
expect(p3.equals(p2)).toBe(false)
expect(p3.equals(p3)).toBe(true)

expect(p1.toString()).toBe("Point<1,2>")
expect(p2.toString()).toBe("Point<2,3>")
expect(p3.toString()).toBe("Point<1,2>")

p1.x += 1;
p1.y = 3;
p2.x -= 1;
p2.y = 3;
p3.x = 0;
p3.y = 0;

expect(p1.x).toBe(2);
expect(p1.y).toBe(3);
expect(p2.x).toBe(1);
expect(p2.y).toBe(3);
expect(p3.x).toBe(0);
expect(p3.y).toBe(0);

expect(p1.equals(p1)).toBe(true)
expect(p1.equals(p2)).toBe(false)
expect(p1.equals(p3)).toBe(false)
expect(p2.equals(p1)).toBe(false)
expect(p2.equals(p2)).toBe(true)
expect(p2.equals(p3)).toBe(false)
expect(p3.equals(p1)).toBe(false)
expect(p3.equals(p2)).toBe(false)
expect(p3.equals(p3)).toBe(true)

expect(p1.toString()).toBe("Point<2,3>")
expect(p2.toString()).toBe("Point<1,3>")
expect(p3.toString()).toBe("Point<0,0>")
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
var foo = "bar";

class Foo {
#bar = foo;

constructor() {
var foo = "foo";
}

test() {
return this.#bar;
}
}

const f = new Foo;
expect(f.test()).toBe(foo);
expect("bar" in f).toBe(false);
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class C {
y = this.#x;
#x;
}

expect(() => {
new C();
}).toThrow();
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
class Foo {
#prop = "foo";

foo() {
return this.#prop;
}
}

class Bar extends Foo {
#prop = "bar";

bar() {
return this.#prop;
}
}

const f = new Foo;
expect(f.foo()).toBe("foo");

const b = new Bar;
expect(b.foo()).toBe("foo");
expect(b.bar()).toBe("bar");
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
class Foo {
#client

constructor(props) {
this.#client = 1;
;([this.x = this.#client, this.#client, this.y = this.#client] = props);
}

getClient() {
return this.#client;
}
}

const foo = new Foo([undefined, 'bar']);
expect(foo.getClient()).toBe('bar');
expect(foo.x).toBe(1);
expect(foo.y).toBe('bar');
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class Foo {
#client

constructor(props) {
let x;
;([x, ...this.#client] = props);
}

getClient() {
return this.#client;
}
}

const foo = new Foo(['foo', 'bar', 'baz', 'quu']);
expect(foo.getClient()).toEqual(['bar', 'baz', 'quu']);
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Foo {
#client

constructor(props) {
([this.#client = 5] = props);
}

getClient() {
return this.#client;
}
}

const foo = new Foo([]);
expect(foo.getClient()).toEqual(5);
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Foo {
static #client

constructor(props) {
;([Foo.#client] = props);
}

getClient() {
return Foo.#client;
}
}

const foo = new Foo(['bar']);
expect(foo.getClient()).toBe('bar');
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Foo {
#client

constructor(props) {
;([this.#client] = props);
}

getClient() {
return this.#client;
}
}

const foo = new Foo(['bar']);
expect(foo.getClient()).toBe('bar');
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
class Foo {
#client

constructor(props) {
this.#client = 'foo';
;({ x: this.x = this.#client, y: this.#client, z: this.z = this.#client } = props)
}

getClient() {
return this.#client;
}
}

const foo = new Foo({ y: 'bar' });
expect(foo.getClient()).toBe('bar');
expect(foo.x).toBe('foo');
expect(foo.z).toBe('bar');
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class Foo {
#client

constructor(props) {
let x;
;({ x, ...this.#client } = props)
}

getClient() {
return this.#client;
}
}

const foo = new Foo({ x: 'foo', y: 'bar', z: 'baz' });
expect(foo.getClient()).toEqual({ y: 'bar', z: 'baz' });
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Foo {
#client

constructor(props) {
({ client: this.#client = 5 } = props);
}

getClient() {
return this.#client;
}
}

const foo = new Foo({});
expect(foo.getClient()).toEqual(5);
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Foo {
static #client

constructor(props) {
;({ client: Foo.#client } = props)
}

getClient() {
return Foo.#client;
}
}

const foo = new Foo({ client: 'bar' });
expect(foo.getClient()).toBe('bar');
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Foo {
#client

constructor(props) {
;({ client: this.#client } = props)
}

getClient() {
return this.#client;
}
}

const foo = new Foo({ client: 'bar' });
expect(foo.getClient()).toBe('bar');
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class Foo {
#bar;

test() {
return this.#bar;
}
}

expect(new Foo().test()).toBe(undefined);
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
class Foo {
#bar = "foo";

test() {
return this.#bar;
}

static test(foo) {
return foo.#bar;
}
}

const f = new Foo();
expect(f.test()).toBe("foo");
expect(Foo.test(f)).toBe("foo");
expect("bar" in f).toBe(false);
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class Foo {
#x = 0;
#y = this.#x + 1;

test() {
return this.#y;
}
}

const f = new Foo();
expect(f.test()).toBe(1);
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
class Foo {
#foo = 1;

test() {
class Nested {
#foo = 2;

[this.#foo]() {
}
}

return new Nested();
}
}

const f = new Foo();
expect(() => {
f.test();
}).toThrow();
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
class Foo {
#m;
init() {
this.#m = (...args) => args;
}
static test() {
const f = new Foo();
f.init();
return f.#m?.(...arguments);
}

static testNull() {
const f = new Foo();
return f.#m?.(...arguments);
}
}

expect(Foo.test(1, 2)).toEqual([1, 2]);
expect(Foo.testNull(1, 2)).toBe(undefined);
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class Foo {
static #foo = function(x) {
return x;
}

test(x) {
return Foo.#foo(x);
}
}

const f = new Foo;
const test = f.test();
expect(f.test("bar")).toBe("bar");
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
class Base {
static #foo = 1;

static getThis() {
return this.#foo;
}

static updateThis(val) {
return (this.#foo = val);
}

static getClass() {
return Base.#foo;
}

static updateClass(val) {
return (Base.#foo = val);
}
}

class Sub1 extends Base {
static #foo = 2;

static update(val) {
return (this.#foo = val);
}
}

class Sub2 extends Base {}

expect(Base.getThis()).toBe(1);
expect(Base.getClass()).toBe(1);
expect(() => Sub1.getThis()).toThrow();
expect(Sub1.getClass()).toBe(1);
expect(() => Sub2.getThis()).toThrow();
expect(Sub2.getClass()).toBe(1);

expect(Sub1.update(3)).toBe(3);
expect(Base.getThis()).toBe(1);
expect(Base.getClass()).toBe(1);
expect(() => Sub1.getThis()).toThrow();
expect(Sub1.getClass()).toBe(1);
expect(() => Sub2.getThis()).toThrow();
expect(Sub2.getClass()).toBe(1);

expect(Base.updateThis(4)).toBe(4);
expect(Base.getThis()).toBe(4);
expect(Base.getClass()).toBe(4);
expect(() => Sub1.getThis()).toThrow();
expect(Sub1.getClass()).toBe(4);
expect(() => Sub2.getThis()).toThrow();
expect(Sub2.getClass()).toBe(4);

expect(Base.updateClass(5)).toBe(5);
expect(Base.getThis()).toBe(5);
expect(Base.getClass()).toBe(5);
expect(() => Sub1.getThis()).toThrow();
expect(Sub1.getClass()).toBe(5);
expect(() => Sub2.getThis()).toThrow();
expect(Sub2.getClass()).toBe(5);

expect(() => Sub2.updateThis(6)).toThrow();
expect(Sub2.updateClass(7)).toBe(7);
expect(Base.getThis()).toBe(7);
expect(Base.getClass()).toBe(7);
expect(() => Sub1.getThis()).toThrow();
expect(Sub1.getClass()).toBe(7);
expect(() => Sub2.getThis()).toThrow();
expect(Sub2.getClass()).toBe(7);
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class Test {

static #x = 1

static method() {
const Test = 2;
const func = () => {
const Test = 3;
return this.#x + Test;
}
return func() + Test;
}
}

expect(Test.method()).toBe(6)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class A {
static #self = this;
static #getA = () => this;

static extract() {
return { self: A.#self, getA: A.#getA };
}
}

const { self, getA } = A.extract();

expect(self).toBe(A);
expect(getA()).toBe(A);
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class Foo {
static #bar;

static test() {
return Foo.#bar;
}

test() {
return Foo.#bar;
}
}

expect("bar" in Foo).toBe(false);
expect(Foo.test()).toBe(undefined);
expect(Foo.test()).toBe(undefined);
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class Foo {
static #bar = "foo";

static test() {
return Foo.#bar;
}

test() {
return Foo.#bar;
}
}

expect("bar" in Foo).toBe(false);
expect(Foo.test()).toBe("foo");
expect(Foo.test()).toBe("foo");
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
class Foo {
#foo = 0;

test(other) {
return [
this.#foo++,
this.#foo,
++this.#foo,
this.#foo,
other.obj.#foo++,
other.obj.#foo,
++other.obj.#foo,
other.obj.#foo,
];
}
}

const f = new Foo;
const results = f.test({ obj: f });
expect(results[0]).toBe(0);
expect(results[1]).toBe(1);
expect(results[2]).toBe(2);
expect(results[3]).toBe(2);
expect(results[4]).toBe(2);
expect(results[5]).toBe(3);
expect(results[6]).toBe(4);
expect(results[7]).toBe(4);
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class Foo {
#foo = function() {
return this;
}

test(other) {
return [this.#foo(), other.#foo()];
}
}

const f = new Foo;
const o = new Foo;
const test = f.test(o);
expect(test[0]).toBe(f);
expect(test[1]).toBe(o);
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
class Point {
#x;
#y;

constructor(x = 0, y = 0) {
this.#x = +x;
this.#y = +y;
}

get x() { return this.#x }
set x(value) { this.#x = +value }

get y() { return this.#y }
set y(value) { this.#y = +value }

equals(p) { return this.#x === p.#x && this.#y === p.#y }

toString() { return `Point<${ this.#x },${ this.#y }>` }

}

const p1 = new Point(1, 2);
const p2 = new Point(2, 3);
const p3 = new Point(1, 2);

expect(p1.x).toBe(1);
expect(p1.y).toBe(2);
expect(p2.x).toBe(2);
expect(p2.y).toBe(3);
expect(p3.x).toBe(1);
expect(p3.y).toBe(2);

expect(p1.equals(p1)).toBe(true)
expect(p1.equals(p2)).toBe(false)
expect(p1.equals(p3)).toBe(true)
expect(p2.equals(p1)).toBe(false)
expect(p2.equals(p2)).toBe(true)
expect(p2.equals(p3)).toBe(false)
expect(p3.equals(p1)).toBe(true)
expect(p3.equals(p2)).toBe(false)
expect(p3.equals(p3)).toBe(true)

expect(p1.toString()).toBe("Point<1,2>")
expect(p2.toString()).toBe("Point<2,3>")
expect(p3.toString()).toBe("Point<1,2>")

p1.x += 1;
p1.y = 3;
p2.x -= 1;
p2.y = 3;
p3.x = 0;
p3.y = 0;

expect(p1.x).toBe(2);
expect(p1.y).toBe(3);
expect(p2.x).toBe(1);
expect(p2.y).toBe(3);
expect(p3.x).toBe(0);
expect(p3.y).toBe(0);

expect(p1.equals(p1)).toBe(true)
expect(p1.equals(p2)).toBe(false)
expect(p1.equals(p3)).toBe(false)
expect(p2.equals(p1)).toBe(false)
expect(p2.equals(p2)).toBe(true)
expect(p2.equals(p3)).toBe(false)
expect(p3.equals(p1)).toBe(false)
expect(p3.equals(p2)).toBe(false)
expect(p3.equals(p3)).toBe(true)

expect(p1.toString()).toBe("Point<2,3>")
expect(p2.toString()).toBe("Point<1,3>")
expect(p3.toString()).toBe("Point<0,0>")
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
var foo = "bar";

class Foo {
#bar = foo;

constructor() {
var foo = "foo";
}

test() {
return this.#bar;
}
}

const f = new Foo;
expect(f.test()).toBe(foo);
expect("bar" in f).toBe(false);
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class C {
y = this.#x;
#x;
}

expect(() => {
new C();
}).toThrow();
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
class Foo {
#prop = "foo";

foo() {
return this.#prop;
}
}

class Bar extends Foo {
#prop = "bar";

bar() {
return this.#prop;
}
}

const f = new Foo;
expect(f.foo()).toBe("foo");

const b = new Bar;
expect(b.foo()).toBe("foo");
expect(b.bar()).toBe("bar");
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
class Foo {
#client

constructor(props) {
this.#client = 1;
;([this.x = this.#client, this.#client, this.y = this.#client] = props);
}

getClient() {
return this.#client;
}
}

const foo = new Foo([undefined, 'bar']);
expect(foo.getClient()).toBe('bar');
expect(foo.x).toBe(1);
expect(foo.y).toBe('bar');
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class Foo {
#client

constructor(props) {
let x;
;([x, ...this.#client] = props);
}

getClient() {
return this.#client;
}
}

const foo = new Foo(['foo', 'bar', 'baz', 'quu']);
expect(foo.getClient()).toEqual(['bar', 'baz', 'quu']);
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Foo {
#client

constructor(props) {
([this.#client = 5] = props);
}

getClient() {
return this.#client;
}
}

const foo = new Foo([]);
expect(foo.getClient()).toEqual(5);
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Foo {
static #client

constructor(props) {
;([Foo.#client] = props);
}

getClient() {
return Foo.#client;
}
}

const foo = new Foo(['bar']);
expect(foo.getClient()).toBe('bar');
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Foo {
#client

constructor(props) {
;([this.#client] = props);
}

getClient() {
return this.#client;
}
}

const foo = new Foo(['bar']);
expect(foo.getClient()).toBe('bar');
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
class Foo {
#client

constructor(props) {
this.#client = 'foo';
;({ x: this.x = this.#client, y: this.#client, z: this.z = this.#client } = props)
}

getClient() {
return this.#client;
}
}

const foo = new Foo({ y: 'bar' });
expect(foo.getClient()).toBe('bar');
expect(foo.x).toBe('foo');
expect(foo.z).toBe('bar');
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class Foo {
#client

constructor(props) {
let x;
;({ x, ...this.#client } = props)
}

getClient() {
return this.#client;
}
}

const foo = new Foo({ x: 'foo', y: 'bar', z: 'baz' });
expect(foo.getClient()).toEqual({ y: 'bar', z: 'baz' });
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Foo {
#client

constructor(props) {
({x: this.#client = 5} = props);
}

getClient() {
return this.#client;
}
}

const foo = new Foo({});
expect(foo.getClient()).toEqual(5);
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Foo {
static #client

constructor(props) {
;({ client: Foo.#client } = props)
}

getClient() {
return Foo.#client;
}
}

const foo = new Foo({ client: 'bar' });
expect(foo.getClient()).toBe('bar');
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Foo {
#client

constructor(props) {
;({ client: this.#client } = props)
}

getClient() {
return this.#client;
}
}

const foo = new Foo({ client: 'bar' });
expect(foo.getClient()).toBe('bar');
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class Foo {
#bar;

test() {
return this.#bar;
}
}

expect(new Foo().test()).toBe(undefined);
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
class Foo {
#bar = "foo";

test() {
return this.#bar;
}

update() {
this.#bar++;
}

set(val) {
this.#bar = val;
}

static test(foo) {
return foo.#bar;
}

static update(foo) {
foo.#bar **= 2;
}
}

const f = new Foo();
expect(f.test()).toBe("foo");
expect(Foo.test(f)).toBe("foo");
expect("bar" in f).toBe(false);

f.set(1);
expect(f.test()).toBe(1);
f.update();
expect(Foo.test(f)).toBe(2);
Foo.update(f);
expect(f.test()).toBe(4);
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class Foo {
#x = 0;
#y = this.#x + 1;

test() {
return this.#y;
}
}

const f = new Foo();
expect(f.test()).toBe(1);
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
class Foo {
static #foo = "foo";
#bar = "bar";

static test() {
return Foo.#foo;
}

test() {
return this.#bar;
}
}

const f = new Foo();
expect("foo" in Foo).toBe(false)
expect("bar" in f).toBe(false)
expect(Foo.test()).toBe("foo")
expect(f.test()).toBe("bar")
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
class Foo {
#foo = 1;

test() {
class Nested {
#foo = 2;

[this.#foo]() {
}
}

return new Nested();
}
}

const f = new Foo();
expect(() => {
f.test();
}).toThrow();
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
class Foo {
#m;
init() {
this.#m = (...args) => args;
}
static test() {
const f = new Foo();
f.init();
return f.#m?.(...arguments);
}

static testNull() {
const f = new Foo();
return f.#m?.(...arguments);
}
}

expect(Foo.test(1, 2)).toEqual([1, 2]);
expect(Foo.testNull(1, 2)).toBe(undefined);
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
function classFactory() {
return class Foo {
#foo = "foo";
static #bar = "bar";

instance() {
return this.#foo;
}

static() {
return Foo.#bar;
}

static instance(inst) {
return inst.#foo;
}

static static() {
return Foo.#bar;
}
};
}

const Foo1 = classFactory();
const Foo2 = classFactory();

const f1 = new Foo1();
const f2 = new Foo2();

expect(f1.instance()).toBe("foo");
expect(f1.static()).toBe("bar");
expect(f2.instance()).toBe("foo");
expect(f2.static()).toBe("bar");

expect(Foo1.instance(f1)).toBe("foo");
expect(Foo1.static()).toBe("bar");
expect(Foo2.instance(f2)).toBe("foo");
expect(Foo2.static()).toBe("bar");

expect(() => {
f1.instance.call(f2), undefined;
}).toThrow();
expect(() => {
f2.instance.call(f1), undefined;
}).toThrow();
expect(() => {
Foo1.instance(f2), undefined;
}).toThrow();
expect(() => {
Foo2.instance(f1), undefined;
}).toThrow();
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class Foo {
static #foo = function(x) {
return x;
}

test(x) {
return Foo.#foo(x);
}
}

const f = new Foo;
const test = f.test();
expect(f.test("bar")).toBe("bar");
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
class Base {
static #foo = 1;

static getThis() {
return this.#foo;
}

static updateThis(val) {
return (this.#foo = val);
}

static getClass() {
return Base.#foo;
}

static updateClass(val) {
return (Base.#foo = val);
}
}

class Sub1 extends Base {
static #foo = 2;

static update(val) {
return (this.#foo = val);
}
}

class Sub2 extends Base {}

expect(Base.getThis()).toBe(1);
expect(Base.getClass()).toBe(1);
expect(() => Sub1.getThis()).toThrow();
expect(Sub1.getClass()).toBe(1);
expect(() => Sub2.getThis()).toThrow();
expect(Sub2.getClass()).toBe(1);

expect(Sub1.update(3)).toBe(3);
expect(Base.getThis()).toBe(1);
expect(Base.getClass()).toBe(1);
expect(() => Sub1.getThis()).toThrow();
expect(Sub1.getClass()).toBe(1);
expect(() => Sub2.getThis()).toThrow();
expect(Sub2.getClass()).toBe(1);

expect(Base.updateThis(4)).toBe(4);
expect(Base.getThis()).toBe(4);
expect(Base.getClass()).toBe(4);
expect(() => Sub1.getThis()).toThrow();
expect(Sub1.getClass()).toBe(4);
expect(() => Sub2.getThis()).toThrow();
expect(Sub2.getClass()).toBe(4);

expect(Base.updateClass(5)).toBe(5);
expect(Base.getThis()).toBe(5);
expect(Base.getClass()).toBe(5);
expect(() => Sub1.getThis()).toThrow();
expect(Sub1.getClass()).toBe(5);
expect(() => Sub2.getThis()).toThrow();
expect(Sub2.getClass()).toBe(5);

expect(() => Sub2.updateThis(6)).toThrow();
expect(Sub2.updateClass(7)).toBe(7);
expect(Base.getThis()).toBe(7);
expect(Base.getClass()).toBe(7);
expect(() => Sub1.getThis()).toThrow();
expect(Sub1.getClass()).toBe(7);
expect(() => Sub2.getThis()).toThrow();
expect(Sub2.getClass()).toBe(7);
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const f = class Foo {
static #x = Foo;
static y = Foo;

static extract() {
return {
x: Foo.#x,
y: Foo.y,
}
}
};

const { x, y } = f.extract();
expect(x).toBe(f)
expect(y).toBe(f)
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const f = class Foo {
static #bar() {
return Foo;
}

static #method() {
return function inner() {
return Foo;
};
}
static #method_shadowed() {
new Foo();
return function inner() {
let Foo = 3;
return Foo;
}
}

static extract() {
return {
bar: Foo.#bar,
method: Foo.#method,
method_shadowed: Foo.#method_shadowed
}
}
};

const { bar, method, method_shadowed } = f.extract();
expect(bar()).toBe(f)
expect(method()()).toBe(f)
expect(method_shadowed()()).toBe(3)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class Test {

static #x = 1

static method() {
const Test = 2;
const func = () => {
const Test = 3;
return this.#x + Test;
}
return func() + Test;
}
}

expect(Test.method()).toBe(6)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class A {
static #self = this;
static #getA = () => this;

static extract() {
return { self: A.#self, getA: A.#getA };
}
}

const { self, getA } = A.extract();

expect(self).toBe(A);
expect(getA()).toBe(A);
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class Foo {
static #bar;

static test() {
return Foo.#bar;
}

test() {
return Foo.#bar;
}
}

expect("bar" in Foo).toBe(false);
expect(Foo.test()).toBe(undefined);
expect(Foo.test()).toBe(undefined);
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class Foo {
static #tag = function () { return this };

static getReceiver() {
return this.#tag``;
}
}

expect(Foo.getReceiver()).toBe(Foo);
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
class Foo {
#tag() {
return this;
}

#tag2 = function() { return this; };

constructor() {
const receiver = this.#tag`tagged template`;
expect(receiver).toBe(this);

const receiver2 = this.#tag2`tagged template`;
expect(receiver2).toBe(this);
}
}

new Foo();
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
class Foo {
#foo = 0;

test(other) {
return [
this.#foo++,
this.#foo,
++this.#foo,
this.#foo,
other.obj.#foo++,
other.obj.#foo,
++other.obj.#foo,
other.obj.#foo,
];
}
}

const f = new Foo;
const results = f.test({ obj: f });
expect(results[0]).toBe(0);
expect(results[1]).toBe(1);
expect(results[2]).toBe(2);
expect(results[3]).toBe(2);
expect(results[4]).toBe(2);
expect(results[5]).toBe(3);
expect(results[6]).toBe(4);
expect(results[7]).toBe(4);
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
const actualOrder = [];

const track = i => {
actualOrder.push(i);
return i;
};

class MyClass {
static [track(1)] = track(10);
[track(2)] = track(13);
get [track(3)]() {
return "foo";
}
set [track(4)](value) {
this.bar = value;
}
[track(5)] = track(14);
static [track(6)] = track(11);
static [track(7)] = track(12);
[track(8)]() {}
[track(9)] = track(15);
}

const inst = new MyClass();

const expectedOrder = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
expect(actualOrder).toEqual(expectedOrder);

expect(MyClass[1]).toBe(10);
expect(inst[2]).toBe(13);
expect(inst[3]).toBe("foo");
inst[4] = "baz";
expect(inst.bar).toBe("baz");
expect(inst[5]).toBe(14);
expect(MyClass[6]).toBe(11);
expect(MyClass[7]).toBe(12);
expect(typeof inst[8]).toBe("function");
expect(inst[9]).toBe(15);
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
function test(x) {
class F {
[x] = 1;
constructor() {}
}

x = 'deadbeef';
expect(new F().foo).toBe(1);
x = 'wrong';
expect(new F().foo).toBe(1);
}

test('foo');
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class A {
static prop = 1;
}

class B extends A {
static prop = 2;
static propA = super.prop;
static getPropA = () => super.prop;
}

const { prop, propA, getPropA } = B;

expect(prop).toBe(2);
expect(propA).toBe(1);
expect(getPropA()).toBe(1);
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class A {
static self = this;
static getA = () => this;
}

const { self, getA } = A;

expect(self).toBe(A);
expect(getA()).toBe(A);
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class Foo {
static num;
}

expect("num" in Foo).toBe(true);
expect(Foo.num).toBeUndefined();
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class Foo {
static num = 0;
static str = "foo";
}

expect(Foo.num).toBe(0);
expect(Foo.num = 1).toBe(1);
expect(Foo.str).toBe("foo");
expect(Foo.str = "bar").toBe("bar");
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class Foo {
foo = function() {
return this;
}

test(other) {
return [this.foo(), other.foo()];
}
}

const f = new Foo;
const o = new Foo;
const test = f.test(o);
expect(test[0]).toBe(f);
expect(test[1]).toBe(o);
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
const actualOrder = [];

const track = i => {
actualOrder.push(i);
return i;
};

class MyClass {
static [track(1)] = track(10);
[track(2)] = track(13);
get [track(3)]() {
return "foo";
}
set [track(4)](value) {
this.bar = value;
}
[track(5)] = track(14);
static [track(6)] = track(11);
static [track(7)] = track(12);
[track(8)]() {}
[track(9)] = track(15);
}

const inst = new MyClass();

const expectedOrder = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
expect(actualOrder).toEqual(expectedOrder);

expect(MyClass[1]).toBe(10);
expect(inst[2]).toBe(13);
expect(inst[3]).toBe("foo");
inst[4] = "baz";
expect(inst.bar).toBe("baz");
expect(inst[5]).toBe(14);
expect(MyClass[6]).toBe(11);
expect(MyClass[7]).toBe(12);
expect(typeof inst[8]).toBe("function");
expect(inst[9]).toBe(15);
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const createClass = (k) => class { [k()] = 2 };

const clazz = createClass(() => 'foo');
const instance = new clazz();
expect(instance.foo).toBe(2);
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
function test(x) {
class F {
[x] = 1;
constructor() {}
}

x = 'deadbeef';
expect(new F().foo).toBe(1);
x = 'wrong';
expect(new F().foo).toBe(1);
}

test('foo');
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
class Foo {
static foo = "foo";
bar = "bar";

static test() {
return Foo.foo;
}

test() {
return this.bar;
}
}

const f = new Foo();
expect("foo" in Foo).toBe(true)
expect("bar" in f).toBe(true)
expect(Foo.test()).toBe("foo")
expect(f.test()).toBe("bar")
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class A {
static prop = 1;
}

class B extends A {
static prop = 2;
static propA = super.prop;
static getPropA = () => super.prop;
}

const { prop, propA, getPropA } = B;

expect(prop).toBe(2);
expect(propA).toBe(1);
expect(getPropA()).toBe(1);
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class A {
static self = this;
static getA = () => this;
}

const { self, getA } = A;

expect(self).toBe(A);
expect(getA()).toBe(A);
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class Foo {
static num;
}

expect("num" in Foo).toBe(true);
expect(Foo.num).toBeUndefined();
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class Foo {
static num = 0;
static str = "foo";
}

expect(Foo.num).toBe(0);
expect(Foo.num = 1).toBe(1);
expect(Foo.str).toBe("foo");
expect(Foo.str = "bar").toBe("bar");
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
class Foo {
foo = 0;

test(other) {
return [
this.foo++,
this.foo,
++this.foo,
this.foo,
other.obj.foo++,
other.obj.foo,
++other.obj.foo,
other.obj.foo,
];
}
}

const f = new Foo;
const results = f.test({ obj: f });
expect(results[0]).toBe(0);
expect(results[1]).toBe(1);
expect(results[2]).toBe(2);
expect(results[3]).toBe(2);
expect(results[4]).toBe(2);
expect(results[5]).toBe(3);
expect(results[6]).toBe(4);
expect(results[7]).toBe(4);
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
"use strict";
class C {
}

class A extends C {
field = 1;

constructor() {
super();

class B extends C {
constructor() {
super();

expect(this.field).toBeUndefined();
}
}

expect(this.field).toBe(1)

new B();
}
}

new A();

class Obj {
constructor() {
return {};
}
}

// ensure superClass is still transformed
class SuperClass extends Obj {
field = 1;

constructor() {
class B extends (super(), Obj) {
constructor() {
super();

expect(this.field).toBeUndefined()
}
}

expect(this.field).toBe(1)

new B();
}
}

new SuperClass();

// ensure ComputedKey Method is still transformed
class ComputedMethod extends Obj {
field = 1;

constructor() {
class B extends Obj {
constructor() {
super();

expect(this.field).toBeUndefined()
}

[super()]() { }
}

expect(this.field).toBe(1)

new B();
}
}

new ComputedMethod();


// ensure ComputedKey Field is still transformed
class ComputedField extends Obj {
field = 1;

constructor() {
class B extends Obj {
constructor() {
super();

expect(this.field).toBeUndefined()
}

[super()] = 1;
}

expect(this.field).toBe(1)

new B();
}
}

new ComputedField();
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const classes = [];
for (let i = 0; i <= 10; ++i) {
classes.push(
class A {
[i] = `computed field ${i}`;
static foo = `static field ${i}`;
#bar = `private field ${i}`;
getBar() {
return this.#bar;
}
}
);
}

for(let i=0; i<= 10; ++i) {
const clazz = classes[i];
expect(clazz.foo).toBe('static field ' + i);

const instance = new clazz();
expect(Object.getOwnPropertyNames(instance)).toEqual([String(i)])
expect(instance[i]).toBe('computed field ' + i);
expect(instance.getBar()).toBe('private field ' + i);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Foo {
static bar = 42;
static {
this.foo = Foo.bar;
}
}
expect(Foo.foo).toBe(42);
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Foo {
static bar = 42;
static {
this.foo = this.bar;
}
}
expect(Foo.foo).toBe(42);
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class Foo {
static {
this.foo = 42;
}
}
expect(Foo.foo).toBe(42);
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Foo extends class extends class Base {
static {
this.qux = 21;
}
} {
static {
this.bar = 21;
}
} {
static {
this.foo = this.bar + this.qux;
}
}
expect(Foo.foo).toBe(42);
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Foo {
static #bar = 21;
static {
this.foo = this.#bar;
this.qux1 = this.qux;
}
static qux = 21;
static {
this.qux2 = this.qux;
}
}
expect(Foo.foo).toBe(21);
expect(Foo.qux1).toBe(undefined);
expect(Foo.qux2).toBe(21);
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class Foo {
static #_ = 42;
// static block can not be tranformed as `#_` here
static {
this.foo = this.#_;
}
}
expect(Foo.foo).toBe(42);
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class Base {
constructor() {
this.Foo = class {
static {
this.foo = new.target;
}
}
}
}
expect((new Base).Foo.foo).toBe(undefined);
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Foo {
bar = 21;
static {
this.foo = this.bar;
}
}
expect(Foo.foo).toBe(undefined);
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
let getFoo;
class Foo {
static #foo = 42;
static {
getFoo = () => this.#foo;
}
}
expect(getFoo()).toBe(42);
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Foo {
static bar = 42;
static {
this.foo = Foo.bar;
}
}
expect(Foo.foo).toBe(42);
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Foo {
static bar = 42;
static {
this.foo = this.bar;
}
}
expect(Foo.foo).toBe(42);
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class Foo {
static {
this.foo = 42;
}
}
expect(Foo.foo).toBe(42);
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Foo extends class extends class Base {
static {
this.qux = 21;
}
} {
static {
this.bar = 21;
}
} {
static {
this.foo = this.bar + this.qux;
}
}
expect(Foo.foo).toBe(42);
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Foo {
static #bar = 21;
static {
this.foo = this.#bar;
this.qux1 = this.qux;
}
static qux = 21;
static {
this.qux2 = this.qux;
}
}
expect(Foo.foo).toBe(21);
expect(Foo.qux1).toBe(undefined);
expect(Foo.qux2).toBe(21);
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class Foo {
static #_ = 42;
// static block can not be tranformed as `#_` here
static {
this.foo = this.#_;
}
}
expect(Foo.foo).toBe(42);
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class Base {
constructor() {
this.Foo = class {
static {
this.foo = new.target;
}
}
}
}
expect((new Base).Foo.foo).toBe(undefined);
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Foo {
bar = 21;
static {
this.foo = this.bar;
}
}
expect(Foo.foo).toBe(undefined);
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Foo {
static bar = 42;
static {
this.foo = Foo.bar;
}
}
expect(Foo.foo).toBe(42);
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Foo {
static bar = 42;
static {
this.foo = this.bar;
}
}
expect(Foo.foo).toBe(42);
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class Foo {
static {
this.foo = 42;
}
}
expect(Foo.foo).toBe(42);
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Foo extends class extends class Base {
static {
this.qux = 21;
}
} {
static {
this.bar = 21;
}
} {
static {
this.foo = this.bar + this.qux;
}
}
expect(Foo.foo).toBe(42);
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Foo {
static #bar = 21;
static {
this.foo = this.#bar;
this.qux1 = this.qux;
}
static qux = 21;
static {
this.qux2 = this.qux;
}
}
expect(Foo.foo).toBe(21);
expect(Foo.qux1).toBe(undefined);
expect(Foo.qux2).toBe(21);
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class Foo {
static #_ = 42;
// static block can not be tranformed as `#_` here
static {
this.foo = this.#_;
}
}
expect(Foo.foo).toBe(42);
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class Base {
constructor() {
this.Foo = class {
static {
this.foo = new.target;
}
}
}
}
expect((new Base).Foo.foo).toBe(undefined);
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Foo {
bar = 21;
static {
this.foo = this.bar;
}
}
expect(Foo.foo).toBe(undefined);
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
var x = undefined;
var sets = 0;
var obj = {
get x() {
return x;
},

set x(value) {
sets++;
x = value;
},
};

expect(obj.x ??= 1).toBe(1);
expect(sets).toBe(1);
expect(obj.x ??= 2).toBe(1);
expect(sets).toBe(1);

var gets = 0;
var deep = {
get obj() {
gets++;
return obj;
},
};

obj.x = undefined;
expect(deep.obj.x ??= 1).toBe(1);
expect(gets).toBe(1);
expect(deep.obj.x ??= 2).toBe(1);
expect(gets).toBe(2);

var key = 0;
obj.x = undefined;
expect(obj[++key] ??= 1).toBe(1);
expect(key).toBe(1);
key = 0;
expect(obj[++key] ??= 2).toBe(1);
expect(key).toBe(1);

obj.x = undefined;
key = 0;
expect(deep.obj[++key] ??= 1).toBe(1);
expect(gets).toBe(3);
expect(key).toBe(1);
key = 0;
expect(deep.obj[++key] ??= 2).toBe(1);
expect(gets).toBe(4);
expect(key).toBe(1);
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
expect(null ?? undefined).toBeUndefined(undefined);
expect(undefined ?? null).toBeNull();
expect(false ?? true).toBe(false);
expect(0 ?? 1).toBe(0);
expect("" ?? "foo").toBe("");

var obj = { exists: true };
expect(obj.exists ?? false).toBe(true);
expect(obj.doesNotExist ?? "foo").toBe("foo");

var counter = 0;
function sideEffect() { return counter++; }
expect(sideEffect() ?? -1).toBe(0);

var counter2 = 0;
var obj2 = {
get foo() { return counter2++; }
};
expect(obj2.foo ?? -1).toBe(0);
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
expect(null ?? undefined).toBeUndefined(undefined);
expect(undefined ?? null).toBeNull();
expect(false ?? true).toBe(false);
expect(0 ?? 1).toBe(0);
expect("" ?? "foo").toBe("");

var obj = { exists: true };
expect(obj.exists ?? false).toBe(true);
expect(obj.doesNotExist ?? "foo").toBe("foo");

var counter = 0;
function sideEffect() { return counter++; }
expect(sideEffect() ?? -1).toBe(0);

var counter2 = 0;
var obj2 = {
get foo() { return counter2++; }
};
expect(obj2.foo ?? -1).toBe(0);
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
expect(9_007_199_254_740_993n).toBe(9007199254740993n);
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
expect(1_000).toBe(1000);
expect(0xAE_BE_CE).toBe(0xAEBECE);
expect(0b1010_0001_1000_0101).toBe(0b1010000110000101);
expect(0o0_6_6_6).toBe(0o0666);
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
expect(1_000).toBe(1000);
expect(0xAE_BE_CE).toBe(11452110);
expect(0b1010_0001_1000_0101).toBe(41349);
expect(0o0_6_6_6).toBe(438);
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const oldGOPDs = Object.getOwnPropertyDescriptors;
Object.getOwnPropertyDescriptors = null;

try {
({ ...{ a: 1 }, b: 1, ...{} });
} finally {
Object.getOwnPropertyDescriptors = oldGOPDs;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const oldGOPDs = Object.getOwnPropertyDescriptors;
Object.getOwnPropertyDescriptors = null;

try {
({ ...{ a: 1 }, b: 1, ...{} });
} finally {
Object.getOwnPropertyDescriptors = oldGOPDs;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
var key, x, y, z;
// impure
key = 1;
var { [key++]: y, ...x } = { 1: 1, a: 1 };
expect(x).toEqual({ a: 1 });
expect(key).toBe(2);
expect(1).toBe(y);

// takes care of the order

key = 1;
var { [++key]: y, [++key]: z, ...rest} = {2: 2, 3: 3};
expect(y).toBe(2);
expect(z).toBe(3);

// pure, computed property should remain as-is
key = 2;
({ [key]: y, z, ...x } = {2: "two", z: "zee"});
expect(y).toBe("two");
expect(x).toEqual({});
expect(z).toBe("zee");

// rhs evaluated before lhs
var order = [];
function left() {
order.push("left");
return 0;
}
function right() {
order.push("right");
return {};
}
var { [left()]: y, ...x} = right();
expect(order).toEqual(["right", "left"]);
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
var result = "";

var obj = {
get foo() {
result += "foo"
},
a: {
get bar() {
result += "bar";
}
},
b: {
get baz() {
result += "baz";
}
}
};

var { a: { ...bar }, b: { ...baz }, ...foo } = obj;

expect(result).toBe("barbazfoo");
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const a = {
"3": "three",
"foo": "bar"
}

const {
[3]: omit,
...rest
} = a;

expect(rest).toEqual({"foo": "bar"});
expect(omit).toBe("three");

const [k1, k2, k3, k4, k5] = [null, undefined, true, false, {toString() { return "warrior"; }}];
const c = {
[k1]: "1",
[k2]: "2",
[k3]: "3",
[k4]: "4",
[k5]: "5"
};

const {
[k1]: v1,
[k2]: v2,
[k3]: v3,
[k4]: v4,
[k5]: v5,
...vrest
} = c;

expect(v1).toBe("1");
expect(v2).toBe("2");
expect(v3).toBe("3");
expect(v4).toBe("4");
expect(v5).toBe("5");
expect(vrest).toEqual({});

// shouldn't convert symbols to strings
const sx = Symbol();
const sy = Symbol();

const d = {
[sx]: "sx",
[sy]: "sy"
}

const {
[sx]: dx,
[sy]: dy
} = d;

expect(dx).toBe("sx");
expect(dy).toBe("sy");
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
function sum(x, y, z) {
return x + y + z;
}
function test() {
var args = arguments;
return sum(...args);
}

expect(test(1, 2, 3)).toBe(6);
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const sym = Symbol("test");
const sym2 = Symbol("not enumerable");

const src = { a: "string" };
Object.defineProperty(src, "b", { value: "not enumerable" })
Object.defineProperty(src, sym, { enumerable: true, value: "symbol" });
Object.defineProperty(src, sym2, { value: "not enumerable" });

const {...rest} = src;

expect(rest[sym]).toBe("symbol");
expect(rest.a).toBe("string");
expect(Object.getOwnPropertyNames(rest)).toEqual(["a"]);
expect(Object.getOwnPropertySymbols(rest)).toEqual([sym]);

const { [sym]: dst, ...noSym } = src;

expect(dst).toBe("symbol");
expect(noSym.a).toBe("string");
expect(Object.getOwnPropertySymbols(noSym)).toEqual([]);
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// var { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };

// expect(x).toBe(1);
// expect(y).toBe(2);
// expect(z).toEqual({ a: 3, b: 4 });

// var complex = {
// x: { a: 1, b: 2, c: 3 },
// };

// var {
// x: { a: xa, ...xbc }
// } = complex;

// expect(xa).toBe(1);
// expect(xbc).toEqual({ b: 2, c: 3});

// // own properties
// function ownX({ ...properties }) {
// return properties.x;
// }
// expect(ownX(Object.create({ x: 1 }))).toBeUndefined();
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const oldGOPDs = Object.getOwnPropertyDescriptors;
Object.getOwnPropertyDescriptors = null;

try {
({ ...{ a: 1 }, b: 1, ...{} });
} finally {
Object.getOwnPropertyDescriptors = oldGOPDs;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
expect([...'']).toHaveLength(0);
expect([...'abc']).toHaveLength(3);
expect([...'def']).toMatchObject(['d','e','f']);
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const oldGOPDs = Object.getOwnPropertyDescriptors;
Object.getOwnPropertyDescriptors = null;

try {
({ ...{ a: 1 }, b: 1, ...{} });
} finally {
Object.getOwnPropertyDescriptors = oldGOPDs;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
expect([...'']).toHaveLength(0);
expect([...'abc']).toHaveLength(3);
expect([...'def']).toMatchObject(['d','e','f']);
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const oldGOPDs = Object.getOwnPropertyDescriptors;
Object.getOwnPropertyDescriptors = null;

try {
({ ...{ a: 1 }, b: 1, ...{} });
} finally {
Object.getOwnPropertyDescriptors = oldGOPDs;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"use strict";
Object.defineProperty(Object.prototype, 'NOSET', {
get(value) {
// noop
},
});

Object.defineProperty(Object.prototype, 'NOWRITE', {
writable: false,
value: 'abc',
});

const obj = { NOSET: 123 };
// this wouldn't work as expected if transformed as Object.assign (or equivalent)
// because those trigger object setters (spread don't)
const objSpread = { ...obj };
expect(objSpread).toHaveProperty('NOSET', 123);

const obj2 = { NOWRITE: 456 };
// this line would throw `TypeError: Cannot assign to read only property 'NOWRITE'`
// if transformed as Object.assign (or equivalent) because those use *assignment* for creating properties
// (spread defines them)
const obj2Spread = { ...obj2 };
expect(obj2Spread).toHaveProperty('NOWRITE', 456);

const KEY = Symbol('key');
const obj3Spread = { ...{ get foo () { return 'bar' } }, [KEY]: 'symbol' };
expect(Object.getOwnPropertyDescriptor(obj3Spread, 'foo').value).toBe('bar');
expect(Object.getOwnPropertyDescriptor(obj3Spread, KEY).value).toBe('symbol');

const obj4Spread = { ...Object.prototype };
expect(Object.getOwnPropertyDescriptor(obj4Spread, 'hasOwnProperty')).toBeUndefined();

expect(() => ({ ...null, ...undefined })).not.toThrow();

const o = Object.create(null);
o.a = 'foo';
o.__proto__ = [];
const o2 = { ...o };
expect(Array.isArray(Object.getPrototypeOf(o2))).toBe(false);
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
expect([...'']).toHaveLength(0);
expect([...'abc']).toHaveLength(3);
expect([...'def']).toMatchObject(['d','e','f']);
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const test = () => {
try {
throw 0;
}
catch {
return true;
}
}
expect(test()).toBe(true);

const test2 = () => {
try {
throw 0;
}
catch (err) {
return true;
}
}
expect(test2()).toBe(true);
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"use strict";

const obj = {
a: {
b: {
c: {
d: 2,
},
},
},
};

const a = obj?.a;
expect(a).toBe(obj.a);

const b = obj?.a?.b;
expect(b).toBe(obj.a.b);

const bad = obj?.b?.b;
expect(bad).toBeUndefined();

let val;
val = obj?.a?.b;
expect(val).toBe(obj.a.b);

expect(() => {
const bad = obj?.b.b;
}).toThrow();
Loading