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 32namespace panda::es2panda::parser { 33static 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 39void ParserImpl::AddCommonjsParams(ArenaVector<ir::Expression *> ¶ms) 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 49void 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 70void 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