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; }
Based on the spec (ECMA-262 5.1 Edition 11.2.3.7), whereas the ES3 spec says it gets replaced with null.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/function.c | 7 ++++++- dlls/mshtml/tests/es5.js | 4 +++- 2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index 12511bb..638d176 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -250,13 +250,18 @@ void detach_arguments_object(jsdisp_t *args_disp) HRESULT Function_invoke(jsdisp_t *func_this, IDispatch *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { FunctionInstance *function; + jsval_t vthis;
TRACE("func %p this %p\n", func_this, jsthis);
assert(is_class(func_this, JSCLASS_FUNCTION)); function = function_from_jsdisp(func_this);
- return function->vtbl->call(function->dispex.ctx, function, jsthis ? jsval_disp(jsthis) : jsval_null(), flags, argc, argv, r); + if(jsthis) + vthis = jsval_disp(jsthis); + else + vthis = function->dispex.ctx->version < SCRIPTLANGUAGEVERSION_ES5 ? jsval_null() : jsval_undefined(); + return function->vtbl->call(function->dispex.ctx, function, vthis, flags, argc, argv, r); }
static HRESULT Function_get_length(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index 1916199..5aa186b 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -1800,13 +1800,15 @@ sync_test("substituted this", function() { }
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() { var f = Object.prototype.toString; return f(); })(); + ok(r === "[object Undefined]", "Object.toString returned " + r); + var r = ((function() { return (function() { return this; }); })())(); ok(r === window, "detached scope this = " + r); });
Signed-off-by: Jacek Caban jacek@codeweavers.com
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=114800
Your paranoid android.
=== w10pro64 (32 bit report) ===
mshtml: htmldoc.c:2541: Test failed: unexpected call UpdateUI htmldoc.c:2853: Test failed: unexpected call Exec_UPDATECOMMANDS
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=114799
Your paranoid android.
=== w10pro64 (32 bit report) ===
mshtml: htmldoc.c:2541: Test failed: unexpected call UpdateUI htmldoc.c:2853: Test failed: unexpected call Exec_UPDATECOMMANDS htmldoc.c:350: Test failed: expected Exec_SETTITLE htmldoc.c:2859: Test failed: unexpected call Exec_SETTITLE
=== w10pro64 (64 bit report) ===
mshtml: htmldoc.c:2541: Test failed: unexpected call UpdateUI htmldoc.c:2853: Test failed: unexpected call Exec_UPDATECOMMANDS
=== w10pro64_zh_CN (64 bit report) ===
mshtml: htmldoc.c:2541: Test failed: unexpected call UpdateUI htmldoc.c:2853: Test failed: unexpected call Exec_UPDATECOMMANDS
=== w7u_2qxl (testbot log) ===
WineRunTask.pl:error: The previous 1 run(s) terminated abnormally
=== w7u_2qxl (32 bit report) ===
mshtml: script.c:644: Test failed: L"/index.html?es5.js:date_now: unexpected Date.now() result 1652720515741 expected 1652720515800"
=== w7u_adm (32 bit report) ===
mshtml: script.c:644: Test failed: L"/index.html?es5.js:date_now: unexpected Date.now() result 1652719183794 expected 1652719183853"