Reimplement initialize & executing Module according to newer spec

* Update test runner for running module tests in test262

Signed-off-by: Seonghyun Kim <sh8281.kim@samsung.com>
This commit is contained in:
Seonghyun Kim 2020-05-20 10:30:32 +09:00 committed by Hyukwoo Park
commit 9b9f980cfe
15 changed files with 732 additions and 371 deletions

View file

@ -464,6 +464,23 @@ static void sendRecordProperties(Debugger* debugger, ExecutionState* state, Iden
}
}
static void sendRecordProperties(Debugger* debugger, ExecutionState* state, const ModuleEnvironmentRecord::ModuleBindingRecordVector& bindings, ModuleEnvironmentRecord* record)
{
size_t size = bindings.size();
for (size_t i = 0; i < size; i++) {
AtomicString name = bindings[i].m_localName;
try {
EnvironmentRecord::GetBindingValueResult result = record->getBindingValue(*state, name);
ASSERT(result.m_hasBindingValue);
sendProperty(debugger, state, name, result.m_value);
} catch (const Value& val) {
sendUnaccessibleProperty(debugger, name);
}
}
}
void Debugger::getScopeVariables(ExecutionState* state, uint32_t index)
{
LexicalEnvironment* lexEnv = state->lexicalEnvironment();
@ -493,7 +510,7 @@ void Debugger::getScopeVariables(ExecutionState* state, uint32_t index)
sendRecordProperties(this, state, *identifierRecordVector, record);
}
} else if (record->isModuleEnvironmentRecord()) {
sendRecordProperties(this, state, declarativeRecord->asModuleEnvironmentRecord()->m_moduleDeclarativeRecord, record);
sendRecordProperties(this, state, record->asModuleEnvironmentRecord()->moduleBindings(), record->asModuleEnvironmentRecord());
} else if (declarativeRecord->isDeclarativeEnvironmentRecordNotIndexed()) {
sendRecordProperties(this, state, declarativeRecord->asDeclarativeEnvironmentRecordNotIndexed()->m_recordVector, record);
}

View file

@ -2787,7 +2787,7 @@ NEVER_INLINE void ByteCodeInterpreter::callFunctionComplexCase(ExecutionState& s
}
env = env->outerEnvironment();
}
if (env->record()->isObjectEnvironmentRecord()) {
if (env && env->record()->isObjectEnvironmentRecord()) {
thisValue = env->record()->asObjectEnvironmentRecord()->bindingObject();
}
}

View file

