Skip to content

Commit

Permalink
Implement missing part of GlobalDeclarationInstantiation and EvalDecl…
Browse files Browse the repository at this point in the history
…arationInstantiation

Signed-off-by: Seonghyun Kim <[email protected]>
  • Loading branch information
ksh8281 authored and clover2123 committed May 11, 2020
1 parent 3916dad commit a9a41ff
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 37 deletions.
14 changes: 11 additions & 3 deletions src/interpreter/ByteCodeInterpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,10 +198,15 @@ Value ByteCodeInterpreter::interpret(ExecutionState* state, ByteCodeBlock* byteC
isCacheWork = true;
} else if (slot->m_cachedStructure == nullptr) {
isCacheWork = true;
if (UNLIKELY(ctx->globalDeclarativeStorage()->at(idx).isEmpty())) {
ErrorObject::throwBuiltinError(*state, ErrorObject::ReferenceError, ctx->globalDeclarativeRecord()->at(idx).m_name.string(), false, String::emptyString, ErrorObject::Messages::IsNotInitialized);
const auto& record = ctx->globalDeclarativeRecord()->at(idx);
auto& storage = ctx->globalDeclarativeStorage()->at(idx);
if (UNLIKELY(storage.isEmpty())) {
ErrorObject::throwBuiltinError(*state, ErrorObject::ReferenceError, record.m_name.string(), false, String::emptyString, ErrorObject::Messages::IsNotInitialized);
}
if (UNLIKELY(!record.m_isMutable)) {
ErrorObject::throwBuiltinError(*state, ErrorObject::TypeError, record.m_name.string(), false, String::emptyString, ErrorObject::Messages::AssignmentToConstantVariable);
}
ctx->globalDeclarativeStorage()->at(idx) = registerFile[code->m_registerIndex];
storage = registerFile[code->m_registerIndex];
}
}

