diff --git a/Libraries/LibJS/Runtime/ReflectObject.cpp b/Libraries/LibJS/Runtime/ReflectObject.cpp index a36be0520e..3fd2dddb04 100644 --- a/Libraries/LibJS/Runtime/ReflectObject.cpp +++ b/Libraries/LibJS/Runtime/ReflectObject.cpp @@ -211,12 +211,12 @@ Value ReflectObject::has(Interpreter& interpreter) return Value(target->has_property(property_key)); } -Value ReflectObject::is_extensible(Interpreter&) +Value ReflectObject::is_extensible(Interpreter& interpreter) { - // FIXME: For this to be useful we need one of these: - // Object.seal(), Object.freeze(), Reflect.preventExtensions() - // For now we just return true, as that's always the case. - return Value(true); + auto* target = get_target_object_from(interpreter, "isExtensible"); + if (!target) + return {}; + return Value(target->is_extensible()); } Value ReflectObject::own_keys(Interpreter& interpreter) @@ -227,10 +227,12 @@ Value ReflectObject::own_keys(Interpreter& interpreter) return target->get_own_properties(*target, GetOwnPropertyMode::Key); } -Value ReflectObject::prevent_extensions(Interpreter&) +Value ReflectObject::prevent_extensions(Interpreter& interpreter) { - // FIXME: Implement me :^) - ASSERT_NOT_REACHED(); + auto* target = get_target_object_from(interpreter, "preventExtensions"); + if (!target) + return {}; + return Value(target->prevent_extensions()); } Value ReflectObject::set(Interpreter& interpreter) diff --git a/Libraries/LibJS/Tests/Reflect.isExtensible.js b/Libraries/LibJS/Tests/Reflect.isExtensible.js new file mode 100644 index 0000000000..104e725d7d --- /dev/null +++ b/Libraries/LibJS/Tests/Reflect.isExtensible.js @@ -0,0 +1,29 @@ +load("test-common.js"); + +try { + assert(Reflect.isExtensible.length === 1); + + [null, undefined, "foo", 123, NaN, Infinity].forEach(value => { + assertThrowsError(() => { + Reflect.isExtensible(value); + }, { + error: TypeError, + message: "First argument of Reflect.isExtensible() must be an object" + }); + }); + + assert(Reflect.isExtensible({}) === true); + + var o = {}; + o.foo = "foo"; + assert(o.foo === "foo"); + assert(Reflect.isExtensible(o) === true); + Reflect.preventExtensions(o); + o.bar = "bar"; + assert(o.bar === undefined); + assert(Reflect.isExtensible(o) === false); + + console.log("PASS"); +} catch (e) { + console.log("FAIL: " + e); +} diff --git a/Libraries/LibJS/Tests/Reflect.preventExtensions.js b/Libraries/LibJS/Tests/Reflect.preventExtensions.js new file mode 100644 index 0000000000..efbda277d4 --- /dev/null +++ b/Libraries/LibJS/Tests/Reflect.preventExtensions.js @@ -0,0 +1,23 @@ +load("test-common.js"); + +try { + assert(Reflect.preventExtensions.length === 1); + + [null, undefined, "foo", 123, NaN, Infinity].forEach(value => { + assertThrowsError(() => { + Reflect.preventExtensions(value); + }, { + error: TypeError, + message: "First argument of Reflect.preventExtensions() must be an object" + }); + }); + + var o = {}; + assert(Reflect.isExtensible(o) === true); + assert(Reflect.preventExtensions(o) === true); + assert(Reflect.isExtensible(o) === false); + + console.log("PASS"); +} catch (e) { + console.log("FAIL: " + e); +}