Module: wine Branch: master Commit: 0d3634b3ffb1fe4d58a883244c9ab74b370f8aa1 URL: https://source.winehq.org/git/wine.git/?a=commit;h=0d3634b3ffb1fe4d58a883244...
Author: Jacek Caban jacek@codeweavers.com Date: Thu Apr 1 18:19:09 2021 +0200
jscript: Add Object.freeze implementation.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/jscript/dispex.c | 13 +++++++++++++ dlls/jscript/jscript.h | 1 + dlls/jscript/object.c | 24 ++++++++++++++++++++++++ dlls/mshtml/tests/es5.js | 41 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 9b11f607791..57f5d09daee 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -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); diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 750158aabd9..d4ebb3246dd 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -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; diff --git a/dlls/jscript/object.c b/dlls/jscript/object.c index 8ff040853ef..3dcfd297a9b 100644 --- a/dlls/jscript/object.c +++ b/dlls/jscript/object.c @@ -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}, diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index 5851278e983..ae73d435456 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -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));