123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- describe("basic usage", () => {
- test.xfailIf(isBytecodeInterpreterEnabled(), "using in normal for loop", () => {
- let isDisposed = false;
- let lastI = -1;
- for (
- using x = {
- i: 0,
- tick() {
- this.i++;
- },
- done() {
- return this.i === 3;
- },
- [Symbol.dispose]() {
- isDisposed = true;
- },
- };
- !x.done();
- x.tick()
- ) {
- expect(isDisposed).toBeFalse();
- expect(x.i).toBeGreaterThan(lastI);
- lastI = x.i;
- }
- expect(isDisposed).toBeTrue();
- expect(lastI).toBe(2);
- });
- test.xfailIf(isBytecodeInterpreterEnabled(), "using in normal for loop with expression body", () => {
- let isDisposed = false;
- let outerI = 0;
- for (
- using x = {
- i: 0,
- tick() {
- this.i++;
- outerI++;
- },
- done() {
- return this.i === 3;
- },
- [Symbol.dispose]() {
- isDisposed = true;
- },
- };
- !x.done();
- x.tick()
- )
- expect(isDisposed).toBeFalse();
- expect(isDisposed).toBeTrue();
- expect(outerI).toBe(3);
- });
- test.xfailIf(isBytecodeInterpreterEnabled(), "using in for of loop", () => {
- const disposable = [];
- const values = [];
- function createDisposable(value) {
- return {
- value: value,
- [Symbol.dispose]() {
- expect(this.value).toBe(value);
- disposable.push(value);
- }
- };
- }
- for (using a of [createDisposable('a'), createDisposable('b'), createDisposable('c')]) {
- expect(disposable).toEqual(values);
- values.push(a.value);
- }
- expect(disposable).toEqual(['a', 'b', 'c']);
- });
- test.xfailIf(isBytecodeInterpreterEnabled(), "using in for of loop with expression body", () => {
- let disposableCalls = 0;
- let i = 0;
- const obj = {
- [Symbol.dispose]() {
- disposableCalls++;
- }
- };
- for (using a of [obj, obj, obj])
- expect(disposableCalls).toBe(i++);
- expect(disposableCalls).toBe(3);
- });
- test.xfailIf(isBytecodeInterpreterEnabled(), "can have multiple declaration in normal for loop", () => {
- let disposed = 0;
- const a = {
- [Symbol.dispose]() {
- disposed++;
- }
- }
- expect(disposed).toBe(0);
- for (using b = a, c = a; false;)
- expect().fail();
- expect(disposed).toBe(2);
- });
- test.xfailIf(isBytecodeInterpreterEnabled(), "can have using in block in for loop", () => {
- const disposed = [];
- const values = [];
- for (let i = 0; i < 3; i++) {
- using a = {
- val: i,
- [Symbol.dispose]() {
- expect(i).toBe(this.val);
- disposed.push(i);
- },
- };
- expect(disposed).toEqual(values);
- values.push(i);
- }
- expect(disposed).toEqual([0, 1, 2]);
- });
- test.xfailIf(isBytecodeInterpreterEnabled(), "can have using in block in for-in loop", () => {
- const disposed = [];
- const values = [];
- for (const i in ['a', 'b', 'c']) {
- using a = {
- val: i,
- [Symbol.dispose]() {
- expect(i).toBe(this.val);
- disposed.push(i);
- },
- };
- expect(disposed).toEqual(values);
- values.push(i);
- }
- expect(disposed).toEqual(["0", "1", "2"]);
- });
- test.xfailIf(isBytecodeInterpreterEnabled(), "dispose is called even if throw in for of loop", () => {
- let disposableCalls = 0;
- const obj = {
- [Symbol.dispose]() {
- expect()
- disposableCalls++;
- }
- };
- try {
- for (using a of [obj])
- throw new ExpectationError("Expected in for-of");
- expect().fail("Should have thrown");
- } catch (e) {
- expect(e).toBeInstanceOf(ExpectationError);
- expect(e.message).toBe("Expected in for-of");
- expect(disposableCalls).toBe(1);
- }
- expect(disposableCalls).toBe(1);
- });
- });
- describe("using is still a valid variable in loops", () => {
- test("for loops var", () => {
- let enteredLoop = false;
- for (var using = 1; using < 2; using++) {
- enteredLoop = true;
- }
- expect(enteredLoop).toBeTrue();
- });
- test("for loops const", () => {
- let enteredLoop = false;
- for (const using = 1; using < 2; ) {
- enteredLoop = true;
- break;
- }
- expect(enteredLoop).toBeTrue();
- });
- test("for loops let", () => {
- let enteredLoop = false;
- for (let using = 1; using < 2; using++) {
- enteredLoop = true;
- }
- expect(enteredLoop).toBeTrue();
- });
- test("using in", () => {
- let enteredLoop = false;
- for (using in [1]) {
- enteredLoop = true;
- expect(using).toBe("0");
- }
- expect(enteredLoop).toBeTrue();
- });
- test("using of", () => {
- let enteredLoop = false;
- for (using of [1]) {
- enteredLoop = true;
- expect(using).toBe(1);
- }
- expect(enteredLoop).toBeTrue();
- });
- test.xfailIf(isBytecodeInterpreterEnabled(), "using using of", () => {
- let enteredLoop = false;
- for (using using of [null]) {
- enteredLoop = true;
- expect(using).toBeNull();
- }
- expect(enteredLoop).toBeTrue();
- });
- });
- describe("syntax errors", () => {
- test("cannot have using as for loop body", () => {
- expect("for (;;) using a = {};").not.toEval();
- expect("for (x in []) using a = {};").not.toEval();
- expect("for (x of []) using a = {};").not.toEval();
- });
- test("must have one declaration without initializer in for loop", () => {
- expect("for (using x = {} of []) {}").not.toEval();
- expect("for (using x, y of []) {}").not.toEval();
- });
- test("cannot have using in for-in loop", () => {
- expect("for (using x in []) {}").not.toEval();
- expect("for (using of in []) {}").not.toEval();
- expect("for (using in of []) {}").not.toEval();
- });
- });
|