Expand Down Expand Up @@ -2097,6 +2102,9 @@ NEVER_INLINE void ByteCodeInterpreter::setGlobalVariableSlowCase(ExecutionState&
if (UNLIKELY(place.isEmpty())) {
ErrorObject::throwBuiltinError(state, ErrorObject::ReferenceError, name.string(), false, String::emptyString, ErrorObject::Messages::IsNotInitialized);
}
if (UNLIKELY(!records[i].m_isMutable)) {
ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::AssignmentToConstantVariable, name);
}
place = value;
return;
}
Expand Down
70 changes: 51 additions & 19 deletions src/parser/Script.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -507,26 +507,28 @@ Value Script::execute(ExecutionState& state, bool isExecuteOnEvalFunction, bool
LexicalEnvironment* globalLexicalEnvironment = new LexicalEnvironment(globalRecord, nullptr);
newState.setLexicalEnvironment(globalLexicalEnvironment, m_topCodeBlock->isStrict());

if (inStrictMode && isExecuteOnEvalFunction) {
EnvironmentRecord* globalVariableRecord = globalRecord;

if (isExecuteOnEvalFunction) {
// NOTE: ES5 10.4.2.1 eval in strict mode
// + Indirect eval code creates a new declarative environment for lexically-scoped declarations (let)
EnvironmentRecord* newVariableRecord = new DeclarativeEnvironmentRecordNotIndexed(state, true);
ExecutionState* newVariableState = new ExecutionState(context());
newVariableState->setLexicalEnvironment(new LexicalEnvironment(newVariableRecord, globalLexicalEnvironment), m_topCodeBlock->isStrict());
newVariableState->setParent(&newState);
codeExecutionState = newVariableState;
if (inStrictMode) {
globalVariableRecord = newVariableRecord;
}
}

testDeclareGlobalFunctions(state, m_topCodeBlock, context()->globalObject());

const InterpretedCodeBlock::IdentifierInfoVector& vec = m_topCodeBlock->identifierInfos();
size_t len = vec.size();
for (size_t i = 0; i < len; i++) {
// https://www.ecma-international.org/ecma-262/5.1/#sec-10.5
// Step 2. If code is eval code, then let configurableBindings be true.
if (vec[i].m_isVarDeclaration) {
codeExecutionState->lexicalEnvironment()->record()->createBinding(*codeExecutionState, vec[i].m_name, isExecuteOnEvalFunction, vec[i].m_isMutable, true, m_topCodeBlock);
}
}
const InterpretedCodeBlock::IdentifierInfoVector& identifierVector = m_topCodeBlock->identifierInfos();
size_t identifierVectorLen = identifierVector.size();

const auto& globalLexicalVector = m_topCodeBlock->blockInfo(0)->m_identifiers;
size_t globalLexicalVectorLen = globalLexicalVector.size();

if (!isExecuteOnEvalFunction) {
InterpretedCodeBlock* child = m_topCodeBlock->firstChild();
Expand All @@ -539,10 +541,38 @@ Value Script::execute(ExecutionState& state, bool isExecuteOnEvalFunction, bool
child = child->nextSibling();
}

const auto& globalLexicalVector = m_topCodeBlock->blockInfo(0)->m_identifiers;
size_t len = globalLexicalVector.size();
for (size_t i = 0; i < len; i++) {
codeExecutionState->lexicalEnvironment()->record()->createBinding(*codeExecutionState, globalLexicalVector[i].m_name, false, globalLexicalVector[i].m_isMutable, false);
// https://www.ecma-international.org/ecma-262/#sec-globaldeclarationinstantiation
IdentifierRecordVector* globalDeclarativeRecord = context()->globalDeclarativeRecord();
size_t globalDeclarativeRecordLen = globalDeclarativeRecord->size();
for (size_t i = 0; i < globalDeclarativeRecordLen; i++) {
// For each name in varNames, do
// If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError
for (size_t j = 0; j < identifierVectorLen; j++) {
if (identifierVector[j].m_isVarDeclaration && identifierVector[j].m_name == globalDeclarativeRecord->at(i).m_name) {
ErrorObject::throwBuiltinError(state, ErrorObject::SyntaxError, globalDeclarativeRecord->at(i).m_name.string(), false, String::emptyString, ErrorObject::Messages::DuplicatedIdentifier);
}
}
}

for (size_t i = 0; i < globalLexicalVectorLen; i++) {
// Let hasRestrictedGlobal be ? envRec.HasRestrictedGlobalProperty(name).
// If hasRestrictedGlobal is true, throw a SyntaxError exception.
auto desc = context()->globalObject()->getOwnProperty(state, globalLexicalVector[i].m_name);
if (desc.hasValue() && !desc.isConfigurable()) {
ErrorObject::throwBuiltinError(state, ErrorObject::SyntaxError, globalLexicalVector[i].m_name.string(), false, String::emptyString, "redeclaration of non-configurable global property %s");
}
}
}

for (size_t i = 0; i < globalLexicalVectorLen; i++) {
codeExecutionState->lexicalEnvironment()->record()->createBinding(*codeExecutionState, globalLexicalVector[i].m_name, false, globalLexicalVector[i].m_isMutable, false);
}

for (size_t i = 0; i < identifierVectorLen; i++) {
// https://www.ecma-international.org/ecma-262/5.1/#sec-10.5
// Step 2. If code is eval code, then let configurableBindings be true.
if (identifierVector[i].m_isVarDeclaration) {
globalVariableRecord->createBinding(*codeExecutionState, identifierVector[i].m_name, isExecuteOnEvalFunction, identifierVector[i].m_isMutable, true, m_topCodeBlock);
}
}

Expand Down Expand Up @@ -604,11 +634,13 @@ Value Script::executeLocal(ExecutionState& state, Value thisValue, InterpretedCo
}
}

for (size_t i = 0; i < vecLen; i++) {
if (vec[i].m_isVarDeclaration) {
auto slot = e->record()->hasBinding(state, vec[i].m_name);
if (slot.m_isLexicallyDeclared && slot.m_index != SIZE_MAX) {
ErrorObject::throwBuiltinError(state, ErrorObject::SyntaxError, vec[i].m_name.string(), false, String::emptyString, ErrorObject::Messages::DuplicatedIdentifier);
if (!m_topCodeBlock->isStrict()) {
for (size_t i = 0; i < vecLen; i++) {
if (vec[i].m_isVarDeclaration) {
auto slot = e->record()->hasBinding(state, vec[i].m_name);
if (slot.m_isLexicallyDeclared && slot.m_index != SIZE_MAX) {
ErrorObject::throwBuiltinError(state, ErrorObject::SyntaxError, vec[i].m_name.string(), false, String::emptyString, ErrorObject::Messages::DuplicatedIdentifier);
}
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/runtime/EnvironmentRecord.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ void GlobalEnvironmentRecord::createBinding(ExecutionState& state, const AtomicS
ObjectPropertyDescriptor::PresentAttribute attribute = (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::EnumerablePresent);
if (canDelete) {
attribute = (ObjectPropertyDescriptor::PresentAttribute)(attribute | ObjectPropertyDescriptor::ConfigurablePresent);
} else {
attribute = (ObjectPropertyDescriptor::PresentAttribute)(attribute | ObjectPropertyDescriptor::NonConfigurablePresent);
}
if (!desc.hasValue()) {
m_globalObject->defineOwnPropertyThrowsException(state, name, ObjectPropertyDescriptor(Value(), attribute));
Expand Down
15 changes: 0 additions & 15 deletions tools/test/test262/excludelist.orig.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1981,14 +1981,6 @@
<test id="language/computed-property-names/class/static/method-number"><reason>TODO</reason></test>
<test id="language/computed-property-names/class/static/method-string"><reason>TODO</reason></test>
<test id="language/computed-property-names/class/static/method-symbol"><reason>TODO</reason></test>
<test id="language/eval-code/direct/var-env-lower-lex-strict-caller"><reason>TODO</reason></test>
<test id="language/eval-code/direct/var-env-lower-lex-strict-source"><reason>TODO</reason></test>
<test id="language/eval-code/indirect/lex-env-distinct-cls"><reason>TODO</reason></test>
<test id="language/eval-code/indirect/lex-env-distinct-const"><reason>TODO</reason></test>
<test id="language/eval-code/indirect/lex-env-distinct-let"><reason>TODO</reason></test>
<test id="language/eval-code/indirect/lex-env-no-init-cls"><reason>TODO</reason></test>
<test id="language/eval-code/indirect/lex-env-no-init-const"><reason>TODO</reason></test>
<test id="language/eval-code/indirect/lex-env-no-init-let"><reason>TODO</reason></test>
<test id="language/expressions/addition/bigint-and-number"><reason>TODO</reason></test>
<test id="language/expressions/addition/bigint-arithmetic"><reason>TODO</reason></test>
<test id="language/expressions/addition/bigint-errors"><reason>TODO</reason></test>
Expand Down Expand Up @@ -4474,13 +4466,6 @@
<test id="language/function-code/each-param-has-own-scope"><reason>TODO</reason></test>
<test id="language/function-code/eval-param-env-with-computed-key"><reason>TODO</reason></test>
<test id="language/function-code/eval-param-env-with-prop-initializer"><reason>TODO</reason></test>
<test id="language/global-code/decl-lex-restricted-global"><reason>TODO</reason></test>
<test id="language/global-code/script-decl-func"><reason>TODO</reason></test>
<test id="language/global-code/script-decl-lex"><reason>TODO</reason></test>
<test id="language/global-code/script-decl-lex-lex"><reason>TODO</reason></test>
<test id="language/global-code/script-decl-lex-restricted-global"><reason>TODO</reason></test>
<test id="language/global-code/script-decl-lex-var"><reason>TODO</reason></test>
<test id="language/global-code/script-decl-var-collision"><reason>TODO</reason></test>
<test id="language/literals/bigint/numeric-separators/numeric-separator-literal-bil-bd-nsl-bd"><reason>TODO</reason></test>
<test id="language/literals/bigint/numeric-separators/numeric-separator-literal-bil-bd-nsl-bds"><reason>TODO</reason></test>
<test id="language/literals/bigint/numeric-separators/numeric-separator-literal-bil-bds-nsl-bd"><reason>TODO</reason></test>
Expand Down

0 comments on commit a9a41ff

Please sign in to comment.