mirror of
https://github.com/Samsung/escargot.git
synced 2026-06-22 10:01:50 +00:00
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:
parent
f50838bb5b
commit
9b9f980cfe
15 changed files with 732 additions and 371 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue