Update to support new.target with Class and eval (#489)

* Pass more tests

Signed-off-by: Boram Bae <boram21.bae@samsung.com>
This commit is contained in:
Boram Bae 2019-10-31 13:38:49 +09:00 committed by Hyukwoo Park
commit f11752b532
9 changed files with 53 additions and 21 deletions

View file

@ -102,7 +102,7 @@ void ByteCodeBlock::fillLocDataIfNeeded(Context* c)
ByteCodeBlock* block;
// TODO give correct stack limit to parser
if (m_codeBlock->asInterpretedCodeBlock()->isGlobalScopeCodeBlock()) {
ProgramNode* nd = esprima::parseProgram(c, m_codeBlock->asInterpretedCodeBlock()->src(), m_codeBlock->script()->isModule(), m_codeBlock->asInterpretedCodeBlock()->isStrict(), m_codeBlock->inWith(), SIZE_MAX, false, false);
ProgramNode* nd = esprima::parseProgram(c, m_codeBlock->asInterpretedCodeBlock()->src(), m_codeBlock->script()->isModule(), m_codeBlock->asInterpretedCodeBlock()->isStrict(), m_codeBlock->inWith(), SIZE_MAX, false, false, false);
block = ByteCodeGenerator::generateByteCode(c, m_codeBlock->asInterpretedCodeBlock(), nd, nd->scopeContext(), m_isEvalMode, m_isOnGlobal, false, true);
} else {
ASTFunctionScopeContext* scopeContext = nullptr;

View file

@ -26,6 +26,8 @@
#include "parser/ScriptParser.h"
#include "parser/ast/AST.h"
#include "parser/CodeBlock.h"
#include "runtime/Environment.h"
#include "runtime/EnvironmentRecord.h"
namespace Escargot {
@ -202,7 +204,7 @@ void ScriptParser::generateCodeBlockTreeFromASTWalkerPostProcess(InterpretedCode
cb->m_astContext = nullptr;
}
ScriptParser::InitializeScriptResult ScriptParser::initializeScript(StringView scriptSource, String* fileName, bool isModule, InterpretedCodeBlock* parentCodeBlock, bool strictFromOutside, bool isEvalCodeInFunction, bool isEvalMode, bool inWithOperation, size_t stackSizeRemain, bool needByteCodeGeneration, bool allowSuperCall, bool allowSuperProperty)
ScriptParser::InitializeScriptResult ScriptParser::initializeScript(StringView scriptSource, String* fileName, bool isModule, InterpretedCodeBlock* parentCodeBlock, bool strictFromOutside, bool isEvalCodeInFunction, bool isEvalMode, bool inWithOperation, size_t stackSizeRemain, bool needByteCodeGeneration, bool allowSuperCall, bool allowSuperProperty, bool allowNewTarget)
{
GC_disable();
@ -213,7 +215,7 @@ ScriptParser::InitializeScriptResult ScriptParser::initializeScript(StringView s
// Parsing
try {
InterpretedCodeBlock* topCodeBlock = nullptr;
ProgramNode* programNode = esprima::parseProgram(m_context, scriptSource, isModule, strictFromOutside, inWith, stackSizeRemain, allowSC, allowSP);
ProgramNode* programNode = esprima::parseProgram(m_context, scriptSource, isModule, strictFromOutside, inWith, stackSizeRemain, allowSC, allowSP, allowNewTarget);
Script* script = new Script(fileName, new StringView(scriptSource), programNode->moduleData(), !parentCodeBlock);
if (parentCodeBlock) {

View file

@ -58,10 +58,10 @@ public:
}
};
InitializeScriptResult initializeScript(StringView scriptSource, String* fileName, bool isModule, InterpretedCodeBlock* parentCodeBlock, bool strictFromOutside, bool isEvalCodeInFunction, bool isEvalMode, bool inWithOperation, size_t stackSizeRemain, bool needByteCodeGeneration, bool allowSuperCall, bool allowSuperProperty);
InitializeScriptResult initializeScript(StringView scriptSource, String* fileName, bool isModule, InterpretedCodeBlock* parentCodeBlock, bool strictFromOutside, bool isEvalCodeInFunction, bool isEvalMode, bool inWithOperation, size_t stackSizeRemain, bool needByteCodeGeneration, bool allowSuperCall, bool allowSuperProperty, bool allowNewTarget);
InitializeScriptResult initializeScript(String* scriptSource, String* fileName, bool isModule, bool strictFromOutside = false, bool isRunningEvalOnFunction = false, bool isEvalMode = false, size_t stackSizeRemain = SIZE_MAX)
{
return initializeScript(StringView(scriptSource, 0, scriptSource->length()), fileName, isModule, nullptr, strictFromOutside, isRunningEvalOnFunction, isEvalMode, false, stackSizeRemain, true, false, false);
return initializeScript(StringView(scriptSource, 0, scriptSource->length()), fileName, isModule, nullptr, strictFromOutside, isRunningEvalOnFunction, isEvalMode, false, stackSizeRemain, true, false, false, false);
}
void generateFunctionByteCode(ExecutionState& state, InterpretedCodeBlock* codeBlock, size_t stackSizeRemain);

View file

@ -76,6 +76,7 @@ struct Context {
bool allowLexicalDeclaration : 1;
bool allowSuperCall : 1;
bool allowSuperProperty : 1;
bool allowNewTarget : 1;
bool isAssignmentTarget : 1;
bool isBindingElement : 1;
bool inFunctionBody : 1;
@ -221,6 +222,7 @@ public:
this->context->allowLexicalDeclaration = false;
this->context->allowSuperCall = false;
this->context->allowSuperProperty = false;
this->context->allowNewTarget = false;
this->context->isAssignmentTarget = true;
this->context->isBindingElement = true;
this->context->inFunctionBody = false;
@ -1398,11 +1400,13 @@ public:
const bool previousAllowYield = this->context->allowYield;
const bool previousAllowSuperCall = this->context->allowSuperCall;
const bool previousAllowSuperProperty = this->context->allowSuperProperty;
const bool previousAllowNewTarget = this->context->allowNewTarget;
const bool previousInArrowFunction = this->context->inArrowFunction;
this->context->allowYield = true;
this->context->inArrowFunction = false;
this->context->allowSuperProperty = true;
this->context->allowNewTarget = true;
if (allowSuperCall) {
this->context->allowSuperCall = true;
@ -1419,6 +1423,7 @@ public:
this->context->allowYield = previousAllowYield;
this->context->inArrowFunction = previousInArrowFunction;
this->context->allowSuperProperty = previousAllowSuperProperty;
this->context->allowNewTarget = previousAllowNewTarget;
this->context->allowSuperCall = previousAllowSuperCall;
this->currentScopeContext->m_paramsStartLOC.index = node.index;
@ -1886,7 +1891,7 @@ public:
if (this->match(Period)) {
this->nextToken();
if (this->lookahead.type == Token::IdentifierToken && this->context->inFunctionBody && this->lookahead.relatedSource(this->scanner->source) == "target") {
if (this->lookahead.type == Token::IdentifierToken && this->context->allowNewTarget && this->lookahead.relatedSource(this->scanner->source) == "target") {
this->nextToken();
this->currentScopeContext->m_hasSuperOrNewTarget = true;
MetaNode node = this->createNode();
@ -4157,8 +4162,11 @@ public:
bool previousAllowYield = this->context->allowYield;
bool previousInArrowFunction = this->context->inArrowFunction;
bool previousAllowNewTarget = this->context->allowNewTarget;
this->context->allowYield = !isGenerator;
this->context->inArrowFunction = false;
this->context->allowNewTarget = true;
ParseFormalParametersResult formalParameters;
this->parseFormalParameters(newBuilder, formalParameters, &firstRestricted);
@ -4180,6 +4188,7 @@ public:
this->context->strict = previousStrict;
this->context->allowYield = previousAllowYield;
this->context->inArrowFunction = previousInArrowFunction;
this->context->allowNewTarget = previousAllowNewTarget;
this->currentScopeContext->m_nodeType = ASTNodeType::FunctionDeclaration;
this->currentScopeContext->m_isGenerator = isGenerator;
@ -4205,8 +4214,11 @@ public:
bool previousAllowYield = this->context->allowYield;
bool previousInArrowFunction = this->context->inArrowFunction;
bool previousAllowNewTarget = this->context->allowNewTarget;
this->context->allowYield = !isGenerator;
this->context->inArrowFunction = false;
this->context->allowNewTarget = true;
if (!this->match(LeftParenthesis)) {
ALLOC_TOKEN(token);
@ -4269,6 +4281,7 @@ public:
this->context->strict = previousStrict;
this->context->allowYield = previousAllowYield;
this->context->inArrowFunction = previousInArrowFunction;
this->context->allowNewTarget = previousAllowNewTarget;
this->currentScopeContext->m_nodeType = ASTNodeType::FunctionExpression;
this->currentScopeContext->m_isGenerator = isGenerator;
@ -4354,10 +4367,12 @@ public:
const bool previousAllowYield = this->context->allowYield;
const bool previousInArrowFunction = this->context->inArrowFunction;
const bool previousAllowSuperProperty = this->context->allowSuperProperty;
const bool previousAllowNewTarget = this->context->allowNewTarget;
this->context->allowYield = true;
this->context->inArrowFunction = false;
this->context->allowSuperProperty = true;
this->context->allowNewTarget = true;
this->expect(LeftParenthesis);
this->expect(RightParenthesis);
@ -4371,6 +4386,7 @@ public:
this->context->allowYield = previousAllowYield;
this->context->inArrowFunction = previousInArrowFunction;
this->context->allowSuperProperty = previousAllowSuperProperty;
this->context->allowNewTarget = previousAllowNewTarget;
this->currentScopeContext->m_paramsStartLOC.index = node.index;
this->currentScopeContext->m_paramsStartLOC.column = node.column;
@ -4398,10 +4414,12 @@ public:
const bool previousAllowYield = this->context->allowYield;
const bool previousInArrowFunction = this->context->inArrowFunction;
const bool previousAllowSuperProperty = this->context->allowSuperProperty;
const bool previousAllowNewTarget = this->context->allowNewTarget;
this->context->allowYield = true;
this->context->allowSuperProperty = true;
this->context->inArrowFunction = false;
this->context->allowNewTarget = true;
this->expect(LeftParenthesis);
@ -4420,6 +4438,7 @@ public:
this->context->allowYield = previousAllowYield;
this->context->allowSuperProperty = previousAllowSuperProperty;
this->context->inArrowFunction = previousInArrowFunction;
this->context->allowNewTarget = previousAllowNewTarget;
this->currentScopeContext->m_paramsStartLOC.index = node.index;
this->currentScopeContext->m_paramsStartLOC.column = node.column;
@ -4447,10 +4466,12 @@ public:
const bool previousAllowYield = this->context->allowYield;
const bool previousInArrowFunction = this->context->inArrowFunction;
const bool previousAllowSuperProperty = this->context->allowSuperProperty;
const bool previousAllowNewTarget = this->context->allowNewTarget;
this->context->allowYield = false;
this->context->allowSuperProperty = true;
this->context->inArrowFunction = false;
this->context->allowNewTarget = true;
this->expect(LeftParenthesis);
@ -4464,6 +4485,7 @@ public:
this->context->allowYield = previousAllowYield;
this->context->allowSuperProperty = previousAllowSuperProperty;
this->context->inArrowFunction = previousInArrowFunction;
this->context->allowNewTarget = previousAllowNewTarget;
this->currentScopeContext->m_paramsStartLOC.index = node.index;
this->currentScopeContext->m_paramsStartLOC.column = node.column;
@ -5198,10 +5220,15 @@ public:
{
ASSERT(this->isParsingSingleFunction);
const bool previousAllowNewTarget = context->allowNewTarget;
context->allowNewTarget = true;
MetaNode node = this->createNode();
StatementContainer* params = this->parseFunctionParameters(builder);
BlockStatementNode* body = this->parseFunctionBody(builder);
context->allowNewTarget = previousAllowNewTarget;
return this->finalize(node, builder.createFunctionNode(params, body, std::move(this->numeralLiteralVector)));
}
@ -5276,7 +5303,7 @@ public:
}
};
ProgramNode* parseProgram(::Escargot::Context* ctx, StringView source, bool isModule, bool strictFromOutside, bool inWith, size_t stackRemain, bool allowSuperCallOutside, bool allowSuperPropertyOutside)
ProgramNode* parseProgram(::Escargot::Context* ctx, StringView source, bool isModule, bool strictFromOutside, bool inWith, size_t stackRemain, bool allowSuperCallFromOutside, bool allowSuperPropertyFromOutside, bool allowNewTargetFromOutside)
{
// GC should be disabled during the parsing process
ASSERT(GC_is_disabled());
@ -5287,8 +5314,9 @@ ProgramNode* parseProgram(::Escargot::Context* ctx, StringView source, bool isMo
parser.context->strict = strictFromOutside;
parser.context->inWith = inWith;
parser.context->allowSuperCall = allowSuperCallOutside;
parser.context->allowSuperProperty = allowSuperPropertyOutside;
parser.context->allowSuperCall = allowSuperCallFromOutside;
parser.context->allowSuperProperty = allowSuperPropertyFromOutside;
parser.context->allowNewTarget = allowNewTargetFromOutside;
ProgramNode* nd = parser.parseProgram(builder);
return nd;
@ -5307,8 +5335,8 @@ FunctionNode* parseSingleFunction(::Escargot::Context* ctx, InterpretedCodeBlock
parser.context->allowLexicalDeclaration = true;
parser.context->allowSuperCall = true;
parser.context->allowSuperProperty = true;
parser.context->allowNewTarget = true;
parser.isParsingSingleFunction = true;
parser.codeBlock = codeBlock;
scopeContext = new (ctx->astAllocator()) ASTFunctionScopeContext(ctx->astAllocator(), codeBlock->isStrict());

View file

@ -61,7 +61,7 @@ struct Error : public gc {
#define ESPRIMA_RECURSIVE_LIMIT 1024
ProgramNode* parseProgram(::Escargot::Context* ctx, StringView source, bool isModule, bool strictFromOutside, bool inWith, size_t stackRemain, bool allowSuperCallOutside, bool allowSuperPropertyOutside);
ProgramNode* parseProgram(::Escargot::Context* ctx, StringView source, bool isModule, bool strictFromOutside, bool inWith, size_t stackRemain, bool allowSuperCallFromOutside, bool allowSuperPropertyFromOutside, bool allowNewTargetFromOutside);
FunctionNode* parseSingleFunction(::Escargot::Context* ctx, InterpretedCodeBlock* codeBlock, ASTFunctionScopeContext*& scopeContext, size_t stackRemain);
}
}

View file

@ -114,7 +114,7 @@ FunctionObject::FunctionSource FunctionObject::createFunctionSourceFromScriptSou
try {
srcToTest.appendString(") { }");
String* cur = srcToTest.finalize(&state);
esprima::parseProgram(state.context(), StringView(cur, 0, cur->length()), false, false, false, SIZE_MAX, false, false);
esprima::parseProgram(state.context(), StringView(cur, 0, cur->length()), false, false, false, SIZE_MAX, false, false, true);
// reset ASTAllocator
state.context()->astAllocator().reset();
@ -151,7 +151,7 @@ FunctionObject::FunctionSource FunctionObject::createFunctionSourceFromScriptSou
ScriptParser parser(state.context());
String* scriptSource = src.finalize(&state);
Script* script = parser.initializeScript(StringView(scriptSource, 0, scriptSource->length()), new ASCIIString("Function Constructor input"), false, nullptr, false, false, false, false, SIZE_MAX, false, allowSuperCall, false).scriptThrowsExceptionIfParseError(state);
Script* script = parser.initializeScript(StringView(scriptSource, 0, scriptSource->length()), new ASCIIString("Function Constructor input"), false, nullptr, false, false, false, false, SIZE_MAX, false, allowSuperCall, false, true).scriptThrowsExceptionIfParseError(state);
InterpretedCodeBlock* cb = script->topCodeBlock()->firstChild();
cb->updateSourceElementStart(3, 1);
LexicalEnvironment* globalEnvironment = new LexicalEnvironment(new GlobalEnvironmentRecord(state, script->topCodeBlock(), state.context()->globalObject(), &state.context()->globalDeclarativeRecord(), &state.context()->globalDeclarativeStorage()), nullptr);

View file

@ -156,7 +156,7 @@ Value GlobalObject::eval(ExecutionState& state, const Value& arg)
#else
size_t stackRemainApprox = STACK_LIMIT_FROM_BASE - (currentStackBase - state.stackBase());
#endif
Script* script = parser.initializeScript(StringView(arg.asString(), 0, arg.asString()->length()), String::fromUTF8(s, strlen(s)), false, nullptr, strictFromOutside, false, true, false, stackRemainApprox, true, false, false).scriptThrowsExceptionIfParseError(state);
Script* script = parser.initializeScript(StringView(arg.asString(), 0, arg.asString()->length()), String::fromUTF8(s, strlen(s)), false, nullptr, strictFromOutside, false, true, false, stackRemainApprox, true, false, false, false).scriptThrowsExceptionIfParseError(state);
// In case of indirect call, use global execution context
ExecutionState stateForNewGlobal(m_context);
return script->execute(stateForNewGlobal, true, script->topCodeBlock()->isStrict());
@ -192,6 +192,12 @@ Value GlobalObject::evalLocal(ExecutionState& state, const Value& arg, Value thi
current = current->parent();
}
bool allowNewTarget = false;
auto thisEnvironment = state.getThisEnvironment();
if (thisEnvironment->isDeclarativeEnvironmentRecord() && thisEnvironment->asDeclarativeEnvironmentRecord()->isFunctionEnvironmentRecord()) {
allowNewTarget = true;
}
volatile int sp;
size_t currentStackBase = (size_t)&sp;
#ifdef STACK_GROWS_DOWN
@ -200,7 +206,7 @@ Value GlobalObject::evalLocal(ExecutionState& state, const Value& arg, Value thi
size_t stackRemainApprox = STACK_LIMIT_FROM_BASE - (currentStackBase - state.stackBase());
#endif
Script* script = parser.initializeScript(StringView(arg.asString(), 0, arg.asString()->length()), String::fromUTF8(s, sizeof(s) - 1), false, parentCodeBlock, strictFromOutside, isRunningEvalOnFunction, true, inWithOperation, stackRemainApprox, true, parentCodeBlock->allowSuperCall(), parentCodeBlock->allowSuperProperty()).scriptThrowsExceptionIfParseError(state);
Script* script = parser.initializeScript(StringView(arg.asString(), 0, arg.asString()->length()), String::fromUTF8(s, sizeof(s) - 1), false, parentCodeBlock, strictFromOutside, isRunningEvalOnFunction, true, inWithOperation, stackRemainApprox, true, parentCodeBlock->allowSuperCall(), parentCodeBlock->allowSuperProperty(), allowNewTarget).scriptThrowsExceptionIfParseError(state);
return script->executeLocal(state, thisValue, parentCodeBlock, script->topCodeBlock()->isStrict(), isRunningEvalOnFunction);
}
return arg;

@ -1 +1 @@
Subproject commit 36bf26ba45e4f87651ab2bdce1122ad5730f07b0
Subproject commit 35e1a26902b029c0dc60673644268f6935d15859

View file

@ -49,6 +49,7 @@ non262/BigInt/decimal.js
non262/BigInt/large-bit-length.js
non262/BigInt/mod.js
non262/BigInt/Number-conversion-rounding.js
non262/class/newTargetDVG.js
# These tests include features of ES7
non262/Array/slice-sparse-with-large-index.js
@ -59,11 +60,6 @@ non262/arrow-functions/arrow-not-as-end-of-statement.js
# TODO
non262/arrow-functions/yield-in-arrow.js
non262/class/className.js
non262/class/newTargetArrow.js
non262/class/newTargetDefaults.js
non262/class/newTargetDVG.js
non262/class/newTargetEval.js
non262/class/newTargetGenerators.js
non262/class/outerBinding.js
non262/class/strictExecution.js
non262/class/superCallBaseInvoked.js