Jacek Caban : jscript: Add Object.isFrozen and Object.isSealed implementation.

Alexandre Julliard julliard at winehq.org
Fri Apr 2 16:10:12 CDT 2021


Module: wine
Branch: master
Commit: 1f49903e66b0a401e47e5951634c804a4b0d242c
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=1f49903e66b0a401e47e5951634c804a4b0d242c

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Fri Apr  2 20:24:37 2021 +0200

jscript: Add Object.isFrozen and Object.isSealed implementation.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/jscript/dispex.c    | 20 ++++++++++++++
 dlls/jscript/jscript.h   |  1 +
 dlls/jscript/object.c    | 46 ++++++++++++++++++++++++++++++++
 dlls/mshtml/tests/es5.js | 68 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 135 insertions(+)

diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c
index b62fcee0b04..188de659c4a 100644
--- a/dlls/jscript/dispex.c
+++ b/dlls/jscript/dispex.c
@@ -2646,6 +2646,26 @@ void jsdisp_freeze(jsdisp_t *obj, BOOL seal)
     obj->extensible = FALSE;
 }
 
+BOOL jsdisp_is_frozen(jsdisp_t *obj, BOOL sealed)
+{
+    unsigned int i;
+
+    if(obj->extensible)
+        return FALSE;
+
+    for(i = 0; i < obj->prop_cnt; i++) {
+        if(obj->props[i].type == PROP_JSVAL) {
+            if(!sealed && (obj->props[i].flags & PROPF_WRITABLE))
+                return FALSE;
+        }else if(obj->props[i].type != PROP_ACCESSOR)
+            continue;
+        if(obj->props[i].flags & PROPF_CONFIGURABLE)
+            return FALSE;
+    }
+
+    return TRUE;
+}
+
 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 ec5001af117..3c870a68a54 100644
--- a/dlls/jscript/jscript.h
+++ b/dlls/jscript/jscript.h
@@ -318,6 +318,7 @@ HRESULT jsdisp_define_data_property(jsdisp_t*,const WCHAR*,unsigned,jsval_t) DEC
 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*,BOOL) DECLSPEC_HIDDEN;
+BOOL jsdisp_is_frozen(jsdisp_t*,BOOL) 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 86c656a719a..b957ea58bdf 100644
--- a/dlls/jscript/object.c
+++ b/dlls/jscript/object.c
@@ -760,6 +760,50 @@ static HRESULT Object_isExtensible(script_ctx_t *ctx, vdisp_t *jsthis, WORD flag
     return S_OK;
 }
 
+static HRESULT Object_isFrozen(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;
+    }
+
+    if(r) *r = jsval_bool(jsdisp_is_frozen(obj, FALSE));
+    return S_OK;
+}
+
+static HRESULT Object_isSealed(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;
+    }
+
+    if(r) *r = jsval_bool(jsdisp_is_frozen(obj, TRUE));
+    return S_OK;
+}
+
 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},
@@ -768,6 +812,8 @@ static const builtin_prop_t ObjectConstr_props[] = {
     {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},
+    {L"isFrozen",                 Object_isFrozen,                    PROPF_ES5|PROPF_METHOD|1},
+    {L"isSealed",                 Object_isSealed,                    PROPF_ES5|PROPF_METHOD|1},
     {L"keys",                     Object_keys,                        PROPF_ES5|PROPF_METHOD|1},
     {L"preventExtensions",        Object_preventExtensions,           PROPF_ES5|PROPF_METHOD|1},
     {L"seal",                     Object_seal,                        PROPF_ES5|PROPF_METHOD|1},
diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js
index 9227fa7e5a5..474c09d3bd7 100644
--- a/dlls/mshtml/tests/es5.js
+++ b/dlls/mshtml/tests/es5.js
@@ -1104,6 +1104,74 @@ sync_test("seal", function() {
     ok(o.length === 1, "o.length = " + o.length);
 });
 
+sync_test("isFrozen", function() {
+    ok(Object.isFrozen.length === 1, "Object.isFrozen.length = " + Object.isFrozen.length);
+    ok(Object.isSealed.length === 1, "Object.isSealed.length = " + Object.isSealed.length);
+
+    var o = Object.freeze({});
+    ok(Object.isFrozen(o) === true, "o is not frozen");
+    ok(Object.isSealed(o) === true, "o is not sealed");
+    ok(Object.isExtensible(o) === false, "o is extensible");
+
+    ok(Object.isFrozen({}) === false, "{} is frozen");
+    ok(Object.isSealed({}) === false, "{} is sealed");
+
+    o = Object.preventExtensions({});
+    ok(Object.isFrozen(o) === true, "o is not frozen");
+    ok(Object.isSealed(o) === true, "o is not sealed");
+    ok(Object.isExtensible(o) === false, "o is extensible");
+
+    o = Object.preventExtensions({ prop: 1 });
+    ok(Object.isFrozen(o) === false, "o is frozen");
+    ok(Object.isSealed(o) === false, "o is sealed");
+    ok(Object.isExtensible(o) === false, "o is extensible");
+
+    o = Object.freeze({ prop: 1 });
+    ok(Object.isFrozen(o) === true, "o is not frozen");
+    ok(Object.isSealed(o) === true, "o is not sealed");
+    ok(Object.isExtensible(o) === false, "o is extensible");
+
+    o = Object.seal({ prop: 1 });
+    ok(Object.isFrozen(o) === false, "o is frozen");
+    ok(Object.isSealed(o) === true, "o is not sealed");
+    ok(Object.isExtensible(o) === false, "o is extensible");
+
+    o = {};
+    Object.defineProperty(o, "prop", { value: 1 });
+    Object.preventExtensions(o);
+    ok(Object.isFrozen(o) === true, "o is not frozen");
+    ok(Object.isSealed(o) === true, "o is not sealed");
+    ok(Object.isExtensible(o) === false, "o is extensible");
+
+    o = {};
+    Object.defineProperty(o, "prop", { value: 1, writable: true });
+    Object.preventExtensions(o);
+    ok(Object.isFrozen(o) === false, "o is frozen");
+    ok(Object.isSealed(o) === true, "o is not sealed");
+    ok(Object.isExtensible(o) === false, "o is extensible");
+
+    o = {};
+    Object.defineProperty(o, "prop", { value: 1, writable: true, configurable: true });
+    Object.preventExtensions(o);
+    ok(Object.isFrozen(o) === false, "o is frozen");
+    ok(Object.isSealed(o) === false, "o is sealed");
+    ok(Object.isExtensible(o) === false, "o is extensible");
+
+    o = {};
+    Object.defineProperty(o, "prop", { value: 1, configurable: true });
+    Object.preventExtensions(o);
+    ok(Object.isFrozen(o) === false, "o is frozen");
+    ok(Object.isSealed(o) === false, "o is sealed");
+    ok(Object.isExtensible(o) === false, "o is extensible");
+
+    o = {};
+    Object.defineProperty(o, "prop", { get: function() {}, set: function() {} });
+    Object.preventExtensions(o);
+    ok(Object.isFrozen(o) === true, "o is not frozen");
+    ok(Object.isSealed(o) === true, "o is not sealed");
+    ok(Object.isExtensible(o) === false, "o is extensible");
+});
+
 sync_test("head_setter", function() {
     document.head = "";
     ok(typeof(document.head) === "object", "typeof(document.head) = " + typeof(document.head));




More information about the wine-cvs mailing list