jscript: Add Object.freeze implementation.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2021-04-01 18:19:09 +02:00 committed by Alexandre Julliard
parent 7f1c98cac6
commit 0d3634b3ff
4 changed files with 79 additions and 0 deletions

View File

@ -2628,6 +2628,19 @@ HRESULT jsdisp_define_data_property(jsdisp_t *obj, const WCHAR *name, unsigned f
return jsdisp_define_property(obj, name, &prop_desc);
}
void jsdisp_freeze(jsdisp_t *obj)
{
unsigned int i;
for(i = 0; i < obj->prop_cnt; i++) {
if(obj->props[i].type == PROP_JSVAL)
obj->props[i].flags &= ~PROPF_WRITABLE;
obj->props[i].flags &= ~PROPF_CONFIGURABLE;
}
obj->extensible = FALSE;
}
HRESULT jsdisp_get_prop_name(jsdisp_t *obj, DISPID id, jsstr_t **r)
{
dispex_prop_t *prop = get_prop(obj, id);

View File

@ -317,6 +317,7 @@ HRESULT jsdisp_define_property(jsdisp_t*,const WCHAR*,property_desc_t*) DECLSPEC
HRESULT jsdisp_define_data_property(jsdisp_t*,const WCHAR*,unsigned,jsval_t) DECLSPEC_HIDDEN;
HRESULT jsdisp_next_prop(jsdisp_t*,DISPID,BOOL,DISPID*) DECLSPEC_HIDDEN;
HRESULT jsdisp_get_prop_name(jsdisp_t*,DISPID,jsstr_t**);
void jsdisp_freeze(jsdisp_t*) DECLSPEC_HIDDEN;
HRESULT create_builtin_function(script_ctx_t*,builtin_invoke_t,const WCHAR*,const builtin_info_t*,DWORD,
jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN;

View File

@ -693,6 +693,29 @@ static HRESULT Object_preventExtensions(script_ctx_t *ctx, vdisp_t *jsthis, WORD
return S_OK;
}
static HRESULT Object_freeze(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc,
jsval_t *argv, jsval_t *r)
{
jsdisp_t *obj;
if(!argc || !is_object_instance(argv[0]) || !get_object(argv[0])) {
WARN("argument is not an object\n");
return JS_E_OBJECT_EXPECTED;
}
TRACE("(%s)\n", debugstr_jsval(argv[0]));
obj = to_jsdisp(get_object(argv[0]));
if(!obj) {
FIXME("Non-JS object\n");
return E_NOTIMPL;
}
jsdisp_freeze(obj);
if(r) *r = jsval_obj(jsdisp_addref(obj));
return S_OK;
}
static HRESULT Object_isExtensible(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
{
jsdisp_t *obj;
@ -718,6 +741,7 @@ static const builtin_prop_t ObjectConstr_props[] = {
{L"create", Object_create, PROPF_ES5|PROPF_METHOD|2},
{L"defineProperties", Object_defineProperties, PROPF_ES5|PROPF_METHOD|2},
{L"defineProperty", Object_defineProperty, PROPF_ES5|PROPF_METHOD|2},
{L"freeze", Object_freeze, PROPF_ES5|PROPF_METHOD|1},
{L"getOwnPropertyDescriptor", Object_getOwnPropertyDescriptor, PROPF_ES5|PROPF_METHOD|2},
{L"getPrototypeOf", Object_getPrototypeOf, PROPF_ES5|PROPF_METHOD|1},
{L"isExtensible", Object_isExtensible, PROPF_ES5|PROPF_METHOD|1},

View File

@ -983,6 +983,47 @@ sync_test("preventExtensions", function() {
ok(Object.isExtensible.length === 1, "Object.isExtensible.length = " + Object.isExtensible.length);
});
sync_test("freeze", function() {
ok(Object.freeze.length === 1, "Object.freeze.length = " + Object.freeze.length);
try {
Object.freeze(1);
ok(false, "exception expected");
}catch(e) {
ok(e.name === "TypeError", "got " + e.name + " exception");
}
function f() {}
var o = {}, r;
o.prop = 1;
o.func = f;
Object.defineProperty(o, "accprop", {
get: function() {
return r;
},
set: function(v) {
r = v;
}
});
test_own_data_prop_desc(o, "prop", true, true, true);
r = Object.freeze(o);
ok(r === o, "r != o");
test_own_data_prop_desc(o, "prop", false, true, false);
test_own_data_prop_desc(o, "func", false, true, false);
ok(!Object.isExtensible(o), "o is still extensible");
o.prop = false;
o.func = false;
ok(o.prop === 1, "o.prop = " + o.prop);
ok(o.func === f, "o.func = " + o.func);
r = 1;
o.accprop = 2;
ok(r === 2, "r = " + r);
r = 3;
ok(o.accprop === 3, "o.accprop = " + o.accprop);
});
sync_test("head_setter", function() {
document.head = "";
ok(typeof(document.head) === "object", "typeof(document.head) = " + typeof(document.head));