1 /**
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ast_verifier_test.h"
17 #include "ir/astNode.h"
18
19 #include <gtest/gtest.h>
20
21 using ark::es2panda::compiler::ast_verifier::ASTVerifier;
22 using ark::es2panda::compiler::ast_verifier::InvariantNameSet;
23 using ark::es2panda::ir::AstNode;
24
25 namespace {
TEST_F(ASTVerifierTest,CatchClause)26 TEST_F(ASTVerifierTest, CatchClause)
27 {
28 ASTVerifier verifier {Allocator()};
29
30 char const *text = R"(
31 let a = 10;
32 try {
33 a / 0;
34 } catch (e) {
35 if (e instanceof Error) {
36 }
37 }
38 )";
39
40 es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.sts");
41 impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED);
42 ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED);
43
44 auto *ast = reinterpret_cast<AstNode *>(impl_->ProgramAst(impl_->ContextProgram(ctx)));
45
46 InvariantNameSet checks;
47 checks.insert("VariableHasEnclosingScopeForAll");
48 const auto &messages = verifier.Verify(ast, checks);
49 ASSERT_EQ(messages.size(), 0);
50
51 impl_->DestroyContext(ctx);
52 }
53
TEST_F(ASTVerifierTest,LambdasHaveCorrectScope)54 TEST_F(ASTVerifierTest, LambdasHaveCorrectScope)
55 {
56 ASTVerifier verifier {Allocator()};
57
58 char const *text = R"(
59 type BenchmarkFunc = () => void;
60
61 function main() {
62 const arr: number[] = [1, 2, 3, 4];
63 const ITERATE_FUNC: BenchmarkFunc = () => {
64 const length = arr.length;
65 };
66 }
67 )";
68
69 es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.sts");
70 impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED);
71 ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED);
72
73 auto *ast = reinterpret_cast<AstNode *>(impl_->ProgramAst(impl_->ContextProgram(ctx)));
74
75 InvariantNameSet checks;
76 checks.insert("VariableHasEnclosingScopeForAll");
77 const auto &messages = verifier.Verify(ast, checks);
78 ASSERT_EQ(messages.size(), 0);
79
80 impl_->DestroyContext(ctx);
81 }
82
TEST_F(ASTVerifierTest,ParametersInArrowFunctionExpression)83 TEST_F(ASTVerifierTest, ParametersInArrowFunctionExpression)
84 {
85 ASTVerifier verifier {Allocator()};
86
87 char const *text = R"(
88 let b = 1;
89 let f = (p: double) => b + p;
90 function main () {
91 assert f(42) == 43
92 }
93 )";
94
95 es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.sts");
96 impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED);
97 ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED);
98
99 auto *ast = reinterpret_cast<AstNode *>(impl_->ProgramAst(impl_->ContextProgram(ctx)));
100
101 InvariantNameSet checks;
102 checks.insert("VariableHasEnclosingScopeForAll");
103 const auto &messages = verifier.Verify(ast, checks);
104 ASSERT_EQ(messages.size(), 0);
105
106 impl_->DestroyContext(ctx);
107 }
108
TEST_F(ASTVerifierTest,LambdaAsParameter)109 TEST_F(ASTVerifierTest, LambdaAsParameter)
110 {
111 ASTVerifier verifier {Allocator()};
112
113 char const *text = R"(
114 function foo(callback: (resolve: (val: int) => void) => void): void {}
115
116 function main(): void {
117 foo((resolve: (val: int) => void): void => {});
118 }
119 )";
120
121 es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.sts");
122 impl_->ProceedToState(ctx, ES2PANDA_STATE_LOWERED);
123 ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_LOWERED);
124
125 auto *ast = reinterpret_cast<AstNode *>(impl_->ProgramAst(impl_->ContextProgram(ctx)));
126
127 InvariantNameSet checks;
128 checks.insert("VariableHasEnclosingScopeForAll");
129 const auto &messages = verifier.Verify(ast, checks);
130 ASSERT_EQ(messages.size(), 0);
131
132 impl_->DestroyContext(ctx);
133 }
134
TEST_F(ASTVerifierTest,PartialClassDeclaration)135 TEST_F(ASTVerifierTest, PartialClassDeclaration)
136 {
137 ASTVerifier verifier {Allocator()};
138
139 char const *text = R"(
140 export class IncrementalNode {
141 protected onChildInserted: ((node: IncrementalNode) => void) | undefined = undefined
142 private static readonly ESCAPED_CHARS: char[] = [c'\"', c'\\']
143 }
144 )";
145
146 es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.sts");
147 impl_->ProceedToState(ctx, ES2PANDA_STATE_LOWERED);
148 ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_LOWERED);
149
150 auto *ast = reinterpret_cast<AstNode *>(impl_->ProgramAst(impl_->ContextProgram(ctx)));
151
152 InvariantNameSet checks;
153 checks.insert("VariableHasEnclosingScopeForAll");
154 const auto &messages = verifier.Verify(ast, checks);
155 ASSERT_EQ(messages.size(), 0);
156
157 impl_->DestroyContext(ctx);
158 }
159 } // namespace
160