From: Jacek Caban jacek@codeweavers.com
--- dlls/jscript/dispex.c | 14 +++++++--- dlls/mshtml/tests/es5.js | 55 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 4 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 6569fdc8421..d5ed3adf4fb 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -274,12 +274,16 @@ static HRESULT update_external_prop(jsdisp_t *obj, const WCHAR *name, dispex_pro
if(desc->name) name = desc->name; - if(!prop && !(prop = alloc_prop(obj, name, PROP_DELETED, 0))) - return E_OUTOFMEMORY;
if(!desc->iid) { + if(!prop && !(prop = alloc_prop(obj, name, PROP_DELETED, 0))) + return E_OUTOFMEMORY; prop->type = PROP_EXTERN; prop->u.id = desc->id; + }else if(prop) { + /* If a property for a host non-volatile already exists, it must have been deleted. */ + *ret = prop; + return S_OK; }else if(desc->flags & PROPF_METHOD) { jsdisp_t *func;
@@ -287,7 +291,8 @@ static HRESULT update_external_prop(jsdisp_t *obj, const WCHAR *name, dispex_pro if(FAILED(hres)) return hres;
- prop->type = PROP_JSVAL; + if(!(prop = alloc_prop(obj, name, PROP_JSVAL, 0))) + return E_OUTOFMEMORY; prop->u.val = jsval_obj(func); }else { jsdisp_t *getter, *setter = NULL; @@ -304,7 +309,8 @@ static HRESULT update_external_prop(jsdisp_t *obj, const WCHAR *name, dispex_pro } }
- prop->type = PROP_ACCESSOR; + if(!(prop = alloc_prop(obj, name, PROP_ACCESSOR, 0))) + return E_OUTOFMEMORY; prop->u.accessor.getter = getter; prop->u.accessor.setter = setter; } diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index e15e3f379cd..40458c103c9 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -2971,3 +2971,58 @@ sync_test("prototypes", function() { ok(document.body instanceof Element, "body is not an instance of Element"); ok(document.body instanceof Node, "body is not an instance of Node"); }); + +sync_test("prototypes_delete", function() { + function check_prop(name) { + var orig = Object.getOwnPropertyDescriptor(Element.prototype, name); + ok(orig != undefined, "Could not get " + name + " descriptor"); + var is_func = "value" in orig; + + function check(obj, has_own, has_prop, has_enum, todo_enum) { + var r = obj.hasOwnProperty(name); + ok(r === has_own, obj + ".hasOwnProperty(" + name + ") returned " + r); + r = name in obj; + ok(r === has_prop, name + " in " + obj + " returned " + r); + r = check_enum(obj, name); + todo_wine_if(todo_enum). + ok(r === has_enum, "enumerating " + name + " in " + obj + "returned " + r); + } + + check(document.body, false, true, true, is_func); + check(Element.prototype, true, true, true, is_func); + check(Node.prototype, false, false, false); + + delete Element.prototype[name]; + check(document.body, false, false, false); + check(Element.prototype, false, false, false); + check(Node.prototype, false, false, false); + + Element.prototype[name] = -2; + Node.prototype[name] = -3; + ok(document.body[name] === -2, "document.body[" + name + "] = " + Element.prototype[name]); + + check(document.body, false, true, true); + check(Element.prototype, true, true, true); + check(Node.prototype, true, true, true); + + delete Element.prototype[name]; + ok(document.body[name] === -3, "document.body[" + name + "] = " + Element.prototype[name]); + check(document.body, false, true, true); + check(Element.prototype, false, true, true); + check(Node.prototype, true, true, true); + + delete Node.prototype[name]; + check(document.body, false, false, false); + check(Element.prototype, false, false, false); + check(Node.prototype, false, false, false); + + /* Restore the prop */ + Object.defineProperty(Element.prototype, name, orig); + check(document.body, false, true, true, is_func); + check(Element.prototype, true, true, true, is_func); + check(Node.prototype, false, false, false); + } + + check_prop("scrollLeft"); /* accessor prop */ + check_prop("getBoundingClientRect"); /* function prop */ +});