@ -45,62 +45,17 @@ Context* Script::context()
return m_topCodeBlock->context();
}
static Optional<Script*> findLoadedModule(Context* context, Optional<Script*> referrer, String* src)
{
const auto& lm = *context->loadedModules();
for (size_t j = 0; j < lm.size(); j++) {
if (lm[j].m_referrer == referrer && lm[j].m_src->equals(src)) {
return Optional<Script*>(lm[j].m_loadedModule);
}
}
return Optional<Script*>();
}
static void registerToLoadedModuleIfNeeds(Context* context, Optional<Script*> referrer, String* src, Script* module)
{
if (!findLoadedModule(context, referrer, src)) {
LoadedModule m;
m.m_loadedModule = module;
m.m_referrer = referrer;
m.m_src = src;
auto lm = context->loadedModules();
lm->push_back(m);
}
}
void Script::loadExternalModule(ExecutionState& state)
{
for (size_t i = 0; i < m_moduleData->m_importEntries.size(); i++) {
bool loaded = findLoadedModule(context(), this, m_moduleData->m_importEntries[i].m_moduleRequest).hasValue();
if (!loaded) {
loadModuleFromScript(state, m_moduleData->m_importEntries[i].m_moduleRequest);
}
}
for (size_t i = 0; i < m_moduleData->m_indirectExportEntries.size(); i++) {
bool loaded = findLoadedModule(context(), this, m_moduleData->m_indirectExportEntries[i].m_moduleRequest.value()).hasValue();
if (!loaded) {
loadModuleFromScript(state, m_moduleData->m_indirectExportEntries[i].m_moduleRequest.value());
}
}
for (size_t i = 0; i < m_moduleData->m_starExportEntries.size(); i++) {
bool loaded = findLoadedModule(context(), this, m_moduleData->m_starExportEntries[i].m_moduleRequest.value()).hasValue();
if (!loaded) {
loadModuleFromScript(state, m_moduleData->m_starExportEntries[i].m_moduleRequest.value());
}
}
}
void Script::loadModuleFromScript(ExecutionState& state, String* src)
Script* Script::loadModuleFromScript(ExecutionState& state, String* src)
{
Platform::LoadModuleResult result = context()->vmInstance()->platform()->onLoadModule(context(), this, src);
if (!result.script) {
ErrorObject::throwBuiltinError(state, (ErrorObject::Code)result.errorCode, result.errorMessage->toNonGCUTF8StringData().data());
}
registerToLoadedModuleIfNeeds(context(), this, src, result.script.value());
result.script->loadExternalModule(state);
if (!result.script->moduleData()->m_didCallLoadedCallback) {
context()->vmInstance()->platform()->didLoadModule(context(), this, result.script.value());
result.script->moduleData()->m_didCallLoadedCallback = true;
}
return result.script.value();
}
size_t Script::moduleRequestsLength()
@ -174,7 +129,7 @@ AtomicStringVector Script::exportedNames(ExecutionState& state, std::vector<Scri
// Let requestedModule be HostResolveImportedModule(module, e.[[ModuleRequest]]).
// ReturnIfAbrupt(requestedModule).
Script* requestedModule = findLoadedModule(context(), this, e.m_moduleRequest.value()).value();
Script* requestedModule = loadModuleFromScript(state, e.m_moduleRequest.value());
// Let starNames be requestedModule.GetExportedNames(exportStarSet).
auto starNames = requestedModule->exportedNames(state, exportStarSet);
@ -241,7 +196,7 @@ Script::ResolveExportResult Script::resolveExport(ExecutionState& state, AtomicS
// Assert: module imports a specific binding for this export.
// Let importedModule be HostResolveImportedModule(module, e.[[ModuleRequest]]).
// ReturnIfAbrupt(importedModule).
Script* importedModule = findLoadedModule(context(), this, e.m_moduleRequest.value()).value();
Script* importedModule = loadModuleFromScript(state, e.m_moduleRequest.value());
// Let indirectResolution be importedModule.ResolveExport(e.[[ImportName]], resolveSet, exportStarSet).
auto indirectResolution = importedModule->resolveExport(state, e.m_importName.value(), resolveSet, exportStarSet);
// ReturnIfAbrupt(indirectResolution).
@ -277,7 +232,7 @@ Script::ResolveExportResult Script::resolveExport(ExecutionState& state, AtomicS
auto& e = starExportEntries[i];
// Let importedModule be HostResolveImportedModule(module, e.[[ModuleRequest]]).
// ReturnIfAbrupt(importedModule).
Script* importedModule = findLoadedModule(context(), this, e.m_moduleRequest.value()).value();
Script* importedModule = loadModuleFromScript(state, e.m_moduleRequest.value());
// Let resolution be importedModule.ResolveExport(exportName, resolveSet, exportStarSet).
// ReturnIfAbrupt(resolution).
auto resolution = importedModule->resolveExport(state, exportName, resolveSet, exportStarSet);
@ -305,148 +260,6 @@ Script::ResolveExportResult Script::resolveExport(ExecutionState& state, AtomicS
return starResolution;
}
Value Script::executeModule(ExecutionState& state, Optional<Script*> referrer)
{
ByteCodeBlock* byteCodeBlock = m_topCodeBlock->byteCodeBlock();
// http://www.ecma-international.org/ecma-262/6.0/#sec-moduledeclarationinstantiation
// ModuleDeclarationInstantiation( ) Concrete Method
LexicalEnvironment* globalLexicalEnv = new LexicalEnvironment(
new GlobalEnvironmentRecord(state, nullptr, context()->globalObject(), context()->globalDeclarativeRecord(), context()->globalDeclarativeStorage()), nullptr);
ExecutionState newState(context(), state.stackLimit());
ModuleEnvironmentRecord* moduleRecord = new ModuleEnvironmentRecord(this);
m_moduleData->m_moduleRecord = moduleRecord;
context()->vmInstance()->platform()->didLoadModule(context(), referrer, this);
registerToLoadedModuleIfNeeds(context(), referrer, src(), this);
loadExternalModule(state);
const InterpretedCodeBlock::IdentifierInfoVector& vec = m_topCodeBlock->identifierInfos();
size_t len = vec.size();
for (size_t i = 0; i < len; i++) {
moduleRecord->createBinding(newState, vec[i].m_name, false, vec[i].m_isMutable, true);
}
InterpretedCodeBlock::BlockInfo* bi = m_topCodeBlock->blockInfo(0);
if (bi) {
len = bi->m_identifiers.size();
for (size_t i = 0; i < len; i++) {
moduleRecord->createBinding(newState, bi->m_identifiers[i].m_name, false, bi->m_identifiers[i].m_isMutable, false);
}
}
// Test import, export first
// For each ImportEntry Record in in module.[[ImportEntries]], do
for (size_t i = 0; i < m_moduleData->m_importEntries.size(); i++) {
auto& in = m_moduleData->m_importEntries[i];
// Let importedModule be HostResolveImportedModule(module, in.[[ModuleRequest]]).
// ReturnIfAbrupt(importedModule).
Script* importedModule = findLoadedModule(context(), this, in.m_moduleRequest).value();
// If in.[[ImportName]] is "*", then
if (in.m_importName == context()->staticStrings().asciiTable[(unsigned char)'*']) {
} else {
// Let resolution be importedModule.ResolveExport(in.[[ImportName]], « », «‍ »).
auto resolution = importedModule->resolveExport(newState, in.m_importName);
// ReturnIfAbrupt(resolution).
// If resolution is null or resolution is "ambiguous", throw a SyntaxError exception.
// Call envRec.CreateImportBinding(in.[[LocalName]], resolution.[[module]], resolution.[[bindingName]]).
if (resolution.m_type == Script::ResolveExportResult::Null) {
StringBuilder builder;
builder.appendString("The requested module '");
builder.appendString(in.m_moduleRequest);
builder.appendString("' does not provide an export named '");
builder.appendString(in.m_localName.string());
builder.appendString("'");
ErrorObject::throwBuiltinError(newState, ErrorObject::Code::SyntaxError, builder.finalize(&newState)->toNonGCUTF8StringData().data());
} else if (resolution.m_type == Script::ResolveExportResult::Ambiguous) {
StringBuilder builder;
builder.appendString("The requested module '");
builder.appendString(in.m_moduleRequest);
builder.appendString("' does not provide an export named '");
builder.appendString(in.m_localName.string());
builder.appendString("' correctly");
ErrorObject::throwBuiltinError(newState, ErrorObject::Code::SyntaxError, builder.finalize(&newState)->toNonGCUTF8StringData().data());
}
}
}
// execute external modules
for (size_t i = 0; i < m_moduleData->m_importEntries.size(); i++) {
Script* script = findLoadedModule(context(), this, m_moduleData->m_importEntries[i].m_moduleRequest).value();
if (!script->isExecuted()) {
script->executeModule(state, this);
}
}
for (size_t i = 0; i < m_moduleData->m_indirectExportEntries.size(); i++) {
Script* script = findLoadedModule(context(), this, m_moduleData->m_indirectExportEntries[i].m_moduleRequest.value()).value();
if (!script->isExecuted()) {
script->executeModule(state, this);
}
}
for (size_t i = 0; i < m_moduleData->m_starExportEntries.size(); i++) {
Script* script = findLoadedModule(context(), this, m_moduleData->m_starExportEntries[i].m_moduleRequest.value()).value();
if (!script->isExecuted()) {
script->executeModule(state, this);
}
}
// Import variables
// For each ImportEntry Record in in module.[[ImportEntries]], do
for (size_t i = 0; i < m_moduleData->m_importEntries.size(); i++) {
auto& in = m_moduleData->m_importEntries[i];
// Let importedModule be HostResolveImportedModule(module, in.[[ModuleRequest]]).
// ReturnIfAbrupt(importedModule).
Script* importedModule = findLoadedModule(context(), this, in.m_moduleRequest).value();
// If in.[[ImportName]] is "*", then
if (in.m_importName == context()->staticStrings().asciiTable[(unsigned char)'*']) {
// Let namespace be GetModuleNamespace(importedModule).
// ReturnIfAbrupt(module).
ModuleNamespaceObject* namespaceObject = importedModule->moduleData()->m_moduleRecord->namespaceObject(newState);
// Let status be envRec.CreateImmutableBinding(in.[[LocalName]], true).
// Assert: status is not an abrupt completion.
// Call envRec.InitializeBinding(in.[[LocalName]], namespace).
moduleRecord->initializeBinding(newState, in.m_localName, Value(namespaceObject));
} else {
// Let resolution be importedModule.ResolveExport(in.[[ImportName]], « », «‍ »).
auto resolution = importedModule->resolveExport(newState, in.m_importName);
// ReturnIfAbrupt(resolution).
// If resolution is null or resolution is "ambiguous", throw a SyntaxError exception.
// Call envRec.CreateImportBinding(in.[[LocalName]], resolution.[[module]], resolution.[[bindingName]]).
ASSERT(resolution.m_type == Script::ResolveExportResult::Record);
auto bindingResult = std::get<0>(resolution.m_record.value())->moduleData()->m_moduleRecord->getBindingValue(newState, std::get<1>(resolution.m_record.value()));
ASSERT(bindingResult.m_hasBindingValue);
moduleRecord->initializeBinding(newState, in.m_localName, bindingResult.m_value);
}
}
newState.setLexicalEnvironment(new LexicalEnvironment(moduleRecord, globalLexicalEnv), true);
size_t literalStorageSize = byteCodeBlock->m_numeralLiteralData.size();
Value* registerFile = (Value*)ALLOCA((byteCodeBlock->m_requiredRegisterFileSizeInValueSize + 1 + literalStorageSize + m_topCodeBlock->lexicalBlockStackAllocatedIdentifierMaximumDepth()) * sizeof(Value), Value, state);
registerFile[0] = Value();
Value* stackStorage = registerFile + byteCodeBlock->m_requiredRegisterFileSizeInValueSize;
stackStorage[0] = Value();
Value* literalStorage = stackStorage + 1 + m_topCodeBlock->lexicalBlockStackAllocatedIdentifierMaximumDepth();
Value* src = byteCodeBlock->m_numeralLiteralData.data();
for (size_t i = 0; i < literalStorageSize; i++) {
literalStorage[i] = src[i];
}
Value resultValue = ByteCodeInterpreter::interpret(&newState, byteCodeBlock, 0, registerFile);
clearStack<512>();
// we give up program bytecodeblock after first excution for reducing memory usage
m_topCodeBlock->m_byteCodeBlock = nullptr;
return resultValue;
}
// https://www.ecma-international.org/ecma-262/9.0/#sec-candeclareglobalfunction
static bool canDeclareGlobalFunction(ExecutionState& state, Object* globalObject, AtomicString N)
{
@ -495,7 +308,22 @@ Value Script::execute(ExecutionState& state, bool isExecuteOnEvalFunction, bool
}
if (isModule()) {
return executeModule(state, nullptr);
ASSERT(!moduleData()->m_didCallLoadedCallback);
if (!moduleData()->m_didCallLoadedCallback) {
context()->vmInstance()->platform()->didLoadModule(context(), nullptr, this);
moduleData()->m_didCallLoadedCallback = true;
}
// https://www.ecma-international.org/ecma-262/#sec-toplevelmoduleevaluationjob
auto result = moduleInstantiate(state);
if (result.gotExecption) {
throw result.value;
}
result = moduleEvaluate(state);
if (result.gotExecption) {
throw result.value;
}
return result.value;
}
ByteCodeBlock* byteCodeBlock = m_topCodeBlock->byteCodeBlock();
@ -719,4 +547,398 @@ Value Script::executeLocal(ExecutionState& state, Value thisValue, InterpretedCo
return resultValue;
}
Script::ModuleExecutionResult Script::moduleInstantiate(ExecutionState& state)
{
// On success, Instantiate transitions this module's [[Status]] from "uninstantiated" to "instantiated". On failure, an exception is thrown and this module's [[Status]] remains "uninstantiated".
ASSERT(isModule());
// Let module be this Cyclic Module Record.
// Assert: module.[[Status]] is not "instantiating" or "evaluating".
ASSERT(moduleData()->m_status != ModuleData::Instantiating && moduleData()->m_status != ModuleData::Evaluating);
// Let stack be a new empty List.
std::vector<Script*> stack;
// Let result be InnerModuleInstantiation(module, stack, 0).
ModuleExecutionResult result = innerModuleInstantiation(state, stack, 0);
// If result is an abrupt completion, then
if (result.gotExecption) {
// For each module m in stack, do
for (size_t i = 0; i < stack.size(); i++) {
// Assert: m.[[Status]] is "instantiating".
ASSERT(stack[i]->isModule());
ModuleData* m = stack[i]->moduleData();
ASSERT(m->m_status == ModuleData::Instantiating);
// Set m.[[Status]] to "uninstantiated".
m->m_status = ModuleData::Uninstantiated;
// Set m.[[Environment]] to undefined.
m->m_moduleRecord = nullptr;
// Set m.[[DFSIndex]] to undefined.
m->m_dfsIndex.reset();
// Set m.[[DFSAncestorIndex]] to undefined.
m->m_dfsAncestorIndex.reset();
}
// Assert: module.[[Status]] is "uninstantiated".
ASSERT(moduleData()->m_status == ModuleData::Uninstantiated);
// Return result.
return result;
}
// Assert: module.[[Status]] is "instantiated" or "evaluated".
ASSERT(moduleData()->m_status == ModuleData::Instantiated || moduleData()->m_status == ModuleData::Evaluated);
// Assert: stack is empty.
ASSERT(stack.empty());
// Return undefined.
return ModuleExecutionResult(false, Value());
}
Script::ModuleExecutionResult Script::innerModuleInstantiation(ExecutionState& state, std::vector<Script*>& stack, uint32_t index)
{
// If module is not a Cyclic Module Record, then
// Perform ? module.Instantiate().
// Return index.
ASSERT(isModule());
// If module.[[Status]] is "instantiating", "instantiated", or "evaluated", then
ModuleData* md = moduleData();
if (md->m_status == ModuleData::Instantiating || md->m_status == ModuleData::Instantiated || md->m_status == ModuleData::Evaluated) {
// Return index.
return Script::ModuleExecutionResult(false, Value(index));
}
// Assert: module.[[Status]] is "uninstantiated".
ASSERT(md->m_status == ModuleData::Uninstantiated);
// Set module.[[Status]] to "instantiating".
md->m_status = ModuleData::Instantiating;
// Set module.[[DFSIndex]] to index.
md->m_dfsIndex = index;
// Set module.[[DFSAncestorIndex]] to index.
md->m_dfsAncestorIndex = index;
// Increase index by 1.
index++;
// Append module to stack.
stack.push_back(this);
// For each String required that is an element of module.[[RequestedModules]], do
size_t rmLength = moduleRequestsLength();
for (size_t i = 0; i < rmLength; i++) {
// Let requiredModule be ! HostResolveImportedModule(module, required).
Script* requiredModule = loadModuleFromScript(state, moduleRequest(i));
// NOTE: Instantiate must be completed successfully prior to invoking this method, so every requested module is guaranteed to resolve successfully.
// Set index to ? innerModuleInstantiation(requiredModule, stack, index).
auto result = requiredModule->innerModuleInstantiation(state, stack, index);
if (result.gotExecption) {
return result;
}
index = result.value.asNumber();
// Assert: requiredModule.[[Status]] is either "instantiating", "instantiated", or "evaluated".
ASSERT(requiredModule->moduleData()->m_status == ModuleData::Instantiating || requiredModule->moduleData()->m_status == ModuleData::Instantiated || requiredModule->moduleData()->m_status == ModuleData::Evaluated);
// Assert: requiredModule.[[Status]] is "instantiating" if and only if requiredModule is in stack.
if (requiredModule->moduleData()->m_status == ModuleData::Instantiating) {
bool onStack = false;
for (size_t j = 0; j < stack.size(); j++) {
if (stack[j] == requiredModule) {
onStack = true;
break;
}
}
ASSERT(onStack);
}
// If requiredModule.[[Status]] is "instantiating", then
if (requiredModule->moduleData()->m_status == ModuleData::Instantiating) {
// Set module.[[DFSAncestorIndex]] to min(module.[[DFSAncestorIndex]], requiredModule.[[DFSAncestorIndex]]).
md->m_dfsAncestorIndex = std::min(md->m_dfsAncestorIndex.value(), requiredModule->moduleData()->m_dfsAncestorIndex.value());
}
}
// Perform ? module.InitializeEnvironment().
auto result = moduleInitializeEnvironment(state);
if (!result.isEmpty()) {
return Script::ModuleExecutionResult(true, result);
}
// Assert: module occurs exactly once in stack.
// Assert: module.[[DFSAncestorIndex]] is less than or equal to module.[[DFSIndex]].
ASSERT(md->m_dfsAncestorIndex.value() <= md->m_dfsIndex.value());
// If module.[[DFSAncestorIndex]] equals module.[[DFSIndex]], then
if (md->m_dfsAncestorIndex.value() == md->m_dfsIndex.value()) {
// Let done be false.
bool done = false;
// Repeat, while done is false,
while (!done) {
// Let requiredModule be the last element in stack.
Script* requiredModule = stack.back();
// Remove the last element of stack.
stack.pop_back();
// Set requiredModule.[[Status]] to "instantiated".
requiredModule->moduleData()->m_status = ModuleData::Instantiated;
// If requiredModule and module are the same Module Record, set done to true.
if (requiredModule == this) {
done = true;
}
}
}
// Return index.
return Script::ModuleExecutionResult(false, Value(index));
}
Script::ModuleExecutionResult Script::moduleEvaluate(ExecutionState& state)
{
// Let module be this Cyclic Module Record.
ModuleData* md = moduleData();
// Assert: module.[[Status]] is "instantiated" or "evaluated".
ASSERT(md->m_status == ModuleData::Instantiated || md->m_status == ModuleData::Evaluated);
// Let stack be a new empty List.
std::vector<Script*> stack;
// Let result be InnerModuleEvaluation(module, stack, 0).
auto result = innerModuleEvaluation(state, stack, 0);
// If result is an abrupt completion, then
if (result.gotExecption) {
// For each module m in stack, do
for (size_t i = 0; i < stack.size(); i++) {
// Assert: m.[[Status]] is "evaluating".
ASSERT(stack[i]->moduleData()->m_status == ModuleData::Evaluating);
// Set m.[[Status]] to "evaluated".
// Set m.[[EvaluationError]] to result.
// Assert: module.[[Status]] is "evaluated" and module.[[EvaluationError]] is result.
stack[i]->moduleData()->m_status = ModuleData::Evaluated;
stack[i]->moduleData()->m_evaluationError = result.value;
}
// Return result.
return result;
}
// Assert: module.[[Status]] is "evaluated" and module.[[EvaluationError]] is undefined.
// Assert: stack is empty.
// Return undefined.
return ModuleExecutionResult(false, Value());
}
Script::ModuleExecutionResult Script::innerModuleEvaluation(ExecutionState& state, std::vector<Script*>& stack, uint32_t index)
{
// If module is not a Cyclic Module Record, then
// Perform ? module.Evaluate().
// Return index.
ASSERT(isModule());
ModuleData* md = moduleData();
// If module.[[Status]] is "evaluated", then
if (md->m_status == ModuleData::Evaluated) {
// If module.[[EvaluationError]] is undefined, return index.
if (md->m_evaluationError == SmallValue()) {
return Script::ModuleExecutionResult(false, Value(index));
}
// Otherwise return module.[[EvaluationError]].
return Script::ModuleExecutionResult(true, md->m_evaluationError);
}
// If module.[[Status]] is "evaluating", return index.
if (md->m_status == ModuleData::Evaluating) {
return Script::ModuleExecutionResult(false, Value(index));
}
// Assert: module.[[Status]] is "instantiated".
ASSERT(md->m_status == ModuleData::Instantiated);
// Set module.[[Status]] to "evaluating".
md->m_status = ModuleData::Evaluating;
// Set module.[[DFSIndex]] to index.
md->m_dfsIndex = index;
// Set module.[[DFSAncestorIndex]] to index.
md->m_dfsAncestorIndex = index;
// Increase index by 1.
index++;
// Append module to stack.
stack.push_back(this);
// For each String required that is an element of module.[[RequestedModules]], do
size_t rmLength = moduleRequestsLength();
for (size_t i = 0; i < rmLength; i++) {
// Let requiredModule be ! HostResolveImportedModule(module, required).
Script* requiredModule = loadModuleFromScript(state, moduleRequest(i));
// NOTE: Instantiate must be completed successfully prior to invoking this method, so every requested module is guaranteed to resolve successfully.
// Set index to ? InnerModuleEvaluation(requiredModule, stack, index).
auto result = requiredModule->innerModuleEvaluation(state, stack, index);
if (result.gotExecption) {
return result;
}
index = result.value.asNumber();
// Assert: requiredModule.[[Status]] is either "evaluating" or "evaluated".
ASSERT(requiredModule->moduleData()->m_status == ModuleData::Evaluating || requiredModule->moduleData()->m_status == ModuleData::Evaluated);
// Assert: requiredModule.[[Status]] is "evaluating" if and only if requiredModule is in stack.
#if !defined(NDEBUG)
if (requiredModule->moduleData()->m_status == ModuleData::Evaluating) {
bool onStack = false;
for (size_t j = 0; j < stack.size(); j++) {
if (stack[j] == requiredModule) {
onStack = true;
break;
}
}
ASSERT(onStack);
}
#endif
// If requiredModule.[[Status]] is "evaluating", then
if (requiredModule->moduleData()->m_status == ModuleData::Evaluating) {
// Assert: requiredModule is a Cyclic Module Record.
ASSERT(requiredModule->isModule());
// Set module.[[DFSAncestorIndex]] to min(module.[[DFSAncestorIndex]], requiredModule.[[DFSAncestorIndex]]).
md->m_dfsAncestorIndex = std::min(md->m_dfsAncestorIndex.value(), requiredModule->moduleData()->m_dfsAncestorIndex.value());
}
}
// Perform ? module.ExecuteModule().
auto result = moduleExecute(state);
if (result.gotExecption) {
return result;
}
// Assert: module occurs exactly once in stack.
// Assert: module.[[DFSAncestorIndex]] is less than or equal to module.[[DFSIndex]].
ASSERT(md->m_dfsAncestorIndex.value() <= md->m_dfsIndex.value());
// If module.[[DFSAncestorIndex]] equals module.[[DFSIndex]], then
if (md->m_dfsAncestorIndex.value() == md->m_dfsIndex.value()) {
// Let done be false.
bool done = false;
// Repeat, while done is false,
while (!done) {
// Let requiredModule be the last element in stack.
Script* requiredModule = stack.back();
// Remove the last element of stack.
stack.pop_back();
// Set requiredModule.[[Status]] to "evaluated".
requiredModule->moduleData()->m_status = ModuleData::Evaluated;
// If requiredModule and module are the same Module Record, set done to true.
if (requiredModule == this) {
done = true;
}
}
}
// Return index.
return Script::ModuleExecutionResult(false, Value(index));
}
Value Script::moduleInitializeEnvironment(ExecutionState& state)
{
ASSERT(m_moduleData->m_moduleRecord == nullptr);
// For each ExportEntry Record e in module.[[IndirectExportEntries]], do
auto& indirectExportEntries = m_moduleData->m_indirectExportEntries;
for (size_t i = 0; i < indirectExportEntries.size(); i++) {
auto& e = indirectExportEntries[i];
// Let resolution be ? module.ResolveExport(e.[[ExportName]], « »).
auto resolution = resolveExport(state, e.m_exportName.value());
// If resolution is null or "ambiguous", throw a SyntaxError exception.
if (resolution.m_type == ResolveExportResult::Null || resolution.m_type == ResolveExportResult::Ambiguous) {
StringBuilder builder;
builder.appendString("The export binding '");
builder.appendString(e.m_exportName.value().string());
builder.appendString("' is ambiguous");
return ErrorObject::createBuiltinError(state, ErrorObject::Code::SyntaxError, builder.finalize(&state)->toNonGCUTF8StringData().data());
}
// Assert: resolution is a ResolvedBinding Record.
}
ModuleEnvironmentRecord* moduleRecord = new ModuleEnvironmentRecord(this);
m_moduleData->m_moduleRecord = moduleRecord;
const InterpretedCodeBlock::IdentifierInfoVector& vec = m_topCodeBlock->identifierInfos();
size_t len = vec.size();
for (size_t i = 0; i < len; i++) {
moduleRecord->createBinding(state, vec[i].m_name, false, vec[i].m_isMutable, true);
}
InterpretedCodeBlock::BlockInfo* bi = m_topCodeBlock->blockInfo(0);
if (bi) {
len = bi->m_identifiers.size();
for (size_t i = 0; i < len; i++) {
moduleRecord->createBinding(state, bi->m_identifiers[i].m_name, false, bi->m_identifiers[i].m_isMutable, false);
}
}
// For each ImportEntry Record in in module.[[ImportEntries]], do
for (size_t i = 0; i < m_moduleData->m_importEntries.size(); i++) {
auto& in = m_moduleData->m_importEntries[i];
// Let importedModule be ! HostResolveImportedModule(module, in.[[ModuleRequest]]).
Script* importedModule = loadModuleFromScript(state, in.m_moduleRequest);
// NOTE: The above call cannot fail because imported module requests are a subset of module.[[RequestedModules]], and these have been resolved earlier in this algorithm.
// If in.[[ImportName]] is "*", then
if (in.m_importName == context()->staticStrings().asciiTable[(unsigned char)'*']) {
// Let namespace be ? GetModuleNamespace(importedModule).
ModuleNamespaceObject* namespaceObject = importedModule->moduleData()->m_moduleRecord->namespaceObject(state);
// Perform ! envRec.CreateImmutableBinding(in.[[LocalName]], true).
// Call envRec.InitializeBinding(in.[[LocalName]], namespace).
moduleRecord->initializeBinding(state, in.m_localName, namespaceObject);
} else {
// Let resolution be importedModule.ResolveExport(in.[[ImportName]], « », «‍ »).
auto resolution = importedModule->resolveExport(state, in.m_importName);
// ReturnIfAbrupt(resolution).
// If resolution is null or resolution is "ambiguous", throw a SyntaxError exception.
if (resolution.m_type == Script::ResolveExportResult::Null) {
StringBuilder builder;
builder.appendString("The requested module '");
builder.appendString(in.m_moduleRequest);
builder.appendString("' does not provide an export named '");
builder.appendString(in.m_localName.string());
builder.appendString("'");
return ErrorObject::createBuiltinError(state, ErrorObject::Code::SyntaxError, builder.finalize(&state)->toNonGCUTF8StringData().data());
} else if (resolution.m_type == Script::ResolveExportResult::Ambiguous) {
StringBuilder builder;
builder.appendString("The requested module '");
builder.appendString(in.m_moduleRequest);
builder.appendString("' does not provide an export named '");
builder.appendString(in.m_localName.string());
builder.appendString("' correctly");
return ErrorObject::createBuiltinError(state, ErrorObject::Code::SyntaxError, builder.finalize(&state)->toNonGCUTF8StringData().data());
}
ASSERT(std::get<0>(resolution.m_record.value())->moduleData()->m_moduleRecord != nullptr);
// Call envRec.CreateImportBinding(in.[[LocalName]], resolution.[[module]], resolution.[[bindingName]]).
moduleRecord->createImportBinding(state, in.m_localName, std::get<0>(resolution.m_record.value())->moduleData()->m_moduleRecord, std::get<1>(resolution.m_record.value()));
}
}
return Value(Value::EmptyValue);
}
Script::ModuleExecutionResult Script::moduleExecute(ExecutionState& state)
{
ASSERT(isModule());
ByteCodeBlock* byteCodeBlock = m_topCodeBlock->byteCodeBlock();
LexicalEnvironment* globalLexicalEnv = new LexicalEnvironment(
new GlobalEnvironmentRecord(state, m_topCodeBlock, context()->globalObject(), context()->globalDeclarativeRecord(), context()->globalDeclarativeStorage()), nullptr);
ExecutionState newState(context(), state.stackLimit());
newState.setLexicalEnvironment(new LexicalEnvironment(moduleData()->m_moduleRecord, globalLexicalEnv), true);
size_t literalStorageSize = byteCodeBlock->m_numeralLiteralData.size();
Value* registerFile = (Value*)ALLOCA((byteCodeBlock->m_requiredRegisterFileSizeInValueSize + 1 + literalStorageSize + m_topCodeBlock->lexicalBlockStackAllocatedIdentifierMaximumDepth()) * sizeof(Value), Value, state);
registerFile[0] = Value();
Value* stackStorage = registerFile + byteCodeBlock->m_requiredRegisterFileSizeInValueSize;
stackStorage[0] = Value();
Value* literalStorage = stackStorage + 1 + m_topCodeBlock->lexicalBlockStackAllocatedIdentifierMaximumDepth();
Value* src = byteCodeBlock->m_numeralLiteralData.data();
for (size_t i = 0; i < literalStorageSize; i++) {
literalStorage[i] = src[i];
}
Value resultValue;
bool gotExecption = false;
try {
ByteCodeInterpreter::interpret(&newState, byteCodeBlock, 0, registerFile);
} catch (const Value& e) {
resultValue = e;
gotExecption = true;
}
clearStack<512>();
// we give up program bytecodeblock after first excution for reducing memory usage
m_topCodeBlock->m_byteCodeBlock = nullptr;
return ModuleExecutionResult(gotExecption, resultValue);
}
}

View file

@ -63,8 +63,15 @@ public:
};
typedef Vector<ExportEntry, GCUtil::gc_malloc_allocator<ExportEntry>> ExportEntryVector;
// http://www.ecma-international.org/ecma-262/6.0/#sec-source-text-module-records
struct ModuleData : public gc {
bool m_didCallLoadedCallback;
// Abstract Module Records
// https://www.ecma-international.org/ecma-262/#sec-abstract-module-records
// [[Environment]]
ModuleEnvironmentRecord* m_moduleRecord; // this record contains namespace object
// Source Text Module Records
// https://www.ecma-international.org/ecma-262/#sec-source-text-module-records
// [[ImportEntries]]
ImportEntryVector m_importEntries;
// [[LocalExportEntries]]
@ -73,12 +80,31 @@ public:
ExportEntryVector m_indirectExportEntries;
// [[StarExportEntries]]
ExportEntryVector m_starExportEntries;
// [[RequestedModules]]
StringVector m_requestedModules;
ModuleEnvironmentRecord* m_moduleRecord;
// Cyclic Module Records
// https://www.ecma-international.org/ecma-262/#sec-cyclic-module-records
enum ModuleStatus {
Uninstantiated,
Instantiating,
Instantiated,
Evaluating,
Evaluated
};
// [[Status]]
ModuleStatus m_status;
// [[EvaluationError]]
SmallValue m_evaluationError;
// [[DFSIndex]]
Optional<uint32_t> m_dfsIndex;
// [[DFSAncestorIndex]]
Optional<uint32_t> m_dfsAncestorIndex;
// [[RequestedModules]] is same with moduleRequests
// StringVector m_requestedModules;
ModuleData()
: m_moduleRecord(nullptr)
: m_didCallLoadedCallback(false)
, m_moduleRecord(nullptr)
, m_status(Uninstantiated)
{
}
};
@ -126,7 +152,7 @@ private:
{
}
Value executeLocal(ExecutionState& state, Value thisValue, InterpretedCodeBlock* parentCodeBlock, bool isStrictModeOutside = false, bool isEvalCodeOnFunction = false);
void loadModuleFromScript(ExecutionState& state, String* src);
Script* loadModuleFromScript(ExecutionState& state, String* src);
void loadExternalModule(ExecutionState& state);
Value executeModule(ExecutionState& state, Optional<Script*> referrer);
struct ResolveExportResult {
@ -151,7 +177,8 @@ private:
std::vector<Script*> exportStarSet;
return resolveExport(state, exportName, resolveSet, exportStarSet);
}
// http://www.ecma-international.org/ecma-262/6.0/#sec-resolveexport
// https://www.ecma-international.org/ecma-262/#sec-resolveexport
ResolveExportResult resolveExport(ExecutionState& state, AtomicString exportName, std::vector<std::tuple<Script*, AtomicString>>& resolveSet, std::vector<Script*>& exportStarSet);
AtomicStringVector exportedNames(ExecutionState& state)
{
@ -160,6 +187,36 @@ private:
}
// http://www.ecma-international.org/ecma-262/6.0/#sec-getexportednames
AtomicStringVector exportedNames(ExecutionState& state, std::vector<Script*>& exportStarSet);
struct ModuleExecutionResult {
bool gotExecption;
Value value;
ModuleExecutionResult(bool gotExecption, Value value)
: gotExecption(gotExecption)
, value(value)
{
}
};
// https://www.ecma-international.org/ecma-262/#sec-moduledeclarationinstantiation
ModuleExecutionResult moduleInstantiate(ExecutionState& state);
// https://www.ecma-international.org/ecma-262/#sec-innermoduleinstantiation
ModuleExecutionResult innerModuleInstantiation(ExecutionState& state, std::vector<Script*>& stack, uint32_t index);
// https://www.ecma-international.org/ecma-262/#sec-moduleevaluation
ModuleExecutionResult moduleEvaluate(ExecutionState& state);
// https://www.ecma-international.org/ecma-262/#sec-innermoduleevaluation
ModuleExecutionResult innerModuleEvaluation(ExecutionState& state, std::vector<Script*>& stack, uint32_t index);
// https://www.ecma-international.org/ecma-262/#sec-source-text-module-record-initialize-environment
Value moduleInitializeEnvironment(ExecutionState& state);
// https://www.ecma-international.org/ecma-262/#sec-source-text-module-record-execute-module
// returns gotExecption and Value
ModuleExecutionResult moduleExecute(ExecutionState& state);
bool m_canExecuteAgain;
String* m_src;
String* m_sourceCode;

View file

@ -415,9 +415,9 @@ template class FunctionEnvironmentRecordNotIndexed<false, true>;
EnvironmentRecord::BindingSlot ModuleEnvironmentRecord::hasBinding(ExecutionState& state, const AtomicString& atomicName)
{
for (size_t i = 0; i < m_moduleDeclarativeRecord.size(); i++) {
if (m_moduleDeclarativeRecord[i].m_name == atomicName) {
return BindingSlot(this, i, !m_moduleDeclarativeRecord[i].m_isVarDeclaration);
for (size_t i = 0; i < m_moduleBindings.size(); i++) {
if (m_moduleBindings[i].m_localName == atomicName) {
return BindingSlot(this, i, !m_moduleBindings[i].m_isVarDeclaration);
}
}
return BindingSlot(this, SIZE_MAX, false);
@ -427,29 +427,26 @@ void ModuleEnvironmentRecord::createBinding(ExecutionState& state, const AtomicS
{
auto hasBindingResult = hasBinding(state, name);
if (UNLIKELY(hasBindingResult.m_index != SIZE_MAX)) {
if (!m_moduleDeclarativeRecord[hasBindingResult.m_index].m_isVarDeclaration || !isVarDeclaration) {
if (!m_moduleBindings[hasBindingResult.m_index].m_isVarDeclaration || !isVarDeclaration) {
ErrorObject::throwBuiltinError(state, ErrorObject::SyntaxError, name.string(), false, String::emptyString, ErrorObject::Messages::DuplicatedIdentifier);
}
return;
}
IdentifierRecord record;
record.m_name = name;
record.m_canDelete = false;
ModuleBindingRecord record;
record.m_localName = name;
record.m_isMutable = isMutable;
record.m_isVarDeclaration = isVarDeclaration;
m_moduleDeclarativeRecord.pushBack(record);
if (isVarDeclaration) {
m_moduleDeclarativeStorage.pushBack(Value());
} else {
m_moduleDeclarativeStorage.pushBack(Value(Value::EmptyValue));
}
record.m_targetRecord = nullptr;
record.m_value = isVarDeclaration ? Value() : Value(Value::EmptyValue);
m_moduleBindings.pushBack(record);
}
void ModuleEnvironmentRecord::initializeBinding(ExecutionState& state, const AtomicString& name, const Value& V)
{
for (size_t i = 0; i < m_moduleDeclarativeRecord.size(); i++) {
if (m_moduleDeclarativeRecord[i].m_name == name) {
m_moduleDeclarativeStorage[i] = V;
for (size_t i = 0; i < m_moduleBindings.size(); i++) {
if (m_moduleBindings[i].m_localName == name) {
ASSERT(m_moduleBindings[i].m_targetRecord == nullptr);
m_moduleBindings[i].m_value = V;
return;
}
}
@ -458,11 +455,11 @@ void ModuleEnvironmentRecord::initializeBinding(ExecutionState& state, const Ato
void ModuleEnvironmentRecord::setMutableBinding(ExecutionState& state, const AtomicString& name, const Value& V)
{
size_t len = m_moduleDeclarativeRecord.size();
size_t len = m_moduleBindings.size();
for (size_t i = 0; i < len; i++) {
if (m_moduleDeclarativeRecord[i].m_name == name) {
if (m_moduleBindings[i].m_localName == name) {
writeCheck(state, i);
m_moduleDeclarativeStorage[i] = V;
m_moduleBindings[i].m_value = V;
return;
}
}
@ -471,28 +468,35 @@ void ModuleEnvironmentRecord::setMutableBinding(ExecutionState& state, const Ato
void ModuleEnvironmentRecord::setMutableBindingByBindingSlot(ExecutionState& state, const BindingSlot& slot, const AtomicString& name, const Value& v)
{
ASSERT(m_moduleBindings[slot.m_index].m_targetRecord == nullptr);
writeCheck(state, slot.m_index);
m_moduleDeclarativeStorage[slot.m_index] = v;
m_moduleBindings[slot.m_index].m_value = v;
}
void ModuleEnvironmentRecord::setMutableBindingByIndex(ExecutionState& state, const size_t i, const Value& v)
{
ASSERT(m_moduleBindings[i].m_targetRecord == nullptr);
writeCheck(state, i);
m_moduleDeclarativeStorage[i] = v;
m_moduleBindings[i].m_value = v;
}
void ModuleEnvironmentRecord::initializeBindingByIndex(ExecutionState& state, const size_t idx, const Value& v)
{
m_moduleDeclarativeStorage[idx] = v;
ASSERT(m_moduleBindings[idx].m_targetRecord == nullptr);
m_moduleBindings[idx].m_value = v;
}
EnvironmentRecord::GetBindingValueResult ModuleEnvironmentRecord::getBindingValue(ExecutionState& state, const AtomicString& name)
{
size_t len = m_moduleDeclarativeRecord.size();
size_t len = m_moduleBindings.size();
for (size_t i = 0; i < len; i++) {
if (m_moduleDeclarativeRecord[i].m_name == name) {
readCheck(state, i);
return GetBindingValueResult(m_moduleDeclarativeStorage[i]);
if (m_moduleBindings[i].m_localName == name) {
if (m_moduleBindings[i].m_targetRecord) {
return m_moduleBindings[i].m_targetRecord->getBindingValue(state, m_moduleBindings[i].m_targetBindingName);
} else {
readCheck(state, i);
return GetBindingValueResult(m_moduleBindings[i].m_value);
}
}
}
return GetBindingValueResult();
@ -500,20 +504,49 @@ EnvironmentRecord::GetBindingValueResult ModuleEnvironmentRecord::getBindingValu
Value ModuleEnvironmentRecord::getBindingValue(ExecutionState& state, const size_t i)
{
readCheck(state, i);
return m_moduleDeclarativeStorage[i];
if (m_moduleBindings[i].m_targetRecord) {
return m_moduleBindings[i].m_targetRecord->getBindingValue(state, m_moduleBindings[i].m_targetBindingName).m_value;
} else {
readCheck(state, i);
return m_moduleBindings[i].m_value;
}
}
void ModuleEnvironmentRecord::setHeapValueByIndex(ExecutionState& state, const size_t idx, const Value& v)
{
writeCheck(state, idx);
m_moduleDeclarativeStorage[idx] = v;
ASSERT(m_moduleBindings[idx].m_targetRecord == nullptr);
m_moduleBindings[idx].m_value = v;
}
Value ModuleEnvironmentRecord::getHeapValueByIndex(ExecutionState& state, const size_t idx)
Value ModuleEnvironmentRecord::getHeapValueByIndex(ExecutionState& state, const size_t i)
{
readCheck(state, idx);
return m_moduleDeclarativeStorage[idx];
if (m_moduleBindings[i].m_targetRecord) {
return m_moduleBindings[i].m_targetRecord->getBindingValue(state, m_moduleBindings[i].m_targetBindingName).m_value;
} else {
readCheck(state, i);
return m_moduleBindings[i].m_value;
}
}
void ModuleEnvironmentRecord::createImportBinding(ExecutionState& state, AtomicString localName, ModuleEnvironmentRecord* targetRecord, AtomicString targetBindingName)
{
// Let envRec be the module Environment Record for which the method was invoked.
// Assert: envRec does not already have a binding for N.
// Assert: M is a Module Record.
// Assert: When M.[[Environment]] is instantiated it will have a direct binding for N2.
// Create an immutable indirect binding in envRec for N that references M and N2 as its target binding and record that the binding is initialized.
// Return NormalCompletion(empty).
size_t len = m_moduleBindings.size();
for (size_t i = 0; i < len; i++) {
if (m_moduleBindings[i].m_localName == localName) {
ASSERT(m_moduleBindings[i].m_targetRecord == nullptr);
m_moduleBindings[i].m_targetRecord = targetRecord;
m_moduleBindings[i].m_targetBindingName = targetBindingName;
return;
}
}
ASSERT_NOT_REACHED();
}
ModuleNamespaceObject* ModuleEnvironmentRecord::namespaceObject(ExecutionState& state)

View file

@ -527,6 +527,20 @@ public:
RELEASE_ASSERT_NOT_REACHED();
}
void* operator new(size_t size)
{
static bool typeInited = false;
static GC_descr descr;
if (!typeInited) {
GC_word objBitmap[GC_BITMAP_SIZE(DeclarativeEnvironmentRecordIndexed)] = { 0 };
GC_set_bit(objBitmap, GC_WORD_OFFSET(DeclarativeEnvironmentRecordIndexed, m_blockInfo));
GC_set_bit(objBitmap, GC_WORD_OFFSET(DeclarativeEnvironmentRecordIndexed, m_heapStorage));
descr = GC_make_descriptor(objBitmap, GC_WORD_LEN(DeclarativeEnvironmentRecordIndexed));
typeInited = true;
}
return GC_MALLOC_EXPLICITLY_TYPED(size, descr);
}
private:
InterpretedCodeBlock::BlockInfo* m_blockInfo;
SmallValueVector m_heapStorage;
@ -588,6 +602,20 @@ public:
virtual void initializeBinding(ExecutionState& state, const AtomicString& name, const Value& V) override;
void* operator new(size_t size)
{
static bool typeInited = false;
static GC_descr descr;
if (!typeInited) {
GC_word objBitmap[GC_BITMAP_SIZE(DeclarativeEnvironmentRecordNotIndexed)] = { 0 };
GC_set_bit(objBitmap, GC_WORD_OFFSET(DeclarativeEnvironmentRecordNotIndexed, m_heapStorage));
GC_set_bit(objBitmap, GC_WORD_OFFSET(DeclarativeEnvironmentRecordNotIndexed, m_recordVector));
descr = GC_make_descriptor(objBitmap, GC_WORD_LEN(DeclarativeEnvironmentRecordNotIndexed));
typeInited = true;
}
return GC_MALLOC_EXPLICITLY_TYPED(size, descr);
}
private:
bool m_isVarDeclarationTarget : 1;
bool m_isCatchClause : 1;
@ -1083,6 +1111,17 @@ class ModuleEnvironmentRecord : public DeclarativeEnvironmentRecord {
friend class Debugger;
#endif /* ESCARGOT_DEBUGGER */
public:
struct ModuleBindingRecord {
bool m_isMutable;
bool m_isVarDeclaration;
AtomicString m_localName;
SmallValue m_value;
ModuleEnvironmentRecord* m_targetRecord;
AtomicString m_targetBindingName;
};
typedef Vector<ModuleBindingRecord, GCUtil::gc_malloc_allocator<ModuleBindingRecord>> ModuleBindingRecordVector;
ModuleEnvironmentRecord(Script* script)
: DeclarativeEnvironmentRecord()
, m_script(script)
@ -1126,27 +1165,48 @@ public:
return m_script;
}
void* operator new(size_t size)
{
static bool typeInited = false;
static GC_descr descr;
if (!typeInited) {
GC_word objBitmap[GC_BITMAP_SIZE(ModuleEnvironmentRecord)] = { 0 };
GC_set_bit(objBitmap, GC_WORD_OFFSET(ModuleEnvironmentRecord, m_moduleBindings));
GC_set_bit(objBitmap, GC_WORD_OFFSET(ModuleEnvironmentRecord, m_script));
GC_set_bit(objBitmap, GC_WORD_OFFSET(ModuleEnvironmentRecord, m_namespaceObject));
descr = GC_make_descriptor(objBitmap, GC_WORD_LEN(ModuleEnvironmentRecord));
typeInited = true;
}
return GC_MALLOC_EXPLICITLY_TYPED(size, descr);
}
void createImportBinding(ExecutionState& state, AtomicString localName, ModuleEnvironmentRecord* targetRecord, AtomicString targetBindingName);
protected:
const ModuleBindingRecordVector& moduleBindings()
{
return m_moduleBindings;
}
void readCheck(ExecutionState& state, const size_t i)
{
if (UNLIKELY(m_moduleDeclarativeStorage[i].isEmpty())) {
ErrorObject::throwBuiltinError(state, ErrorObject::ReferenceError, m_moduleDeclarativeRecord[i].m_name.string(), false, String::emptyString, ErrorObject::Messages::IsNotInitialized);
if (UNLIKELY(m_moduleBindings[i].m_value.isEmpty())) {
ErrorObject::throwBuiltinError(state, ErrorObject::ReferenceError, m_moduleBindings[i].m_localName.string(), false, String::emptyString, ErrorObject::Messages::IsNotInitialized);
}
}
void writeCheck(ExecutionState& state, const size_t i)
{
if (UNLIKELY(!m_moduleDeclarativeRecord[i].m_isMutable)) {
ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::AssignmentToConstantVariable, m_moduleDeclarativeRecord[i].m_name);
if (UNLIKELY(!m_moduleBindings[i].m_isMutable)) {
ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::AssignmentToConstantVariable, m_moduleBindings[i].m_localName);
}
if (UNLIKELY(!m_moduleDeclarativeRecord[i].m_isVarDeclaration && m_moduleDeclarativeStorage[i].isEmpty())) {
ErrorObject::throwBuiltinError(state, ErrorObject::ReferenceError, m_moduleDeclarativeRecord[i].m_name.string(), false, String::emptyString, ErrorObject::Messages::IsNotInitialized);
if (UNLIKELY(!m_moduleBindings[i].m_isVarDeclaration && m_moduleBindings[i].m_value.isEmpty())) {
ErrorObject::throwBuiltinError(state, ErrorObject::ReferenceError, m_moduleBindings[i].m_localName.string(), false, String::emptyString, ErrorObject::Messages::IsNotInitialized);
}
}
IdentifierRecordVector m_moduleDeclarativeRecord;
SmallValueVector m_moduleDeclarativeStorage;
ModuleBindingRecordVector m_moduleBindings;
Script* m_script;
ModuleNamespaceObject* m_namespaceObject;
};

View file

@ -23,7 +23,27 @@
namespace Escargot {
void ErrorObject::throwBuiltinError(ExecutionState& state, Code code, String* objectName, bool prototype, String* functionName, const char* templateString)
ErrorObject* ErrorObject::createError(ExecutionState& state, ErrorObject::Code code, String* errorMessage)
{
switch (code) {
case ReferenceError:
return new ReferenceErrorObject(state, state.context()->globalObject()->referenceErrorPrototype(), errorMessage);
case TypeError:
return new TypeErrorObject(state, state.context()->globalObject()->typeErrorPrototype(), errorMessage);
case SyntaxError:
return new SyntaxErrorObject(state, state.context()->globalObject()->syntaxErrorPrototype(), errorMessage);
case RangeError:
return new RangeErrorObject(state, state.context()->globalObject()->rangeErrorPrototype(), errorMessage);
case URIError:
return new URIErrorObject(state, state.context()->globalObject()->uriErrorPrototype(), errorMessage);
case EvalError:
return new EvalErrorObject(state, state.context()->globalObject()->evalErrorPrototype(), errorMessage);
default:
return new ErrorObject(state, state.context()->globalObject()->errorPrototype(), errorMessage);
}
}
ErrorObject* ErrorObject::createBuiltinError(ExecutionState& state, Code code, String* objectName, bool prototype, String* functionName, const char* templateString)
{
StringBuilder replacerBuilder;
if (objectName->length()) {
@ -56,29 +76,34 @@ void ErrorObject::throwBuiltinError(ExecutionState& state, Code code, String* ob
errorMessage = new UTF16String(str.data(), str.length());
switch (code) {
case ReferenceError:
state.throwException(new ReferenceErrorObject(state, state.context()->globalObject()->referenceErrorPrototype(), errorMessage));
return new ReferenceErrorObject(state, state.context()->globalObject()->referenceErrorPrototype(), errorMessage);
break;
case TypeError:
state.throwException(new TypeErrorObject(state, state.context()->globalObject()->typeErrorPrototype(), errorMessage));
return new TypeErrorObject(state, state.context()->globalObject()->typeErrorPrototype(), errorMessage);
break;
case SyntaxError:
state.throwException(new SyntaxErrorObject(state, state.context()->globalObject()->syntaxErrorPrototype(), errorMessage));
return new SyntaxErrorObject(state, state.context()->globalObject()->syntaxErrorPrototype(), errorMessage);
break;
case RangeError:
state.throwException(new RangeErrorObject(state, state.context()->globalObject()->rangeErrorPrototype(), errorMessage));
return new RangeErrorObject(state, state.context()->globalObject()->rangeErrorPrototype(), errorMessage);
break;
case URIError:
state.throwException(new URIErrorObject(state, state.context()->globalObject()->uriErrorPrototype(), errorMessage));
return new URIErrorObject(state, state.context()->globalObject()->uriErrorPrototype(), errorMessage);
break;
case EvalError:
state.throwException(new EvalErrorObject(state, state.context()->globalObject()->evalErrorPrototype(), errorMessage));
return new EvalErrorObject(state, state.context()->globalObject()->evalErrorPrototype(), errorMessage);
break;
default:
state.throwException(new ErrorObject(state, state.context()->globalObject()->errorPrototype(), errorMessage));
return new ErrorObject(state, state.context()->globalObject()->errorPrototype(), errorMessage);
break;
}
}
void ErrorObject::throwBuiltinError(ExecutionState& state, Code code, String* objectName, bool prototype, String* functionName, const char* templateString)
{
state.throwException(Value(ErrorObject::createBuiltinError(state, code, objectName, prototype, functionName, templateString)));
}
ErrorObject::ErrorObject(ExecutionState& state, Object* proto, String* errorMessage)
: Object(state, proto)
, m_stackTraceData(nullptr)
@ -89,26 +114,6 @@ ErrorObject::ErrorObject(ExecutionState& state, Object* proto, String* errorMess
}
}
ErrorObject* ErrorObject::createError(ExecutionState& state, ErrorObject::Code code, String* errorMessage)
{
switch (code) {
case ReferenceError:
return new ReferenceErrorObject(state, state.context()->globalObject()->referenceErrorPrototype(), errorMessage);
case TypeError:
return new TypeErrorObject(state, state.context()->globalObject()->typeErrorPrototype(), errorMessage);
case SyntaxError:
return new SyntaxErrorObject(state, state.context()->globalObject()->syntaxErrorPrototype(), errorMessage);
case RangeError:
return new RangeErrorObject(state, state.context()->globalObject()->rangeErrorPrototype(), errorMessage);
case URIError:
return new URIErrorObject(state, state.context()->globalObject()->uriErrorPrototype(), errorMessage);
case EvalError:
return new EvalErrorObject(state, state.context()->globalObject()->evalErrorPrototype(), errorMessage);
default:
return new ErrorObject(state, state.context()->globalObject()->errorPrototype(), errorMessage);
}
}
ReferenceErrorObject::ReferenceErrorObject(ExecutionState& state, Object* proto, String* errorMessage)
: ErrorObject(state, proto, errorMessage)
{

View file

@ -132,8 +132,13 @@ public:
{
throwBuiltinError(state, code, templateDataString, false, String::emptyString, templateString);
}
static void throwBuiltinError(ExecutionState& state, Code code, String* objectName, bool prototype, String* functionName, const char* templateString);
static ErrorObject* createBuiltinError(ExecutionState& state, Code code, const char* templateString)
{
return createBuiltinError(state, code, String::emptyString, false, String::emptyString, templateString);
}
static ErrorObject* createError(ExecutionState& state, ErrorObject::Code code, String* errorMessage);
static ErrorObject* createBuiltinError(ExecutionState& state, Code code, String* objectName, bool prototype, String* functionName, const char* templateString);
static void throwBuiltinError(ExecutionState& state, Code code, String* objectName, bool prototype, String* functionName, const char* templateString);
ErrorObject(ExecutionState& state, Object* proto, String* errorMessage);

View file

@ -55,7 +55,7 @@ ModuleNamespaceObject::ModuleNamespaceObject(ExecutionState& state, ModuleEnviro
m_exports = std::move(unambiguousNames);
// http://www.ecma-international.org/ecma-262/6.0/#sec-@@tostringtag
Object::defineOwnProperty(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)), ObjectPropertyDescriptor(Value(state.context()->staticStrings().Module.string()), ObjectPropertyDescriptor::ConfigurablePresent));
Object::defineOwnProperty(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)), ObjectPropertyDescriptor(Value(state.context()->staticStrings().Module.string()), ObjectPropertyDescriptor::NotPresent));
m_isInitialized = true;
}

View file

@ -135,10 +135,16 @@ void SandBox::createStackTraceData(StackTraceDataVector& stackTraceData, Executi
break;
} else if (es->lexicalEnvironment()->record()->isDeclarativeEnvironmentRecord() && es->lexicalEnvironment()->record()->asDeclarativeEnvironmentRecord()->isFunctionEnvironmentRecord()) {
break;
} else if (es->lexicalEnvironment()->record()->isModuleEnvironmentRecord()) {
break;
}
es = es->parent();
}
if (!es) {
break;
}
bool alreadyExists = false;
for (size_t i = 0; i < stackTraceData.size(); i++) {
@ -151,7 +157,13 @@ void SandBox::createStackTraceData(StackTraceDataVector& stackTraceData, Executi
if (!alreadyExists) {
if (!callee && es && es->lexicalEnvironment()) {
// can be null on module outer env
CodeBlock* cb = es->lexicalEnvironment()->record()->asGlobalEnvironmentRecord()->globalCodeBlock();
CodeBlock* cb;
if (es->lexicalEnvironment()->record()->isGlobalEnvironmentRecord()) {
cb = es->lexicalEnvironment()->record()->asGlobalEnvironmentRecord()->globalCodeBlock();
} else {
ASSERT(es->lexicalEnvironment()->record()->isModuleEnvironmentRecord());
cb = es->lexicalEnvironment()->outerEnvironment()->record()->asGlobalEnvironmentRecord()->globalCodeBlock();
}
if (cb) {
ByteCodeBlock* b = cb->asInterpretedCodeBlock()->byteCodeBlock();
ExtendedNodeLOC loc(SIZE_MAX, SIZE_MAX, SIZE_MAX);

View file

@ -512,19 +512,18 @@ public:
return LoadModuleResult(ErrorObjectRef::Code::None, StringRef::createFromUTF8(s.data(), s.length()));
}
auto parseResult = relatedContext->scriptParser()->initializeScript(source.value(), moduleSrc, true);
auto parseResult = relatedContext->scriptParser()->initializeScript(source.value(), StringRef::createFromUTF8(absPath.data(), absPath.size()), true);
if (!parseResult.isSuccessful()) {
return LoadModuleResult(parseResult.parseErrorCode, parseResult.parseErrorMessage);
}
loadedModules.push_back(std::make_tuple(absPath, relatedContext, PersistentRefHolder<ScriptRef>(parseResult.script.get())));
return LoadModuleResult(parseResult.script.get());
}
virtual void didLoadModule(ContextRef* relatedContext, OptionalRef<ScriptRef> referrer, ScriptRef* loadedModule) override
{
std::string path;
if (referrer) {
if (referrer && loadedModule->src()->length() && loadedModule->src()->charAt(0) != '/') {
path = absolutePath(referrer->src()->toStdUTF8String(), loadedModule->src()->toStdUTF8String());
} else {
path = absolutePath(loadedModule->src()->toStdUTF8String());
@ -630,6 +629,8 @@ int main(int argc, char* argv[])
bool runShell = true;
bool seenModule = false;
std::string fileName;
for (int i = 1; i < argc; i++) {
if (strlen(argv[i]) >= 2 && argv[i][0] == '-') { // parse command line option
if (argv[i][1] == '-') { // `--option` case
@ -641,6 +642,10 @@ int main(int argc, char* argv[])
seenModule = true;
continue;
}
if (strstr(argv[i], "--filename-as=") == argv[i]) {
fileName = argv[i] + sizeof("--filename-as=") - 1;
continue;
}
if (strcmp(argv[i], "--start-debug-server") == 0) {
context->initDebugger(nullptr);
continue;
@ -685,10 +690,15 @@ int main(int argc, char* argv[])
argv[i])
.result->asString();
if (!evalScript(context, src, StringRef::createFromUTF8(argv[i], strlen(argv[i])), false, seenModule)) {
if (fileName.length() == 0) {
fileName = argv[i];
}
if (!evalScript(context, src, StringRef::createFromUTF8(fileName.data(), fileName.length()), false, seenModule)) {
return 3;
}
seenModule = false;
fileName.clear();
} else {
runShell = false;
printf("Cannot open file %s\n", argv[i]);

View file

@ -65,6 +65,12 @@ public:
return hasValue();
}
void reset()
{
m_value = T();
m_hasValue = false;
}
bool operator==(const Optional<T>& other) const
{
if (m_hasValue != other.hasValue()) {
@ -148,6 +154,11 @@ public:
return hasValue();
}
void reset()
{
m_value = nullptr;
}
T* operator->()
{
ASSERT(hasValue());

@ -1 +1 @@
Subproject commit 1ebd73cd1e3d4fb0d2d75312a7d1075c7395607c
Subproject commit aad8e2f2279ca4583a05cd46c5a1b1efcadb0837

View file

@ -4851,30 +4851,11 @@
<test id="language/literals/numeric/numeric-separators/numeric-separator-literal-oil-ods-nsl-ods"><reason>TODO</reason></test>
<test id="language/literals/numeric/numeric-separators/numeric-separator-literal-sign-minus-dds-nsl-dd"><reason>TODO</reason></test>
<test id="language/literals/numeric/numeric-separators/numeric-separator-literal-sign-plus-dds-nsl-dd"><reason>TODO</reason></test>
<test id="language/module-code/eval-export-cls-semi"><reason>TODO</reason></test>
<test id="language/module-code/eval-export-dflt-cls-anon"><reason>TODO</reason></test>
<test id="language/module-code/eval-export-dflt-cls-anon-semi"><reason>TODO</reason></test>
<test id="language/module-code/eval-export-dflt-cls-name-meth"><reason>TODO</reason></test>
<test id="language/module-code/eval-export-dflt-cls-named"><reason>TODO</reason></test>
<test id="language/module-code/eval-export-dflt-cls-named-semi"><reason>TODO</reason></test>
<test id="language/module-code/eval-export-dflt-expr-cls-anon"><reason>TODO</reason></test>
<test id="language/module-code/eval-export-dflt-expr-cls-name-meth"><reason>TODO</reason></test>
<test id="language/module-code/eval-export-dflt-expr-cls-named"><reason>TODO</reason></test>
<test id="language/module-code/eval-export-dflt-expr-fn-anon"><reason>TODO</reason></test>
<test id="language/module-code/eval-export-dflt-expr-fn-named"><reason>TODO</reason></test>
<test id="language/module-code/eval-export-dflt-expr-gen-anon"><reason>TODO</reason></test>
<test id="language/module-code/eval-export-dflt-expr-gen-named"><reason>TODO</reason></test>
<test id="language/module-code/eval-export-dflt-expr-in"><reason>TODO</reason></test>
<test id="language/module-code/eval-export-dflt-fun-anon-semi"><reason>TODO</reason></test>
<test id="language/module-code/eval-export-dflt-fun-named-semi"><reason>TODO</reason></test>
<test id="language/module-code/eval-export-dflt-gen-anon-semi"><reason>TODO</reason></test>
<test id="language/module-code/eval-export-dflt-gen-named-semi"><reason>TODO</reason></test>
<test id="language/module-code/eval-export-fun-semi"><reason>TODO</reason></test>
<test id="language/module-code/eval-export-gen-semi"><reason>TODO</reason></test>
<test id="language/module-code/eval-gtbndng-indirect-trlng-comma"><reason>TODO</reason></test>
<test id="language/module-code/eval-gtbndng-indirect-trlng-comma_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/eval-gtbndng-indirect-update"><reason>TODO</reason></test>
<test id="language/module-code/eval-gtbndng-indirect-update-as"><reason>TODO</reason></test>
<test id="language/module-code/eval-gtbndng-indirect-update-as_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/eval-gtbndng-indirect-update-dflt"><reason>TODO</reason></test>
<test id="language/module-code/eval-gtbndng-indirect-update-dflt_FIXTURE"><reason>TODO</reason></test>
@ -4888,18 +4869,11 @@
<test id="language/module-code/eval-rqstd-order-6_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/eval-rqstd-order-8_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/eval-self-once"><reason>TODO</reason></test>
<test id="language/module-code/eval-this"><reason>TODO</reason></test>
<test id="language/module-code/instn-iee-bndng-cls"><reason>TODO</reason></test>
<test id="language/module-code/instn-iee-bndng-cls_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-iee-bndng-const"><reason>TODO</reason></test>
<test id="language/module-code/instn-iee-bndng-const_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-iee-bndng-fun"><reason>TODO</reason></test>
<test id="language/module-code/instn-iee-bndng-fun_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-iee-bndng-gen"><reason>TODO</reason></test>
<test id="language/module-code/instn-iee-bndng-gen_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-iee-bndng-let"><reason>TODO</reason></test>
<test id="language/module-code/instn-iee-bndng-let_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-iee-bndng-var"><reason>TODO</reason></test>
<test id="language/module-code/instn-iee-bndng-var_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-iee-err-ambiguous-1_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-iee-err-ambiguous-2_FIXTURE"><reason>TODO</reason></test>
@ -4907,45 +4881,20 @@
<test id="language/module-code/instn-iee-err-circular_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-iee-err-dflt-thru-star-dflt_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-iee-err-dflt-thru-star-int_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-iee-iee-cycle"><reason>TODO</reason></test>
<test id="language/module-code/instn-iee-iee-cycle-2_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-iee-star-cycle"><reason>TODO</reason></test>
<test id="language/module-code/instn-iee-star-cycle-2_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-iee-star-cycle-indirect-x_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-iee-trlng-comma"><reason>TODO</reason></test>
<test id="language/module-code/instn-iee-trlng-comma_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-local-bndng-export-cls"><reason>TODO</reason></test>
<test id="language/module-code/instn-local-bndng-export-const"><reason>TODO</reason></test>
<test id="language/module-code/instn-local-bndng-export-fun"><reason>TODO</reason></test>
<test id="language/module-code/instn-local-bndng-export-gen"><reason>TODO</reason></test>
<test id="language/module-code/instn-local-bndng-export-let"><reason>TODO</reason></test>
<test id="language/module-code/instn-local-bndng-export-var"><reason>TODO</reason></test>
<test id="language/module-code/instn-local-bndng-for"><reason>TODO</reason></test>
<test id="language/module-code/instn-local-bndng-fun"><reason>TODO</reason></test>
<test id="language/module-code/instn-local-bndng-gen"><reason>TODO</reason></test>
<test id="language/module-code/instn-local-bndng-var"><reason>TODO</reason></test>
<test id="language/module-code/instn-named-bndng-cls"><reason>TODO</reason></test>
<test id="language/module-code/instn-named-bndng-const"><reason>TODO</reason></test>
<test id="language/module-code/instn-named-bndng-dflt-cls"><reason>TODO</reason></test>
<test id="language/module-code/instn-named-bndng-dflt-expr"><reason>TODO</reason></test>
<test id="language/module-code/instn-named-bndng-dflt-fun-anon"><reason>TODO</reason></test>
<test id="language/module-code/instn-named-bndng-dflt-fun-named"><reason>TODO</reason></test>
<test id="language/module-code/instn-named-bndng-dflt-gen-anon"><reason>TODO</reason></test>
<test id="language/module-code/instn-named-bndng-dflt-gen-named"><reason>TODO</reason></test>
<test id="language/module-code/instn-named-bndng-dflt-named"><reason>TODO</reason></test>
<test id="language/module-code/instn-named-bndng-dflt-star"><reason>TODO</reason></test>
<test id="language/module-code/instn-named-bndng-fun"><reason>TODO</reason></test>
<test id="language/module-code/instn-named-bndng-gen"><reason>TODO</reason></test>
<test id="language/module-code/instn-named-bndng-let"><reason>TODO</reason></test>
<test id="language/module-code/instn-named-bndng-trlng-comma"><reason>TODO</reason></test>
<test id="language/module-code/instn-named-bndng-var"><reason>TODO</reason></test>
<test id="language/module-code/instn-named-err-ambiguous-1_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-named-err-ambiguous-2_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-named-err-ambiguous_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-named-err-dflt-thru-star-dflt_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-named-err-dflt-thru-star-int_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-named-id-name"><reason>TODO</reason></test>
<test id="language/module-code/instn-named-iee-cycle"><reason>TODO</reason></test>
<test id="language/module-code/instn-named-iee-cycle-2_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-named-star-cycle"><reason>TODO</reason></test>
<test id="language/module-code/instn-named-star-cycle-2_FIXTURE"><reason>TODO</reason></test>
@ -4961,28 +4910,20 @@
<test id="language/module-code/instn-resolve-order-src-reference_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-resolve-order-src-syntax_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-same-global"><reason>TODO</reason></test>
<test id="language/module-code/instn-star-ambiguous"><reason>TODO</reason></test>
<test id="language/module-code/instn-star-ambiguous-1_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-star-ambiguous-2_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-star-ambiguous_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-star-as-props-dflt-skip"><reason>TODO</reason></test>
<test id="language/module-code/instn-star-binding"><reason>TODO</reason></test>
<test id="language/module-code/instn-star-equality"><reason>TODO</reason></test>
<test id="language/module-code/instn-star-equality-other_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-star-err-not-found-faulty_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-star-id-name"><reason>TODO</reason></test>
<test id="language/module-code/instn-star-iee-cycle"><reason>TODO</reason></test>
<test id="language/module-code/instn-star-iee-cycle-2_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-star-props-circular"><reason>TODO</reason></test>
<test id="language/module-code/instn-star-props-circular-a_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-star-props-circular-b_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-star-props-dflt-keep-indirect"><reason>TODO</reason></test>
<test id="language/module-code/instn-star-props-dflt-keep-indirect-def_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-star-props-dflt-keep-indirect-reexport_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-star-props-dflt-keep-local"><reason>TODO</reason></test>
<test id="language/module-code/instn-star-props-dflt-keep-local-named_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-star-props-dflt-keep-local-prod_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-star-props-dflt-skip"><reason>TODO</reason></test>
<test id="language/module-code/instn-star-props-dflt-skip-named_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-star-props-dflt-skip-prod_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-star-props-dflt-skip-star-as-named-end_FIXTURE"><reason>TODO</reason></test>
@ -4998,9 +4939,6 @@
<test id="language/module-code/instn-star-star-cycle"><reason>TODO</reason></test>
<test id="language/module-code/instn-star-star-cycle-2_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-star-star-cycle-indirect-x_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/instn-uniq-env-rec"><reason>TODO</reason></test>
<test id="language/module-code/namespace/Symbol.iterator"><reason>TODO</reason></test>
<test id="language/module-code/namespace/Symbol.toStringTag"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/define-own-property"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/delete-exported-init"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/delete-exported-uninit"><reason>TODO</reason></test>
@ -5015,35 +4953,11 @@
<test id="language/module-code/namespace/internals/get-nested-namespace-props-nrml-1_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/get-nested-namespace-props-nrml-2_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/get-nested-namespace-props-nrml-3_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/get-own-property-str-found-init"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/get-own-property-str-found-uninit"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/get-own-property-str-not-found"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/get-own-property-sym"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/get-prototype-of"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/get-str-found-init"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/get-str-found-uninit"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/get-str-initialize"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/get-str-not-found"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/get-str-update"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/get-sym-found"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/get-sym-not-found"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/has-property-str-found-init"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/has-property-str-found-uninit"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/has-property-str-not-found"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/has-property-sym-found"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/has-property-sym-not-found"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/is-extensible"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/object-hasOwnProperty-binding-uninit"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/object-keys-binding-uninit"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/object-propertyIsEnumerable-binding-uninit"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/own-property-keys-binding-types"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/own-property-keys-binding-types_FIXTURE"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/own-property-keys-sort"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/prevent-extensions"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/set"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/set-prototype-of"><reason>TODO</reason></test>
<test id="language/module-code/namespace/internals/set-prototype-of-null"><reason>TODO</reason></test>
<test id="language/module-code/parse-export-empty"><reason>TODO</reason></test>
<test id="language/module-code/privatename-valid-no-earlyerr"><reason>TODO</reason></test>
<test id="language/module-code/top-level-await/await-awaits-thenable-not-callable"><reason>TODO</reason></test>
<test id="language/module-code/top-level-await/await-awaits-thenables"><reason>TODO</reason></test>

View file

@ -371,11 +371,26 @@ class TestCase(object):
return (code, out, err)
def RunTestIn(self, command_template, tmp):
tmp.Write(self.GetSource())
source = self.GetSource()
is_module = False
if "flags" in self.testRecord:
is_module = "module" in self.testRecord["flags"]
if is_module:
is_module = "--module "
else:
is_module = ""
tmp.Write(source)
tmp.Close()
command = self.InstantiateTemplate(command_template, {
'path': tmp.name
'path': tmp.name,
'test_case_path': self.full_path,
'is_module': is_module
})
(code, out, err) = self.Execute(command)
return TestResult(code, out, err, self)
@ -575,7 +590,7 @@ class TestSuite(object):
def Run(self, command_template, tests, print_summary, full_summary, logname, junitfile):
if not "{{path}}" in command_template:
command_template += " {{path}}"
command_template += " {{is_module}}--filename-as={{test_case_path}} {{path}}"
cases = self.EnumerateTests(tests)
if len(cases) == 0:
ReportError("No tests to run")