mirror of
				https://github.com/LadybirdBrowser/ladybird.git
				synced 2025-11-03 23:00:58 +00:00 
			
		
		
		
	
		
			
	
	
		
			425 lines
		
	
	
	
		
			13 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			425 lines
		
	
	
	
		
			13 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 
								 | 
							
								"use strict";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Note the globalThisValue and globalObject do not need to be the same.
							 | 
						||
| 
								 | 
							
								const globalThisValue = this;
							 | 
						||
| 
								 | 
							
								const globalObject = (0, eval)("this");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// These tests are done in global state to ensure that is possible
							 | 
						||
| 
								 | 
							
								const globalArrow = () => {
							 | 
						||
| 
								 | 
							
								    expect(this).toBe(globalThisValue);
							 | 
						||
| 
								 | 
							
								    return this;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function globalFunction() {
							 | 
						||
| 
								 | 
							
								    expect(this).toBe(undefined);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    expect(globalArrow()).toBe(globalThisValue);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const arrowInGlobalFunction = () => this;
							 | 
						||
| 
								 | 
							
								    expect(arrowInGlobalFunction()).toBe(undefined);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return arrowInGlobalFunction;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								expect(globalArrow()).toBe(globalThisValue);
							 | 
						||
| 
								 | 
							
								expect(globalFunction()()).toBe(undefined);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const arrowFromGlobalFunction = globalFunction();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const customThisValue = {
							 | 
						||
| 
								 | 
							
								    isCustomThis: true,
							 | 
						||
| 
								 | 
							
								    variant: 0,
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const otherCustomThisValue = {
							 | 
						||
| 
								 | 
							
								    isCustomThis: true,
							 | 
						||
| 
								 | 
							
								    variant: 1,
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								describe("describe with arrow function", () => {
							 | 
						||
| 
								 | 
							
								    expect(this).toBe(globalThisValue);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    test("nested test with normal function should get global object", function () {
							 | 
						||
| 
								 | 
							
								        expect(this).toBe(undefined);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    test("nested test with arrow function should get same this value as enclosing function", () => {
							 | 
						||
| 
								 | 
							
								        expect(this).toBe(globalThisValue);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								describe("describe with normal function", function () {
							 | 
						||
| 
								 | 
							
								    expect(this).toBe(undefined);
							 | 
						||
| 
								 | 
							
								    test("nested test with normal function should get global object", function () {
							 | 
						||
| 
								 | 
							
								        expect(this).toBe(undefined);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    test("nested test with arrow function should get same this value as enclosing function", () => {
							 | 
						||
| 
								 | 
							
								        expect(this).toBe(undefined);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								describe("basic behavior", () => {
							 | 
						||
| 
								 | 
							
								    expect(this).toBe(globalThisValue);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    expect(arrowFromGlobalFunction()).toBeUndefined();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    expect(customThisValue).not.toBe(otherCustomThisValue);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    test("binding arrow function does not influence this value", () => {
							 | 
						||
| 
								 | 
							
								        const boundGlobalArrow = globalArrow.bind({ shouldNotBeHere: true });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        expect(boundGlobalArrow()).toBe(globalThisValue);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function functionInArrow() {
							 | 
						||
| 
								 | 
							
								        expect(arrowFromGlobalFunction()).toBeUndefined();
							 | 
						||
| 
								 | 
							
								        return this;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function functionWithArrow() {
							 | 
						||
| 
								 | 
							
								        expect(arrowFromGlobalFunction()).toBeUndefined();
							 | 
						||
| 
								 | 
							
								        return () => {
							 | 
						||
| 
								 | 
							
								            expect(arrowFromGlobalFunction()).toBeUndefined();
							 | 
						||
| 
								 | 
							
								            return this;
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function strictFunction() {
							 | 
						||
| 
								 | 
							
								        "use strict";
							 | 
						||
| 
								 | 
							
								        return this;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    test("functions get globalObject as this value", () => {
							 | 
						||
| 
								 | 
							
								        expect(functionInArrow()).toBeUndefined();
							 | 
						||
| 
								 | 
							
								        expect(functionWithArrow()()).toBeUndefined();
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    test("strict functions get undefined as this value", () => {
							 | 
						||
| 
								 | 
							
								        expect(strictFunction()).toBeUndefined();
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    test("bound function gets overwritten this value", () => {
							 | 
						||
| 
								 | 
							
								        const boundFunction = functionInArrow.bind(customThisValue);
							 | 
						||
| 
								 | 
							
								        expect(boundFunction()).toBe(customThisValue);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const boundFunctionWithArrow = functionWithArrow.bind(customThisValue);
							 | 
						||
| 
								 | 
							
								        expect(boundFunctionWithArrow()()).toBe(customThisValue);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // However we cannot bind the arrow function itself
							 | 
						||
| 
								 | 
							
								        const failingArrowBound = boundFunctionWithArrow().bind(otherCustomThisValue);
							 | 
						||
| 
								 | 
							
								        expect(failingArrowBound()).toBe(customThisValue);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const boundStrictFunction = strictFunction.bind(customThisValue);
							 | 
						||
| 
								 | 
							
								        expect(boundStrictFunction()).toBe(customThisValue);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								describe("functions on created objects", () => {
							 | 
						||
| 
								 | 
							
								    const obj = {
							 | 
						||
| 
								 | 
							
								        func: function () {
							 | 
						||
| 
								 | 
							
								            expect(arrowFromGlobalFunction()).toBeUndefined();
							 | 
						||
| 
								 | 
							
								            return this;
							 | 
						||
| 
								 | 
							
								        },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        funcWithArrow: function () {
							 | 
						||
| 
								 | 
							
								            expect(arrowFromGlobalFunction()).toBeUndefined();
							 | 
						||
| 
								 | 
							
								            return () => this;
							 | 
						||
| 
								 | 
							
								        },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        arrow: () => {
							 | 
						||
| 
								 | 
							
								            expect(arrowFromGlobalFunction()).toBeUndefined();
							 | 
						||
| 
								 | 
							
								            return this;
							 | 
						||
| 
								 | 
							
								        },
							 | 
						||
| 
								 | 
							
								        otherProperty: "yes",
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    test("function get this value of associated object", () => {
							 | 
						||
| 
								 | 
							
								        expect(obj.func()).toBe(obj);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    test("arrow function on object get above this value", () => {
							 | 
						||
| 
								 | 
							
								        expect(obj.arrow()).toBe(globalThisValue);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    test("arrow function from normal function from object has object as this value", () => {
							 | 
						||
| 
								 | 
							
								        expect(obj.funcWithArrow()()).toBe(obj);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    test("bound overwrites value of normal object function", () => {
							 | 
						||
| 
								 | 
							
								        const boundFunction = obj.func.bind(customThisValue);
							 | 
						||
| 
								 | 
							
								        expect(boundFunction()).toBe(customThisValue);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const boundFunctionWithArrow = obj.funcWithArrow.bind(customThisValue);
							 | 
						||
| 
								 | 
							
								        expect(boundFunctionWithArrow()()).toBe(customThisValue);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const boundArrowFunction = obj.arrow.bind(customThisValue);
							 | 
						||
| 
								 | 
							
								        expect(boundArrowFunction()).toBe(globalThisValue);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    test("also works for object defined in function", () => {
							 | 
						||
| 
								 | 
							
								        (function () {
							 | 
						||
| 
								 | 
							
								            expect(arrowFromGlobalFunction()).toBeUndefined();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            // It is bound below
							 | 
						||
| 
								 | 
							
								            expect(this).toBe(customThisValue);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            const obj2 = {
							 | 
						||
| 
								 | 
							
								                func: function () {
							 | 
						||
| 
								 | 
							
								                    expect(arrowFromGlobalFunction()).toBeUndefined();
							 | 
						||
| 
								 | 
							
								                    return this;
							 | 
						||
| 
								 | 
							
								                },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                arrow: () => {
							 | 
						||
| 
								 | 
							
								                    expect(arrowFromGlobalFunction()).toBeUndefined();
							 | 
						||
| 
								 | 
							
								                    return this;
							 | 
						||
| 
								 | 
							
								                },
							 | 
						||
| 
								 | 
							
								                otherProperty: "also",
							 | 
						||
| 
								 | 
							
								            };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            expect(obj2.func()).toBe(obj2);
							 | 
						||
| 
								 | 
							
								            expect(obj2.arrow()).toBe(customThisValue);
							 | 
						||
| 
								 | 
							
								        }.bind(customThisValue)());
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								describe("behavior with classes", () => {
							 | 
						||
| 
								 | 
							
								    class Basic {
							 | 
						||
| 
								 | 
							
								        constructor(value) {
							 | 
						||
| 
								 | 
							
								            expect(this).toBeInstanceOf(Basic);
							 | 
						||
| 
								 | 
							
								            this.arrowFunctionInClass = () => {
							 | 
						||
| 
								 | 
							
								                return this;
							 | 
						||
| 
								 | 
							
								            };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            this.value = value;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            expect(arrowFromGlobalFunction()).toBeUndefined();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        func() {
							 | 
						||
| 
								 | 
							
								            expect(arrowFromGlobalFunction()).toBeUndefined();
							 | 
						||
| 
								 | 
							
								            return this;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const basic = new Basic(14);
							 | 
						||
| 
								 | 
							
								    const basic2 = new Basic(457);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    expect(basic).not.toBe(basic2);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    test("calling functions on class should give instance as this value", () => {
							 | 
						||
| 
								 | 
							
								        expect(basic.func()).toBe(basic);
							 | 
						||
| 
								 | 
							
								        expect(basic2.func()).toBe(basic2);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    test("calling arrow function created in constructor should give instance as this value", () => {
							 | 
						||
| 
								 | 
							
								        expect(basic.arrowFunctionInClass()).toBe(basic);
							 | 
						||
| 
								 | 
							
								        expect(basic2.arrowFunctionInClass()).toBe(basic2);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    test("can bind function in class", () => {
							 | 
						||
| 
								 | 
							
								        const boundFunction = basic.func.bind(customThisValue);
							 | 
						||
| 
								 | 
							
								        expect(boundFunction()).toBe(customThisValue);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const boundFunction2 = basic2.func.bind(otherCustomThisValue);
							 | 
						||
| 
								 | 
							
								        expect(boundFunction2()).toBe(otherCustomThisValue);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								describe("derived classes behavior", () => {
							 | 
						||
| 
								 | 
							
								    class Base {
							 | 
						||
| 
								 | 
							
								        baseFunction() {
							 | 
						||
| 
								 | 
							
								            expect(arrowFromGlobalFunction()).toBeUndefined();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            return this;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    class Derived extends Base {
							 | 
						||
| 
								 | 
							
								        constructor(value) {
							 | 
						||
| 
								 | 
							
								            expect(arrowFromGlobalFunction()).toBeUndefined();
							 | 
						||
| 
								 | 
							
								            const arrowMadeBeforeSuper = () => {
							 | 
						||
| 
								 | 
							
								                expect(this).toBeInstanceOf(Derived);
							 | 
						||
| 
								 | 
							
								                return this;
							 | 
						||
| 
								 | 
							
								            };
							 | 
						||
| 
								 | 
							
								            super();
							 | 
						||
| 
								 | 
							
								            expect(arrowMadeBeforeSuper()).toBe(this);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            this.arrowMadeBeforeSuper = arrowMadeBeforeSuper;
							 | 
						||
| 
								 | 
							
								            this.arrowMadeAfterSuper = () => {
							 | 
						||
| 
								 | 
							
								                expect(this).toBeInstanceOf(Derived);
							 | 
						||
| 
								 | 
							
								                return this;
							 | 
						||
| 
								 | 
							
								            };
							 | 
						||
| 
								 | 
							
								            this.value = value;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        derivedFunction() {
							 | 
						||
| 
								 | 
							
								            expect(arrowFromGlobalFunction()).toBeUndefined();
							 | 
						||
| 
								 | 
							
								            return this;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    test("can create derived with arrow functions using this before super", () => {
							 | 
						||
| 
								 | 
							
								        const testDerived = new Derived(-89);
							 | 
						||
| 
								 | 
							
								        expect(testDerived.arrowMadeBeforeSuper()).toBe(testDerived);
							 | 
						||
| 
								 | 
							
								        expect(testDerived.arrowMadeAfterSuper()).toBe(testDerived);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    test("base and derived functions get correct this values", () => {
							 | 
						||
| 
								 | 
							
								        const derived = new Derived(12);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        expect(derived.derivedFunction()).toBe(derived);
							 | 
						||
| 
								 | 
							
								        expect(derived.baseFunction()).toBe(derived);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    test("can bind derived and base functions", () => {
							 | 
						||
| 
								 | 
							
								        const derived = new Derived(846);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const boundDerivedFunction = derived.derivedFunction.bind(customThisValue);
							 | 
						||
| 
								 | 
							
								        expect(boundDerivedFunction()).toBe(customThisValue);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const boundBaseFunction = derived.baseFunction.bind(otherCustomThisValue);
							 | 
						||
| 
								 | 
							
								        expect(boundBaseFunction()).toBe(otherCustomThisValue);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								describe("proxy behavior", () => {
							 | 
						||
| 
								 | 
							
								    test("with no handler it makes no difference", () => {
							 | 
						||
| 
								 | 
							
								        const globalArrowProxyNoHandler = new Proxy(globalArrow, {});
							 | 
						||
| 
								 | 
							
								        expect(globalArrowProxyNoHandler()).toBe(globalThisValue);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    test("proxy around global arrow still gives correct this value", () => {
							 | 
						||
| 
								 | 
							
								        let lastThisArg = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const handler = {
							 | 
						||
| 
								 | 
							
								            apply(target, thisArg, argArray) {
							 | 
						||
| 
								 | 
							
								                expect(target).toBe(globalArrow);
							 | 
						||
| 
								 | 
							
								                lastThisArg = thisArg;
							 | 
						||
| 
								 | 
							
								                expect(this).toBe(handler);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                return target(...argArray);
							 | 
						||
| 
								 | 
							
								            },
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const globalArrowProxy = new Proxy(globalArrow, handler);
							 | 
						||
| 
								 | 
							
								        expect(globalArrowProxy()).toBe(globalThisValue);
							 | 
						||
| 
								 | 
							
								        expect(lastThisArg).toBeUndefined();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const boundProxy = globalArrowProxy.bind(customThisValue);
							 | 
						||
| 
								 | 
							
								        expect(boundProxy()).toBe(globalThisValue);
							 | 
						||
| 
								 | 
							
								        expect(lastThisArg).toBe(customThisValue);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        expect(globalArrowProxy.call(15)).toBe(globalThisValue);
							 | 
						||
| 
								 | 
							
								        expect(lastThisArg).toBe(15);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								describe("derived classes which access this before super should fail", () => {
							 | 
						||
| 
								 | 
							
								    class Base {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    test("direct access of this should throw reference error", () => {
							 | 
						||
| 
								 | 
							
								        class IncorrectConstructor extends Base {
							 | 
						||
| 
								 | 
							
								            constructor() {
							 | 
						||
| 
								 | 
							
								                this.something = "this will fail";
							 | 
						||
| 
								 | 
							
								                super();
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        expect(() => {
							 | 
						||
| 
								 | 
							
								            new IncorrectConstructor();
							 | 
						||
| 
								 | 
							
								        }).toThrowWithMessage(ReferenceError, "|this| has not been initialized");
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    test("access of this via a arrow function", () => {
							 | 
						||
| 
								 | 
							
								        class IncorrectConstructor extends Base {
							 | 
						||
| 
								 | 
							
								            constructor() {
							 | 
						||
| 
								 | 
							
								                const arrow = () => this;
							 | 
						||
| 
								 | 
							
								                arrow();
							 | 
						||
| 
								 | 
							
								                super();
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        expect(() => {
							 | 
						||
| 
								 | 
							
								            new IncorrectConstructor();
							 | 
						||
| 
								 | 
							
								        }).toThrowWithMessage(ReferenceError, "|this| has not been initialized");
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    test("access of this via a eval", () => {
							 | 
						||
| 
								 | 
							
								        class IncorrectConstructor extends Base {
							 | 
						||
| 
								 | 
							
								            constructor() {
							 | 
						||
| 
								 | 
							
								                eval("this.foo = 'bar'");
							 | 
						||
| 
								 | 
							
								                super();
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        expect(() => {
							 | 
						||
| 
								 | 
							
								            new IncorrectConstructor();
							 | 
						||
| 
								 | 
							
								        }).toThrowWithMessage(ReferenceError, "|this| has not been initialized");
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    test.skip("access of this via a eval in arrow function", () => {
							 | 
						||
| 
								 | 
							
								        class IncorrectConstructor extends Base {
							 | 
						||
| 
								 | 
							
								            constructor() {
							 | 
						||
| 
								 | 
							
								                const arrow = () => eval("() => this")();
							 | 
						||
| 
								 | 
							
								                arrow();
							 | 
						||
| 
								 | 
							
								                super();
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        expect(() => {
							 | 
						||
| 
								 | 
							
								            new IncorrectConstructor();
							 | 
						||
| 
								 | 
							
								        }).toThrowWithMessage(ReferenceError, "|this| has not been initialized");
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    test("access of this via arrow function even if bound with something else", () => {
							 | 
						||
| 
								 | 
							
								        class IncorrectConstructor extends Base {
							 | 
						||
| 
								 | 
							
								            constructor() {
							 | 
						||
| 
								 | 
							
								                const arrow = () => this;
							 | 
						||
| 
								 | 
							
								                const boundArrow = arrow.bind(customThisValue);
							 | 
						||
| 
								 | 
							
								                boundArrow();
							 | 
						||
| 
								 | 
							
								                super();
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        expect(() => {
							 | 
						||
| 
								 | 
							
								            new IncorrectConstructor();
							 | 
						||
| 
								 | 
							
								        }).toThrowWithMessage(ReferenceError, "|this| has not been initialized");
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								describe("in strict mode primitive this values are not converted to objects", () => {
							 | 
						||
| 
								 | 
							
								    const array = [true, false];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Technically the comma is implementation defined here. (Also for tests below.)
							 | 
						||
| 
								 | 
							
								    expect(array.toLocaleString()).toBe("true,false");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    test("directly overwriting toString", () => {
							 | 
						||
| 
								 | 
							
								        let count = 0;
							 | 
						||
| 
								 | 
							
								        Boolean.prototype.toString = function () {
							 | 
						||
| 
								 | 
							
								            count++;
							 | 
						||
| 
								 | 
							
								            return typeof this;
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        expect(array.toLocaleString()).toBe("boolean,boolean");
							 | 
						||
| 
								 | 
							
								        expect(count).toBe(2);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    test("overwriting toString with a getter", () => {
							 | 
						||
| 
								 | 
							
								        let count = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Object.defineProperty(Boolean.prototype, "toString", {
							 | 
						||
| 
								 | 
							
								            get() {
							 | 
						||
| 
								 | 
							
								                count++;
							 | 
						||
| 
								 | 
							
								                const that = typeof this;
							 | 
						||
| 
								 | 
							
								                return function () {
							 | 
						||
| 
								 | 
							
								                    return that;
							 | 
						||
| 
								 | 
							
								                };
							 | 
						||
| 
								 | 
							
								            },
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        expect(array.toLocaleString()).toBe("boolean,boolean");
							 | 
						||
| 
								 | 
							
								        expect(count).toBe(2);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								});
							 |