diff --git a/es2panda/binder/scope.cpp b/es2panda/binder/scope.cpp index 682f1543ee39ba23f206c9a1f6192e75e20a7654..6ea26c5cf40eb40304e5d69672d06e793059795a 100644 --- a/es2panda/binder/scope.cpp +++ b/es2panda/binder/scope.cpp @@ -90,34 +90,30 @@ Variable *Scope::FindLocal(const util::StringView &name, ResolveBindingOptions o return res->second; } +bool Scope::HasLexEnvInCorrespondingFunctionScope(const FunctionParamScope *scope) const +{ + auto *funcVariableScope = scope->GetFunctionScope(); + // we may only have function param scope without function scope in TS here + if ((funcVariableScope != nullptr) && (funcVariableScope->NeedLexEnv())) { + return true; + } + return false; +} + ScopeFindResult Scope::Find(const util::StringView &name, ResolveBindingOptions options) const { uint32_t level = 0; uint32_t lexLevel = 0; const auto *iter = this; ir::ScriptFunction *concurrentFunc = nullptr; - - if (iter->IsFunctionParamScope()) { - Variable *v = iter->FindLocal(name, options); - - if (v != nullptr) { - return {name, const_cast(iter), level, lexLevel, v, concurrentFunc}; - } - - level++; - auto *funcVariableScope = iter->AsFunctionParamScope()->GetFunctionScope(); - - // we may only have function param scope without function scope in TS here - if ((funcVariableScope != nullptr) && (funcVariableScope->NeedLexEnv())) { - lexLevel++; - } - - iter = iter->Parent(); - } - + // If the first scope is functionParamScope, it means its corresponding functionScope is not + // iterated. so by default we set prevScopeNotFunctionScope as true so under such case, + // functionScopeNotIterated will be true. + bool prevScopeNotFunctionScope = true; bool lexical = false; while (iter != nullptr) { + bool functionScopeNotIterated = iter->IsFunctionParamScope() && prevScopeNotFunctionScope; Variable *v = iter->FindLocal(name, options); if (v != nullptr) { @@ -141,10 +137,15 @@ ScopeFindResult Scope::Find(const util::StringView &name, ResolveBindingOptions (!iter->IsClassScope() || !iter->Node()->AsClassDefinition()->IsSendable())) { lexLevel++; } + } else if (functionScopeNotIterated) { + level++; + if (HasLexEnvInCorrespondingFunctionScope(iter->AsFunctionParamScope())) { + lexLevel++; + } } + prevScopeNotFunctionScope = !iter->IsFunctionVariableScope(); util::Helpers::SendableCheckForClassStaticInitializer(name, iter, concurrentFunc); - iter = iter->Parent(); } diff --git a/es2panda/binder/scope.h b/es2panda/binder/scope.h index 9943856dd2f5e36cb3b6e3263b2f02c8ea6d0c2c..0989e610126c8650f5a1cc66ccc8a5ad8361cbd0 100644 --- a/es2panda/binder/scope.h +++ b/es2panda/binder/scope.h @@ -353,6 +353,8 @@ public: bool HasVarDecl(const util::StringView &name) const; + bool HasLexEnvInCorrespondingFunctionScope(const FunctionParamScope *scope) const; + template Variable *FindLocalTSVariable(const util::StringView &name) const { diff --git a/es2panda/binder/variable.cpp b/es2panda/binder/variable.cpp index 42d1d45b26c1a9dbde67f614d0d4acc8ce395569..1d37a27845a4a9389eabc547445356e6f1f4201d 100644 --- a/es2panda/binder/variable.cpp +++ b/es2panda/binder/variable.cpp @@ -46,7 +46,8 @@ void LocalVariable::SetLexical(Scope *scope, util::PatchFix *patchFixHelper) return; } - VariableScope *varScope = scope->EnclosingVariableScope(); + VariableScope *varScope = scope->IsFunctionParamScope() ? + scope->AsFunctionParamScope()->GetFunctionScope() : scope->EnclosingVariableScope(); uint32_t slot = 0; auto name = Declaration()->Name(); diff --git a/es2panda/ir/statements/forInStatement.cpp b/es2panda/ir/statements/forInStatement.cpp index 3428db10d7a102192f9983770e5e45d6aeb554be..715d51bf3a094a10c96567a3f34fefc3aedd5860 100644 --- a/es2panda/ir/statements/forInStatement.cpp +++ b/es2panda/ir/statements/forInStatement.cpp @@ -56,6 +56,8 @@ void ForInStatement::Compile(compiler::PandaGen *pg) const const auto &labelSet = enumeratorInitTryCtx.LabelSet(); pg->SetLabel(right_, labelSet.TryBegin()); right_->Compile(pg); + pg->GetPropIterator(this); + pg->StoreAccumulator(this, iter); pg->SetLabel(right_, labelSet.TryEnd()); pg->Branch(right_, labelSet.CatchEnd()); @@ -70,10 +72,6 @@ void ForInStatement::Compile(compiler::PandaGen *pg) const pg->SetLabel(right_, labelSet.CatchEnd()); } - // if no exception occurred, the target object should be in acc - pg->GetPropIterator(this); - pg->StoreAccumulator(this, iter); - if (scope_->NeedLexEnv()) { pg->PopLexEnv(this); } diff --git a/es2panda/test/compiler/interpreter/lexicalEnv/lexical_env-expected.txt b/es2panda/test/compiler/interpreter/lexicalEnv/lexical_env-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..d00491fd7e5bb6fa28c517a0bb32b8b506539d4d --- /dev/null +++ b/es2panda/test/compiler/interpreter/lexicalEnv/lexical_env-expected.txt @@ -0,0 +1 @@ +1 diff --git a/es2panda/test/compiler/interpreter/lexicalEnv/lexical_env.js b/es2panda/test/compiler/interpreter/lexicalEnv/lexical_env.js new file mode 100644 index 0000000000000000000000000000000000000000..022027e21f837c0ce9e09c9f6077b60e0c66aaa2 --- /dev/null +++ b/es2panda/test/compiler/interpreter/lexicalEnv/lexical_env.js @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +(function (){ + let a = 1; + function A (b = ((()=>{print(a)})())) { + function B () { + b; + } + B(); + } + A(); +})(); diff --git a/es2panda/test/compiler/interpreter/lexicalEnv/lexical_env1-expected.txt b/es2panda/test/compiler/interpreter/lexicalEnv/lexical_env1-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..d00491fd7e5bb6fa28c517a0bb32b8b506539d4d --- /dev/null +++ b/es2panda/test/compiler/interpreter/lexicalEnv/lexical_env1-expected.txt @@ -0,0 +1 @@ +1 diff --git a/es2panda/test/compiler/interpreter/lexicalEnv/lexical_env1.js b/es2panda/test/compiler/interpreter/lexicalEnv/lexical_env1.js new file mode 100644 index 0000000000000000000000000000000000000000..cb937cfce8cdff5d6089478c5cc8fa8607761a7e --- /dev/null +++ b/es2panda/test/compiler/interpreter/lexicalEnv/lexical_env1.js @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +(function (){ + let a = 1; + function A(b = class {static{print(a)}}) { + function B() { + b; + } + } + A(); +})(); diff --git a/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole1-expected.txt b/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole1-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..2e9ba477f89e86c5bbc86c0516283f59d8f6e178 --- /dev/null +++ b/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole1-expected.txt @@ -0,0 +1 @@ +success diff --git a/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole1.js b/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole1.js new file mode 100644 index 0000000000000000000000000000000000000000..36bcebd1185e832357466e4143815ff85c837e1f --- /dev/null +++ b/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole1.js @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +try {} catch (e) { + const dummy = new Proxy(function () { + return dummy; + },handler); +} +function test_func2(obj, type) { + for (let name of Object.getOwnPropertyNames(obj)) {} +} +function test_func8(obj, seed) { + let prop = test_func2(obj); +} +let test_gc; +(function () { + test_gc = function() {}; +})(); +try{ + (function (v4 = () => arguments){ + var v5; + let v6 = v4(); + if (v6 != null && typeof v6 == "object") Object.defineProperty(v6, test_func8(v6, 104270),{ + value: v6 + }); + { + function f4() { + try { + v5[5]; + } catch (e) {} + } + } + })(); +} catch(e) {} +print("success"); diff --git a/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole2-expected.txt b/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole2-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..2e9ba477f89e86c5bbc86c0516283f59d8f6e178 --- /dev/null +++ b/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole2-expected.txt @@ -0,0 +1 @@ +success diff --git a/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole2.js b/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole2.js new file mode 100644 index 0000000000000000000000000000000000000000..065f96a96afcac68952d8552a4535a9821e10108 --- /dev/null +++ b/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole2.js @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +try {} catch (e) { + const dummy = new Proxy(function () { + return dummy; + },handler); +} +let test_gc; +(function () { + test_gc = function() {}; +})(); +function f0(v0) {} +(function (v4 = () => arguments){ + var v5; + let v6 = v4(); + let v7; + { + function f3(){}; + v7 =f3; + Reflect.set([null], 0, 0, v6); + function f4() { + v5[5]; + } + } + f0(v7 !== v6); +})(); +print("success"); diff --git a/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole3-expected.txt b/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole3-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..2e9ba477f89e86c5bbc86c0516283f59d8f6e178 --- /dev/null +++ b/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole3-expected.txt @@ -0,0 +1 @@ +success diff --git a/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole3.js b/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole3.js new file mode 100644 index 0000000000000000000000000000000000000000..339cdcd1cb8a8fc34deb4556ed73b4f1118e9143 --- /dev/null +++ b/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole3.js @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +try {} catch (e) { + const dummy = new Proxy(function () { + return dummy; + },handler); +} +let test_gc; +(function () { + test_gc = function() {}; +})(); +function f0(v0, v1= "Bad assertion") {} +f0.aarEq = function f2(v5, v6, v7 = `Expected «${v6}» to be «${v5}».`){}; +{ + let v11 = []; + let v12 = new Proxy(Object.create(null, { + x: { + enumerable: true, + configurable: true, + value: 0 + } + }), { + getOwnPropertyDescriptor(v13, v14) { + v11.push(`gopd ${v14}`); + v13[test_func8(v13, 1040732)] = true, test_gc(); + } + }); + try { + for (let v15 in v12) { + if (v15 != null && typeof v15 == "object") Object.defineProperty(v15, test_func8(v15, 647748), { + get: function () {}, + set: function (value) { + v15[test_func8(v15, 586990)], test_gc(); + } + }) + } + } catch (e) {} + try { + f0.aarEq(["gopd x", "enumerate x"], v11); + }catch (e) {} +} +print("success"); diff --git a/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole4-expected.txt b/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole4-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..7eb5d23111f86e8d79397ed880d1dc35b24e24f6 --- /dev/null +++ b/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole4-expected.txt @@ -0,0 +1 @@ +Failed diff --git a/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole4.js b/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole4.js new file mode 100644 index 0000000000000000000000000000000000000000..b09ed23a5ff3582ba67aaef95341c48f840b679a --- /dev/null +++ b/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole4.js @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +try {} catch (e) { + const dummy = new Proxy(function () { + return dummy; + },handler); +} +function test_func7(f) {} +let test_gc; +(function () { + test_gc = function() {}; +})(); +function f0(v0) {} +(function (v4 = () => arguments) { + v4[Symbol.toStringTag] = "hello2"; +})(); +(function (v12 = () => v13, { + arguments: {} +}) {})(undefined, { + arguments: {} +}); +try { + (function (v16 = () => v18, v17 = v16(), { + arguments: v18 + }) { + f0(v17[1] === undefined); + test_func7(() => { + return f0(v17.length === 3); + }); + var v19; + { + function f10() { + v19[18]; + } + } + })(undefined, undefined, { + arguments: {} + }); +} catch (e) { + print("Failed") +} diff --git a/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole5-expected.txt b/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole5-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..2e9ba477f89e86c5bbc86c0516283f59d8f6e178 --- /dev/null +++ b/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole5-expected.txt @@ -0,0 +1 @@ +success diff --git a/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole5.js b/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole5.js new file mode 100644 index 0000000000000000000000000000000000000000..ad04bd1f07a17a3a99af867f5b5ae1e747ed4a05 --- /dev/null +++ b/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole5.js @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +try {} catch (e) { + const dummy = new Proxy(function () { + return dummy; + },handler); +} +let test_gc; +(function () { + test_gc = function() {}; +})(); +function f0(v3 = 10, v4 = function (){ + return v3; +}) { + try { + v3 = 20; + } catch (e) {} + try { + if (v3 === 20) { + Array.prototype.__defineGetter__(100, () => 1); + } else {} + } catch (e) {} + return v4; +} +if (f0()() === 20) {} else {} +print("success"); diff --git a/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole6-expected.txt b/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole6-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..2e9ba477f89e86c5bbc86c0516283f59d8f6e178 --- /dev/null +++ b/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole6-expected.txt @@ -0,0 +1 @@ +success diff --git a/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole6.js b/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole6.js new file mode 100644 index 0000000000000000000000000000000000000000..071815db37614a5479bda707496bb957259de218 --- /dev/null +++ b/es2panda/test/compiler/interpreter/lexicalEnv/safe_hole6.js @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +try {} catch (e) { + const dummy = new Proxy(function () { + return dummy; + },handler); +} +let test_gc; +(function () { + test_gc = function() {}; +})(); +function f0(v3 = 10, v4 = function (){ + return v3; +}) { + try { + v3 = 20; + } catch (e) {} + try { + 'pybfr'.replace(v4, ''); + } catch (e) {} + try { + if (v3 === 20) {} else { + try { + Set.prototype.add = () => {}; + } catch (e) {} + } + } catch (e) {} +} +try { + if (f0()() === 20) {} else {} +} catch (e) {} +print("success"); diff --git a/es2panda/test/runner.py b/es2panda/test/runner.py index af80fcb764f800ee999bc76807b4747015723402..6a49105f35e66e324ed12e2860f1d906021f8287 100755 --- a/es2panda/test/runner.py +++ b/es2panda/test/runner.py @@ -1605,6 +1605,7 @@ def main(): runner.add_directory("compiler/commonjs", "js", ["--commonjs"]) runner.add_directory("compiler/recordsource/with-on", "js", ["--record-source"]) runner.add_directory("compiler/recordsource/with-off", "js", []) + runner.add_directory("compiler/interpreter/lexicalEnv", "js", []) runners.append(runner)