Not just for interpreted functions.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/engine.c | 33 +++++++++++++++++++++++---------- dlls/jscript/tests/api.js | 2 ++ dlls/jscript/tests/lang.js | 3 +++ dlls/mshtml/tests/es5.js | 20 ++++++++++++++++++++ 4 files changed, 48 insertions(+), 10 deletions(-)
diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index 73b9d86..7dce4fe 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -314,9 +314,13 @@ static HRESULT exprval_propget(script_ctx_t *ctx, exprval_t *ref, jsval_t *r)
static HRESULT exprval_call(script_ctx_t *ctx, exprval_t *ref, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { + jsdisp_t *jsdisp; + HRESULT hres; + jsval_t v; + switch(ref->type) { case EXPRVAL_STACK_REF: { - jsval_t v = ctx->stack[ref->u.off]; + v = ctx->stack[ref->u.off];
if(!is_object_instance(v)) { FIXME("invoke %s\n", debugstr_jsval(v)); @@ -326,10 +330,24 @@ static HRESULT exprval_call(script_ctx_t *ctx, exprval_t *ref, WORD flags, unsig return disp_call_value(ctx, get_object(v), NULL, flags, argc, argv, r); } case EXPRVAL_IDREF: + /* ECMA-262 3rd Edition 11.2.3.7 / ECMA-262 5.1 Edition 11.2.3.6 * + * Don't treat scope object props as PropertyReferences. */ + if((jsdisp = to_jsdisp(ref->u.idref.disp)) && jsdisp->builtin_info->class == JSCLASS_NONE) { + hres = disp_propget(ctx, ref->u.idref.disp, ref->u.idref.id, &v); + if(FAILED(hres)) + return hres; + if(!is_object_instance(v)) { + FIXME("invoke %s\n", debugstr_jsval(v)); + hres = E_FAIL; + }else { + hres = disp_call_value(ctx, get_object(v), NULL, flags, argc, argv, r); + } + jsval_release(v); + return hres; + } return disp_call(ctx, ref->u.idref.disp, ref->u.idref.id, flags, argc, argv, r); case EXPRVAL_JSVAL: { IDispatch *obj; - HRESULT hres;
hres = to_object(ctx, ref->u.val, &obj); if(SUCCEEDED(hres)) { @@ -3300,16 +3318,11 @@ HRESULT exec_source(script_ctx_t *ctx, DWORD flags, bytecode_t *bytecode, functi } }
- /* ECMA-262 3rd Edition 11.2.3.7 */ if(this_obj) { - jsdisp_t *jsthis; + jsdisp_t *jsthis = to_jsdisp(this_obj);
- jsthis = iface_to_jsdisp(this_obj); - if(jsthis) { - if(jsthis->builtin_info->class == JSCLASS_GLOBAL || jsthis->builtin_info->class == JSCLASS_NONE) - this_obj = NULL; - jsdisp_release(jsthis); - } + if(jsthis && jsthis->builtin_info->class == JSCLASS_GLOBAL) + this_obj = NULL; }
if(ctx->call_ctx && (flags & EXEC_EVAL)) { diff --git a/dlls/jscript/tests/api.js b/dlls/jscript/tests/api.js index e81bbea..1368f39 100644 --- a/dlls/jscript/tests/api.js +++ b/dlls/jscript/tests/api.js @@ -2634,6 +2634,8 @@ testException(function() {null.toString();}, "E_OBJECT_EXPECTED"); testException(function() {RegExp.prototype.toString.call(new Object());}, "E_REGEXP_EXPECTED"); testException(function() {/a/.lastIndex();}, "E_NOT_FUNC"); testException(function() {"a".length();}, "E_NOT_FUNC"); +testException(function() {((function() { var f = Number.prototype.toString; return (function() { return f(); }); })())();}, "E_NOT_NUM"); +testException(function() {((function() { var f = Object.prototype.hasOwnProperty; return (function() { return f("f"); }); })())();}, "E_OBJECT_EXPECTED");
testException(function() { return arguments.callee(); }, "E_STACK_OVERFLOW");
diff --git a/dlls/jscript/tests/lang.js b/dlls/jscript/tests/lang.js index cf08423..67e4576 100644 --- a/dlls/jscript/tests/lang.js +++ b/dlls/jscript/tests/lang.js @@ -310,6 +310,9 @@ argumentsTest(); ok(callAsExprTest.arguments === null, "callAsExprTest.arguments = " + callAsExprTest.arguments); })(1,2);
+tmp = ((function() { var f = function() {return this}; return (function() { return f(); }); })())(); +ok(tmp === this, "detached scope function call this != global this"); + tmp = (function() {1;})(); ok(tmp === undefined, "tmp = " + tmp); tmp = eval("1;"); diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index 0f9df4c..1916199 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -1791,6 +1791,26 @@ sync_test("let scope instances", function() { ok(f() == 2, "f() = " + f()); });
+sync_test("substituted this", function() { + try { + ((function() { var f = Number.prototype.toString; return (function() { return f(); }); })())(); + }catch(ex) { + var n = ex.number >>> 0; + ok(n === JS_E_NUMBER_EXPECTED, "Number.toString threw " + n); + } + + var r = ((function() { var f = Object.prototype.toString; return (function() { return f(); }); })())(); + todo_wine. + ok(r === "[object Undefined]", "detached scope Object.toString returned " + r); + + var r = (function() { this.f = Object.prototype.toString; return this.f(); })(); + todo_wine. + ok(r === "[object Window]", "Object.toString returned " + r); + + var r = ((function() { return (function() { return this; }); })())(); + ok(r === window, "detached scope this = " + r); +}); + sync_test("functions scope", function() { function f(){ return 1; } function f(){ return 2; }