123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- test("deleting object properties", () => {
- const o = {};
- o.x = 1;
- o.y = 2;
- o.z = 3;
- expect(Object.getOwnPropertyNames(o)).toHaveLength(3);
- expect(delete o.x).toBeTrue();
- expect(o.hasOwnProperty("x")).toBeFalse();
- expect(o.hasOwnProperty("y")).toBeTrue();
- expect(o.hasOwnProperty("z")).toBeTrue();
- expect(Object.getOwnPropertyNames(o)).toHaveLength(2);
- expect(delete o.y).toBeTrue();
- expect(o.hasOwnProperty("x")).toBeFalse();
- expect(o.hasOwnProperty("y")).toBeFalse();
- expect(o.hasOwnProperty("z")).toBeTrue();
- expect(Object.getOwnPropertyNames(o)).toHaveLength(1);
- expect(delete o.z).toBeTrue();
- expect(o.hasOwnProperty("x")).toBeFalse();
- expect(o.hasOwnProperty("y")).toBeFalse();
- expect(o.hasOwnProperty("z")).toBeFalse();
- expect(Object.getOwnPropertyNames(o)).toHaveLength(0);
- });
- test("deleting array indices", () => {
- const a = [3, 5, 7];
- expect(Object.getOwnPropertyNames(a)).toHaveLength(4);
- expect(delete a[0]).toBeTrue();
- expect(a.hasOwnProperty(0)).toBeFalse();
- expect(a.hasOwnProperty(1)).toBeTrue();
- expect(a.hasOwnProperty(2)).toBeTrue();
- expect(Object.getOwnPropertyNames(a)).toHaveLength(3);
- expect(delete a[1]).toBeTrue();
- expect(a.hasOwnProperty(0)).toBeFalse();
- expect(a.hasOwnProperty(1)).toBeFalse();
- expect(a.hasOwnProperty(2)).toBeTrue();
- expect(Object.getOwnPropertyNames(a)).toHaveLength(2);
- expect(delete a[2]).toBeTrue();
- expect(a.hasOwnProperty(0)).toBeFalse();
- expect(a.hasOwnProperty(1)).toBeFalse();
- expect(a.hasOwnProperty(2)).toBeFalse();
- expect(Object.getOwnPropertyNames(a)).toHaveLength(1);
- expect(delete a["42"]).toBeTrue();
- expect(Object.getOwnPropertyNames(a)).toHaveLength(1);
- });
- test("deleting non-configurable property", () => {
- const q = {};
- Object.defineProperty(q, "foo", { value: 1, writable: false, enumerable: false });
- expect(q.foo).toBe(1);
- expect(delete q.foo).toBeFalse();
- expect(q.hasOwnProperty("foo")).toBeTrue();
- });
- test("deleting non-configurable property throws in strict mode", () => {
- "use strict";
- const q = {};
- Object.defineProperty(q, "foo", { value: 1, writable: false, enumerable: false });
- expect(q.foo).toBe(1);
- expect(() => {
- delete q.foo;
- }).toThrowWithMessage(TypeError, "Cannot delete property 'foo' of [object Object]");
- expect(q.hasOwnProperty("foo")).toBeTrue();
- });
- test("deleting super property", () => {
- class A {
- foo() {}
- }
- class B extends A {
- bar() {
- delete super.foo;
- }
- baz() {
- delete super["foo"];
- }
- }
- class C {
- static foo() {
- delete super.bar;
- }
- }
- const obj = new B();
- expect(() => {
- obj.bar();
- }).toThrowWithMessage(ReferenceError, "Can't delete a property on 'super'");
- expect(() => {
- obj.baz();
- }).toThrowWithMessage(ReferenceError, "Can't delete a property on 'super'");
- Object.setPrototypeOf(C, null);
- expect(() => {
- C.foo();
- }).toThrowWithMessage(ReferenceError, "Can't delete a property on 'super'");
- });
- test("deleting an object computed property coerces the object to a property key", () => {
- let called = false;
- const obj = { prop1: 1, 2: 2 };
- function createToPrimitiveFunction(object, valueToReturn) {
- return function (hint) {
- called = true;
- console.log(this, object);
- expect(this).toBe(object);
- expect(hint).toBe("string");
- return valueToReturn;
- };
- }
- const a = {
- [Symbol.toPrimitive]: function (hint) {
- called = true;
- expect(this).toBe(a);
- expect(hint).toBe("string");
- return "prop1";
- },
- };
- const b = {
- [Symbol.toPrimitive]: function (hint) {
- called = true;
- expect(this).toBe(b);
- expect(hint).toBe("string");
- return 2;
- },
- };
- const c = {
- [Symbol.toPrimitive]: function (hint) {
- called = true;
- expect(this).toBe(c);
- expect(hint).toBe("string");
- return {};
- },
- };
- expect(Object.hasOwn(obj, "prop1")).toBeTrue();
- expect(Object.hasOwn(obj, 2)).toBeTrue();
- expect(delete obj[a]).toBeTrue();
- expect(called).toBeTrue();
- expect(Object.hasOwn(obj, "prop1")).toBeFalse();
- expect(Object.hasOwn(obj, 2)).toBeTrue();
- expect(obj.prop1).toBeUndefined();
- expect(obj[2]).toBe(2);
- called = false;
- expect(delete obj[b]).toBeTrue();
- expect(called).toBeTrue();
- expect(Object.hasOwn(obj, "prop1")).toBeFalse();
- expect(Object.hasOwn(obj, 2)).toBeFalse();
- expect(obj.prop1).toBeUndefined();
- expect(obj[2]).toBeUndefined();
- called = false;
- expect(() => {
- delete obj[c];
- }).toThrowWithMessage(
- TypeError,
- `Can't convert [object Object] to primitive with hint "string", its @@toPrimitive method returned an object`
- );
- expect(called).toBeTrue();
- });
- test("deleting a symbol returned by @@toPrimitive", () => {
- let called = false;
- const obj = { [Symbol.toStringTag]: "hello world" };
- const a = {
- [Symbol.toPrimitive]: function (hint) {
- called = true;
- expect(this).toBe(a);
- expect(hint).toBe("string");
- return Symbol.toStringTag;
- },
- };
- expect(Object.hasOwn(obj, Symbol.toStringTag)).toBeTrue();
- expect(delete obj[a]).toBeTrue();
- expect(called).toBeTrue();
- expect(Object.hasOwn(obj, Symbol.toStringTag)).toBeFalse();
- expect(obj[Symbol.toStringTag]).toBeUndefined();
- });
- // FIXME: This currently does not work with the AST interpreter, but works with Bytecode.
- test.skip("delete always evaluates the lhs", () => {
- const obj = { prop: 1 };
- let called = false;
- function a() {
- called = true;
- return obj;
- }
- expect(delete a()).toBeTrue();
- expect(called).toBeTrue();
- expect(obj).toBeDefined();
- expect(Object.hasOwn(obj, "prop")).toBeTrue();
- expect(obj.prop).toBe(1);
- called = false;
- expect(delete a().prop).toBeTrue();
- expect(called).toBeTrue();
- expect(obj).toBeDefined();
- expect(Object.hasOwn(obj, "prop")).toBeFalse();
- expect(obj.prop).toBeUndefined();
- let b = 1;
- expect(delete ++b).toBeTrue();
- expect(b).toBe(2);
- expect(delete b++).toBeTrue();
- expect(b).toBe(3);
- let c = { d: 1 };
- expect(delete (b = c)).toBeTrue();
- expect(b).toBeDefined();
- expect(c).toBeDefined();
- expect(b).toBe(c);
- function d() {
- throw new Error("called");
- }
- expect(() => {
- delete d();
- }).toThrowWithMessage(Error, "called");
- expect(() => {
- delete d().stack;
- }).toThrowWithMessage(Error, "called");
- expect(() => {
- delete ~d();
- }).toThrowWithMessage(Error, "called");
- expect(() => {
- delete new d();
- }).toThrowWithMessage(Error, "called");
- });
|