Jacek Caban : jscript: Add interpreter support for getters and setters in object initializer.

Alexandre Julliard julliard at winehq.org
Mon Dec 3 15:28:52 CST 2018


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

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Fri Nov 30 22:44:40 2018 +0100

jscript: Add interpreter support for getters and setters in object initializer.

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

---

 dlls/jscript/compile.c   |  9 +++----
 dlls/jscript/engine.c    | 24 ++++++++++++++++-
 dlls/jscript/engine.h    |  2 +-
 dlls/mshtml/tests/es5.js | 69 +++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 95 insertions(+), 9 deletions(-)

diff --git a/dlls/jscript/compile.c b/dlls/jscript/compile.c
index a498abd..006386a 100644
--- a/dlls/jscript/compile.c
+++ b/dlls/jscript/compile.c
@@ -889,7 +889,6 @@ static HRESULT compile_array_literal(compiler_ctx_t *ctx, array_literal_expressi
 static HRESULT compile_object_literal(compiler_ctx_t *ctx, property_value_expression_t *expr)
 {
     property_definition_t *iter;
-    unsigned instr;
     BSTR name;
     HRESULT hres;
 
@@ -905,11 +904,9 @@ static HRESULT compile_object_literal(compiler_ctx_t *ctx, property_value_expres
         if(FAILED(hres))
             return hres;
 
-        instr = push_instr(ctx, OP_obj_prop);
-        if(!instr)
-            return E_OUTOFMEMORY;
-
-        instr_ptr(ctx, instr)->u.arg->bstr = name;
+        hres = push_instr_bstr_uint(ctx, OP_obj_prop, name, iter->type);
+        if(FAILED(hres))
+            return hres;
     }
 
     return S_OK;
diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c
index bd4edda..0f9e3a5 100644
--- a/dlls/jscript/engine.c
+++ b/dlls/jscript/engine.c
@@ -1445,6 +1445,7 @@ static HRESULT interp_new_obj(script_ctx_t *ctx)
 static HRESULT interp_obj_prop(script_ctx_t *ctx)
 {
     const BSTR name = get_op_bstr(ctx, 0);
+    unsigned type = get_op_uint(ctx, 1);
     jsdisp_t *obj;
     jsval_t val;
     HRESULT hres;
@@ -1456,7 +1457,28 @@ static HRESULT interp_obj_prop(script_ctx_t *ctx)
     assert(is_object_instance(stack_top(ctx)));
     obj = as_jsdisp(get_object(stack_top(ctx)));
 
-    hres = jsdisp_propput_name(obj, name, val);
+    if(type == PROPERTY_DEFINITION_VALUE) {
+        hres = jsdisp_propput_name(obj, name, val);
+    }else {
+        property_desc_t desc = {PROPF_ENUMERABLE | PROPF_CONFIGURABLE};
+        jsdisp_t *func;
+
+        assert(is_object_instance(val));
+        func = iface_to_jsdisp(get_object(val));
+
+        desc.mask = desc.flags;
+        if(type == PROPERTY_DEFINITION_GETTER) {
+            desc.explicit_getter = TRUE;
+            desc.getter = func;
+        }else {
+            desc.explicit_setter = TRUE;
+            desc.setter = func;
+        }
+
+        hres = jsdisp_define_property(obj, name, &desc);
+        jsdisp_release(func);
+    }
+
     jsval_release(val);
     return hres;
 }
diff --git a/dlls/jscript/engine.h b/dlls/jscript/engine.h
index d0c419a..eb287d5 100644
--- a/dlls/jscript/engine.h
+++ b/dlls/jscript/engine.h
@@ -66,7 +66,7 @@
     X(new,        1, ARG_UINT,   0)        \
     X(new_obj,    1, 0,0)                  \
     X(null,       1, 0,0)                  \
-    X(obj_prop,   1, ARG_BSTR,   0)        \
+    X(obj_prop,   1, ARG_BSTR,   ARG_UINT) \
     X(or,         1, 0,0)                  \
     X(pop,        1, ARG_UINT,   0)        \
     X(pop_except, 0, ARG_ADDR,   0)        \
diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js
index 6097f4c..3e81961 100644
--- a/dlls/mshtml/tests/es5.js
+++ b/dlls/mshtml/tests/es5.js
@@ -149,7 +149,7 @@ function test_identifier_keywords() {
 }
 
 function test_own_data_prop_desc(obj, prop, expected_writable, expected_enumerable,
-                            expected_configurable) {
+                                 expected_configurable) {
     var desc = Object.getOwnPropertyDescriptor(obj, prop);
     ok("value" in desc, "value is not in desc");
     ok(desc.value === obj[prop], "desc.value = " + desc.value + " expected " + obj[prop]);
@@ -427,6 +427,72 @@ function test_defineProperty() {
     next_test();
 }
 
+function test_property_definitions() {
+    var obj, val, i, arr;
+
+    function test_accessor_prop_desc(obj, prop, have_getter, have_setter) {
+        var desc = Object.getOwnPropertyDescriptor(obj, prop);
+        ok(desc.enumerable === true, "desc.enumerable = " + desc.enumerable);
+        ok(desc.configurable === true, "desc.configurable = " + desc.configurable);
+
+        if(have_getter) {
+            ok(typeof(desc.get) === "function", "desc.get = " + desc.get);
+            ok(typeof(desc.get.prototype) === "object", "desc.get.prototype = " + desc.get.prototype);
+            trace("" + desc.get);
+        }else {
+            ok(!("get" in obj), "desc.get = " + desc.get);
+        }
+
+        if(have_setter) {
+            ok(typeof(desc.set) === "function", "desc.set = " + desc.set);
+            ok(typeof(desc.set.prototype) === "object", "desc.set.prototype = " + desc.set.prototype);
+        }else {
+            ok(!("set" in obj), "desc.get = " + desc.get);
+        }
+    }
+
+    obj = {
+        get prop()  { return val + 1; },
+        set prop(v) { val = v; }
+    };
+    test_accessor_prop_desc(obj, "prop", true, true);
+    val = 0;
+    ok(obj.prop === 1, "obj.prop = " + obj.prop);
+    obj.prop = 3;
+    ok(val === 3, "val = " + val);
+    ok(obj.prop === 4, "obj.prop = " + obj.prop);
+
+    arr = [];
+    for(i in obj)
+        arr.push(i);
+    ok(arr.join() === "prop", "prop of obj = " + arr.join());
+
+    obj = {
+        set prop(v) { val = v; }
+    };
+    test_accessor_prop_desc(obj, "prop", false, true);
+    val = 1;
+    ok(obj.prop === undefined, "obj.prop = " + obj.prop);
+    obj.prop = 2;
+    ok(val === 2, "val = " + val);
+    ok(obj.prop === undefined, "obj.prop = " + obj.prop);
+
+    obj = {
+        get prop()  { return val + 1; },
+        get 0()     { return val + 2; }
+    };
+    test_accessor_prop_desc(obj, "prop", true, false);
+    val = 5;
+    ok(obj.prop === 6, "obj.prop = " + obj.prop);
+    obj.prop = 10;
+    ok(val === 5, "val = " + val);
+    ok(obj.prop === 6, "obj.prop = " + obj.prop);
+    test_accessor_prop_desc(obj, "0", true, false);
+    ok(obj[0] === 7, "obj.prop = " + obj[0]);
+
+    next_test();
+}
+
 function test_string_trim() {
     function test_trim(value, expected) {
         var r = String.prototype.trim.call(value);
@@ -513,6 +579,7 @@ var tests = [
     test_identifier_keywords,
     test_getOwnPropertyDescriptor,
     test_defineProperty,
+    test_property_definitions,
     test_string_trim,
     test_global_properties,
     test_string_split




More information about the wine-cvs mailing list