• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 <binder/binder.h>
17 #include <ir/base/scriptFunction.h>
18 #include <ir/expression.h>
19 #include <ir/expressions/arrayExpression.h>
20 #include <ir/expressions/callExpression.h>
21 #include <ir/expressions/functionExpression.h>
22 #include <ir/expressions/identifier.h>
23 #include <ir/expressions/memberExpression.h>
24 #include <ir/statements/expressionStatement.h>
25 #include <ir/statements/blockStatement.h>
26 
27 #include <string_view>
28 #include <vector>
29 
30 #include "parserImpl.h"
31 
32 namespace panda::es2panda::parser {
33 static std::vector<std::string_view> cjsMandatoryParams = {binder::Binder::CJS_MANDATORY_PARAM_EXPORTS,
34                                                            binder::Binder::CJS_MANDATORY_PARAM_REQUIRE,
35                                                            binder::Binder::CJS_MANDATORY_PARAM_MODULE,
36                                                            binder::Binder::CJS_MANDATORY_PARAM_FILENAME,
37                                                            binder::Binder::CJS_MANDATORY_PARAM_DIRNAME};
38 
AddCommonjsParams(ArenaVector<ir::Expression * > & params)39 void ParserImpl::AddCommonjsParams(ArenaVector<ir::Expression *> &params)
40 {
41     for (auto paramName : cjsMandatoryParams) {
42         ir::Expression *param = AllocNode<ir::Identifier>(paramName);
43         param->AsIdentifier()->SetReference();
44         Binder()->AddParamDecl(param);
45         params.push_back(param);
46     }
47 }
48 
AddReflectApplyArgs(ArenaVector<ir::Expression * > & args,ir::FunctionExpression * wrapper)49 void ParserImpl::AddReflectApplyArgs(ArenaVector<ir::Expression *> &args, ir::FunctionExpression *wrapper)
50 {
51     ASSERT(wrapper != nullptr);
52     // wrapper
53     args.push_back(wrapper);
54     // thisValue
55     ir::Expression *thisValue = AllocNode<ir::Identifier>(binder::Binder::CJS_MANDATORY_PARAM_EXPORTS);
56     thisValue->AsIdentifier()->SetReference();
57     args.push_back(thisValue);
58     // wrapper's arguments
59     ArenaVector<ir::Expression *> elements(Allocator()->Adapter());
60     for (auto argName : cjsMandatoryParams) {
61         ir::Expression *arg = AllocNode<ir::Identifier>(argName);
62         arg->AsIdentifier()->SetReference();
63         elements.push_back(arg);
64     }
65     ir::ArrayExpression *wrapperArgsArray =
66         AllocNode<ir::ArrayExpression>(ir::AstNodeType::ARRAY_EXPRESSION, std::move(elements), false);
67     args.push_back(wrapperArgsArray);
68 }
69 
ParseCommonjs()70 void ParserImpl::ParseCommonjs()
71 {
72     // create FunctionExpression as callee
73     ir::FunctionExpression *wrapper = nullptr;
74     {
75         FunctionContext functionContext(this, ParserStatus::FUNCTION | ParserStatus::ALLOW_NEW_TARGET);
76         FunctionParameterContext funcParamContext(&context_, Binder());
77         auto *funcParamScope = funcParamContext.LexicalScope().GetScope();
78 
79         ArenaVector<ir::Expression *> params(Allocator()->Adapter());
80         AddCommonjsParams(params);
81 
82         auto functionCtx = binder::LexicalScope<binder::FunctionScope>(Binder());
83         auto *functionScope = functionCtx.GetScope();
84         functionScope->BindParamScope(funcParamScope);
85         funcParamScope->BindFunctionScope(functionScope);
86 
87         ParseProgram(ScriptKind::COMMONJS);
88 
89         auto *funcNode =
90             AllocNode<ir::ScriptFunction>(functionScope, std::move(params), nullptr, program_.Ast(), nullptr,
91                                           functionContext.Flags(), false, Extension() == ScriptExtension::TS);
92         functionScope->BindNode(funcNode);
93         funcParamScope->BindNode(funcNode);
94 
95         wrapper = AllocNode<ir::FunctionExpression>(funcNode);
96     }
97 
98     // create CallExpression
99     ArenaVector<ir::Expression *> arguments(Allocator()->Adapter());
100     AddReflectApplyArgs(arguments, wrapper);
101 
102     auto *apply = AllocNode<ir::Identifier>("apply");
103     auto *reflect = AllocNode<ir::Identifier>("Reflect");
104     auto *reflectApply = AllocNode<ir::MemberExpression>(reflect, apply,
105         ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false);
106 
107     auto *callExpr = AllocNode<ir::CallExpression>(reflectApply, std::move(arguments), nullptr, false);
108     // create ExpressionStatement
109     auto *exprStatementNode = AllocNode<ir::ExpressionStatement>(callExpr);
110 
111     ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
112     statements.push_back(exprStatementNode);
113 
114     auto *blockStmt = AllocNode<ir::BlockStatement>(Binder()->GetScope(), std::move(statements));
115     Binder()->GetScope()->BindNode(blockStmt);
116 
117     program_.SetAst(blockStmt);
118 }
119 }  // namespace panda::es2panda::parser