/* * Copyright (c) 2021 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "parserImpl.h" namespace panda::es2panda::parser { static std::vector cjsMandatoryParams = {binder::Binder::CJS_MANDATORY_PARAM_EXPORTS, binder::Binder::CJS_MANDATORY_PARAM_REQUIRE, binder::Binder::CJS_MANDATORY_PARAM_MODULE, binder::Binder::CJS_MANDATORY_PARAM_FILENAME, binder::Binder::CJS_MANDATORY_PARAM_DIRNAME}; void ParserImpl::AddCommonjsParams(ArenaVector ¶ms) { for (auto paramName : cjsMandatoryParams) { ir::Expression *param = AllocNode(paramName); param->AsIdentifier()->SetReference(); Binder()->AddParamDecl(param); params.push_back(param); } } void ParserImpl::AddReflectApplyArgs(ArenaVector &args, ir::FunctionExpression *wrapper) { ASSERT(wrapper != nullptr); // wrapper args.push_back(wrapper); // thisValue ir::Expression *thisValue = AllocNode(binder::Binder::CJS_MANDATORY_PARAM_EXPORTS); thisValue->AsIdentifier()->SetReference(); args.push_back(thisValue); // wrapper's arguments ArenaVector elements(Allocator()->Adapter()); for (auto argName : cjsMandatoryParams) { ir::Expression *arg = AllocNode(argName); arg->AsIdentifier()->SetReference(); elements.push_back(arg); } ir::ArrayExpression *wrapperArgsArray = AllocNode(ir::AstNodeType::ARRAY_EXPRESSION, std::move(elements), false); args.push_back(wrapperArgsArray); } void ParserImpl::ParseCommonjs() { // create FunctionExpression as callee ir::FunctionExpression *wrapper = nullptr; { FunctionContext functionContext(this, ParserStatus::FUNCTION | ParserStatus::ALLOW_NEW_TARGET); FunctionParameterContext funcParamContext(&context_, Binder()); auto *funcParamScope = funcParamContext.LexicalScope().GetScope(); ArenaVector params(Allocator()->Adapter()); AddCommonjsParams(params); auto functionCtx = binder::LexicalScope(Binder()); auto *functionScope = functionCtx.GetScope(); functionScope->BindParamScope(funcParamScope); funcParamScope->BindFunctionScope(functionScope); ParseProgram(ScriptKind::COMMONJS); auto *funcNode = AllocNode(functionScope, std::move(params), nullptr, program_.Ast(), nullptr, functionContext.Flags(), false, Extension() == ScriptExtension::TS); functionScope->BindNode(funcNode); funcParamScope->BindNode(funcNode); wrapper = AllocNode(funcNode); } // create CallExpression ArenaVector arguments(Allocator()->Adapter()); AddReflectApplyArgs(arguments, wrapper); auto *apply = AllocNode("apply"); auto *reflect = AllocNode("Reflect"); auto *reflectApply = AllocNode(reflect, apply, ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); auto *callExpr = AllocNode(reflectApply, std::move(arguments), nullptr, false); // create ExpressionStatement auto *exprStatementNode = AllocNode(callExpr); ArenaVector statements(Allocator()->Adapter()); statements.push_back(exprStatementNode); auto *blockStmt = AllocNode(Binder()->GetScope(), std::move(statements)); Binder()->GetScope()->BindNode(blockStmt); program_.SetAst(blockStmt); } } // namespace panda::es2panda::parser