From 0e4a9f116b58f9639b0d5d6116549aaa6629d40c Mon Sep 17 00:00:00 2001 From: Akrosh Gandhi Date: Thu, 19 Sep 2019 16:23:40 -0700 Subject: [PATCH] Param scope and body scope should not be merged on this case. When the param is used in the function, defined at the param scope, we should be have different param and body scope for the the enclosing function. However we are using the function id from the top ref of the pidRefStack. This is not correct as we could have pushed a ref on the stack with different block id but for the same function - so this logic could break. For fixing that we should walk that pidRefStack to see if there is access to the inner function. --- lib/Parser/Hash.h | 15 +++++++++++++++ lib/Parser/Parse.cpp | 2 +- test/Bugs/os_23446064.js | 21 +++++++++++++++++++++ test/Bugs/rlexe.xml | 6 ++++++ 4 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 test/Bugs/os_23446064.js diff --git a/lib/Parser/Hash.h b/lib/Parser/Hash.h index 6b8754820f7..7cea3fb6828 100644 --- a/lib/Parser/Hash.h +++ b/lib/Parser/Hash.h @@ -224,6 +224,21 @@ struct Ident return prevRef; } + // Since the pidrefstack is not sorted in the function id order. We need to scan it and find out if + // any of the reference exist in the nested func. + bool HasReferencedInNestedFunction(Js::LocalFunctionId functionId) + { + PidRefStack *ref; + for (ref = m_pidRefStack; ref; ref = ref->prev) + { + if (ref->GetFuncScopeId() > functionId) + { + return true; + } + } + return false; + } + PidRefStack * FindOrAddPidRef(ArenaAllocator *alloc, int scopeId, Js::LocalFunctionId funcId) { // If the stack is empty, or we are pushing to the innermost scope already, diff --git a/lib/Parser/Parse.cpp b/lib/Parser/Parse.cpp index 634c621efdb..c99892250b5 100644 --- a/lib/Parser/Parse.cpp +++ b/lib/Parser/Parse.cpp @@ -5890,7 +5890,7 @@ void Parser::ParseFncDeclHelper(ParseNodeFnc * pnodeFnc, LPCOLESTR pNameHint, us else if (pnodeFnc->HasNonSimpleParameterList() && pnodeFnc->IsBodyAndParamScopeMerged()) { paramScope->ForEachSymbolUntil([this, paramScope, pnodeFnc](Symbol* sym) { - if (sym->GetPid()->GetTopRef()->GetFuncScopeId() > pnodeFnc->functionId) + if (sym->GetPid()->HasReferencedInNestedFunction(pnodeFnc->functionId)) { // One of the symbol has non local reference. Mark the param scope as we can't merge it with body scope. pnodeFnc->ResetBodyAndParamScopeMerged(); diff --git a/test/Bugs/os_23446064.js b/test/Bugs/os_23446064.js new file mode 100644 index 00000000000..542a4260ba5 --- /dev/null +++ b/test/Bugs/os_23446064.js @@ -0,0 +1,21 @@ +//------------------------------------------------------------------------------------------------------- +// Copyright (C) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. +//------------------------------------------------------------------------------------------------------- + +function test0() { + var obj1 = {}; + var arrObj0 = obj1; + var func0 = function(a, + b = (Object.defineProperty(arrObj0, 'prop0', {set: function(_x) { a; } }), (1 - {1: a }) ) + ) + { + }; + + func0(); + obj1.prop0 = {}; + eval(''); + }; + + test0(); + print("Pass"); \ No newline at end of file diff --git a/test/Bugs/rlexe.xml b/test/Bugs/rlexe.xml index a410eaae3ce..e4a159dbfa0 100644 --- a/test/Bugs/rlexe.xml +++ b/test/Bugs/rlexe.xml @@ -594,6 +594,12 @@ -maxinterpretcount:1 -bgjit- -oopjit- -loopinterpretcount:1 -maxsimplejitruncount:2 + + + os_23446064.js + -force:deferparse + + Bug19948792.js