зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1614041 - Defer ModuleBuilder GC allocations r=arai
Introduce StencilModuleEntry type to replace {Import,Export}EntryObject during parsing. Also introduce StencilModuleMetadata to hold resulting import/export tables. Differential Revision: https://phabricator.services.mozilla.com/D83206
This commit is contained in:
Родитель
58ab7096a2
Коммит
5211daac48
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "vm/JSObject-inl.h"
|
||||
#include "vm/JSScript-inl.h"
|
||||
#include "vm/NativeObject-inl.h"
|
||||
|
||||
using namespace js;
|
||||
|
||||
|
@ -1217,45 +1218,52 @@ ModuleBuilder::ModuleBuilder(JSContext* cx,
|
|||
requestedModules_(cx, RequestedModuleVector(cx)),
|
||||
importEntries_(cx, ImportEntryMap(cx)),
|
||||
exportEntries_(cx, ExportEntryVector(cx)),
|
||||
exportNames_(cx, AtomSet(cx)),
|
||||
localExportEntries_(cx, ExportEntryVector(cx)),
|
||||
indirectExportEntries_(cx, ExportEntryVector(cx)),
|
||||
starExportEntries_(cx, ExportEntryVector(cx)) {}
|
||||
exportNames_(cx, AtomSet(cx)) {}
|
||||
|
||||
bool ModuleBuilder::buildTables() {
|
||||
for (const auto& e : exportEntries_) {
|
||||
RootedExportEntryObject exp(cx_, e);
|
||||
if (!exp->moduleRequest()) {
|
||||
RootedImportEntryObject importEntry(cx_,
|
||||
importEntryFor(exp->localName()));
|
||||
bool ModuleBuilder::buildTables(frontend::StencilModuleMetadata& metadata) {
|
||||
// https://tc39.es/ecma262/#sec-parsemodule
|
||||
// 15.2.1.17.1 ParseModule, Steps 4-11.
|
||||
|
||||
// Step 4.
|
||||
metadata.requestedModules = std::move(requestedModules_.get());
|
||||
|
||||
// Step 5.
|
||||
if (!metadata.importEntries.reserve(importEntries_.count())) {
|
||||
return false;
|
||||
}
|
||||
for (auto r = importEntries_.all(); !r.empty(); r.popFront()) {
|
||||
frontend::StencilModuleEntry& entry = r.front().value();
|
||||
metadata.importEntries.infallibleAppend(entry);
|
||||
}
|
||||
|
||||
// Steps 6-11.
|
||||
for (const frontend::StencilModuleEntry& exp : exportEntries_) {
|
||||
if (!exp.specifier) {
|
||||
frontend::StencilModuleEntry* importEntry = importEntryFor(exp.localName);
|
||||
if (!importEntry) {
|
||||
if (!localExportEntries_.append(exp)) {
|
||||
if (!metadata.localExportEntries.append(exp)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (importEntry->importName() == cx_->names().star) {
|
||||
if (!localExportEntries_.append(exp)) {
|
||||
if (importEntry->importName == cx_->names().star) {
|
||||
if (!metadata.localExportEntries.append(exp)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
RootedAtom exportName(cx_, exp->exportName());
|
||||
RootedAtom moduleRequest(cx_, importEntry->moduleRequest());
|
||||
RootedAtom importName(cx_, importEntry->importName());
|
||||
RootedExportEntryObject exportEntry(cx_);
|
||||
exportEntry = ExportEntryObject::create(
|
||||
cx_, exportName, moduleRequest, importName, nullptr,
|
||||
exp->lineNumber(), exp->columnNumber());
|
||||
if (!exportEntry || !indirectExportEntries_.append(exportEntry)) {
|
||||
auto entry = frontend::StencilModuleEntry::exportFromEntry(
|
||||
importEntry->specifier, importEntry->importName, exp.exportName,
|
||||
exp.lineno, exp.column);
|
||||
if (!metadata.indirectExportEntries.append(entry)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (exp->importName() == cx_->names().star) {
|
||||
if (!starExportEntries_.append(exp)) {
|
||||
} else if (exp.importName == cx_->names().star) {
|
||||
if (!metadata.starExportEntries.append(exp)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!indirectExportEntries_.append(exp)) {
|
||||
if (!metadata.indirectExportEntries.append(exp)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1264,39 +1272,106 @@ bool ModuleBuilder::buildTables() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ModuleBuilder::initModule(JS::Handle<ModuleObject*> module) {
|
||||
RootedArrayObject requestedModules(cx_,
|
||||
js::CreateArray(cx_, requestedModules_));
|
||||
if (!requestedModules) {
|
||||
enum class ModuleArrayType {
|
||||
ImportEntryObject,
|
||||
ExportEntryObject,
|
||||
RequestedModuleObject,
|
||||
};
|
||||
|
||||
static ArrayObject* ModuleBuilderInitArray(
|
||||
JSContext* cx, ModuleArrayType arrayType,
|
||||
const frontend::StencilModuleMetadata::EntryVector& vector) {
|
||||
RootedArrayObject resultArray(
|
||||
cx, NewDenseFullyAllocatedArray(cx, vector.length()));
|
||||
if (!resultArray) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
resultArray->ensureDenseInitializedLength(cx, 0, vector.length());
|
||||
|
||||
RootedAtom specifier(cx);
|
||||
RootedAtom localName(cx);
|
||||
RootedAtom importName(cx);
|
||||
RootedAtom exportName(cx);
|
||||
RootedObject req(cx);
|
||||
|
||||
for (uint32_t i = 0; i < vector.length(); ++i) {
|
||||
const frontend::StencilModuleEntry& entry = vector[i];
|
||||
specifier = entry.specifier;
|
||||
localName = entry.localName;
|
||||
importName = entry.importName;
|
||||
exportName = entry.exportName;
|
||||
|
||||
switch (arrayType) {
|
||||
case ModuleArrayType::ImportEntryObject:
|
||||
MOZ_ASSERT(localName && importName);
|
||||
req = ImportEntryObject::create(cx, specifier, importName, localName,
|
||||
entry.lineno, entry.column);
|
||||
break;
|
||||
case ModuleArrayType::ExportEntryObject:
|
||||
MOZ_ASSERT(localName || importName || exportName);
|
||||
req = ExportEntryObject::create(cx, exportName, specifier, importName,
|
||||
localName, entry.lineno, entry.column);
|
||||
break;
|
||||
case ModuleArrayType::RequestedModuleObject:
|
||||
req = RequestedModuleObject::create(cx, specifier, entry.lineno,
|
||||
entry.column);
|
||||
// TODO: Make this consistent with other object types.
|
||||
if (req && !FreezeObject(cx, req)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!req) {
|
||||
return nullptr;
|
||||
}
|
||||
resultArray->initDenseElement(i, ObjectValue(*req));
|
||||
}
|
||||
|
||||
return resultArray;
|
||||
}
|
||||
|
||||
// Use StencilModuleMetadata data to fill in ModuleObject
|
||||
bool frontend::StencilModuleMetadata::initModule(
|
||||
JSContext* cx, JS::Handle<ModuleObject*> module) {
|
||||
RootedArrayObject requestedModulesObject(
|
||||
cx, ModuleBuilderInitArray(cx, ModuleArrayType::RequestedModuleObject,
|
||||
requestedModules));
|
||||
if (!requestedModulesObject) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedArrayObject importEntries(cx_, createArrayFromHashMap(importEntries_));
|
||||
if (!importEntries) {
|
||||
RootedArrayObject importEntriesObject(
|
||||
cx, ModuleBuilderInitArray(cx, ModuleArrayType::ImportEntryObject,
|
||||
importEntries));
|
||||
if (!importEntriesObject) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedArrayObject localExportEntries(
|
||||
cx_, js::CreateArray(cx_, localExportEntries_));
|
||||
if (!localExportEntries) {
|
||||
RootedArrayObject localExportEntriesObject(
|
||||
cx, ModuleBuilderInitArray(cx, ModuleArrayType::ExportEntryObject,
|
||||
localExportEntries));
|
||||
if (!localExportEntriesObject) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedArrayObject indirectExportEntries(
|
||||
cx_, js::CreateArray(cx_, indirectExportEntries_));
|
||||
if (!indirectExportEntries) {
|
||||
RootedArrayObject indirectExportEntriesObject(
|
||||
cx, ModuleBuilderInitArray(cx, ModuleArrayType::ExportEntryObject,
|
||||
indirectExportEntries));
|
||||
if (!indirectExportEntriesObject) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedArrayObject starExportEntries(cx_,
|
||||
js::CreateArray(cx_, starExportEntries_));
|
||||
if (!starExportEntries) {
|
||||
RootedArrayObject starExportEntriesObject(
|
||||
cx, ModuleBuilderInitArray(cx, ModuleArrayType::ExportEntryObject,
|
||||
starExportEntries));
|
||||
if (!starExportEntriesObject) {
|
||||
return false;
|
||||
}
|
||||
|
||||
module->initImportExportData(requestedModules, importEntries,
|
||||
localExportEntries, indirectExportEntries,
|
||||
starExportEntries);
|
||||
module->initImportExportData(
|
||||
requestedModulesObject, importEntriesObject, localExportEntriesObject,
|
||||
indirectExportEntriesObject, starExportEntriesObject);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1335,10 +1410,9 @@ bool ModuleBuilder::processImport(frontend::BinaryNode* importNode) {
|
|||
eitherParser_.computeLineAndColumn(importNameNode->pn_pos.begin, &line,
|
||||
&column);
|
||||
|
||||
RootedImportEntryObject importEntry(cx_);
|
||||
importEntry = ImportEntryObject::create(cx_, module, importName, localName,
|
||||
line, column);
|
||||
if (!importEntry || !appendImportEntryObject(importEntry)) {
|
||||
auto entry = frontend::StencilModuleEntry::importEntry(
|
||||
module, localName, importName, line, column);
|
||||
if (!importEntries_.put(localName, entry)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1346,12 +1420,6 @@ bool ModuleBuilder::processImport(frontend::BinaryNode* importNode) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ModuleBuilder::appendImportEntryObject(
|
||||
HandleImportEntryObject importEntry) {
|
||||
MOZ_ASSERT(importEntry->localName());
|
||||
return importEntries_.put(importEntry->localName(), importEntry);
|
||||
}
|
||||
|
||||
bool ModuleBuilder::processExport(frontend::ParseNode* exportNode) {
|
||||
using namespace js::frontend;
|
||||
|
||||
|
@ -1568,14 +1636,15 @@ bool ModuleBuilder::processExportFrom(frontend::BinaryNode* exportNode) {
|
|||
return true;
|
||||
}
|
||||
|
||||
ImportEntryObject* ModuleBuilder::importEntryFor(JSAtom* localName) const {
|
||||
frontend::StencilModuleEntry* ModuleBuilder::importEntryFor(
|
||||
JSAtom* localName) const {
|
||||
MOZ_ASSERT(localName);
|
||||
auto ptr = importEntries_.lookup(localName);
|
||||
if (!ptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ptr->value();
|
||||
return &ptr->value();
|
||||
}
|
||||
|
||||
bool ModuleBuilder::hasExportedName(JSAtom* name) const {
|
||||
|
@ -1592,10 +1661,19 @@ bool ModuleBuilder::appendExportEntry(HandleAtom exportName,
|
|||
eitherParser_.computeLineAndColumn(node->pn_pos.begin, &line, &column);
|
||||
}
|
||||
|
||||
Rooted<ExportEntryObject*> exportEntry(cx_);
|
||||
exportEntry = ExportEntryObject::create(cx_, exportName, nullptr, nullptr,
|
||||
localName, line, column);
|
||||
return exportEntry && appendExportEntryObject(exportEntry);
|
||||
auto entry = frontend::StencilModuleEntry::exportAsEntry(
|
||||
localName, exportName, line, column);
|
||||
if (!exportEntries_.append(entry)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (exportName) {
|
||||
if (!exportNames_.put(exportName)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ModuleBuilder::appendExportFromEntry(HandleAtom exportName,
|
||||
|
@ -1606,19 +1684,12 @@ bool ModuleBuilder::appendExportFromEntry(HandleAtom exportName,
|
|||
uint32_t column;
|
||||
eitherParser_.computeLineAndColumn(node->pn_pos.begin, &line, &column);
|
||||
|
||||
Rooted<ExportEntryObject*> exportEntry(cx_);
|
||||
exportEntry = ExportEntryObject::create(cx_, exportName, moduleRequest,
|
||||
importName, nullptr, line, column);
|
||||
return exportEntry && appendExportEntryObject(exportEntry);
|
||||
}
|
||||
|
||||
bool ModuleBuilder::appendExportEntryObject(
|
||||
HandleExportEntryObject exportEntry) {
|
||||
if (!exportEntries_.append(exportEntry)) {
|
||||
auto entry = frontend::StencilModuleEntry::exportFromEntry(
|
||||
moduleRequest, importName, exportName, line, column);
|
||||
if (!exportEntries_.append(entry)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JSAtom* exportName = exportEntry->exportName();
|
||||
return !exportName || exportNames_.put(exportName);
|
||||
}
|
||||
|
||||
|
@ -1632,15 +1703,13 @@ bool ModuleBuilder::maybeAppendRequestedModule(HandleAtom specifier,
|
|||
uint32_t column;
|
||||
eitherParser_.computeLineAndColumn(node->pn_pos.begin, &line, &column);
|
||||
|
||||
JSContext* cx = cx_;
|
||||
RootedRequestedModuleObject req(
|
||||
cx, RequestedModuleObject::create(cx, specifier, line, column));
|
||||
if (!req) {
|
||||
auto entry =
|
||||
frontend::StencilModuleEntry::moduleRequest(specifier, line, column);
|
||||
if (!requestedModules_.append(entry)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return FreezeObject(cx, req) && requestedModules_.append(req) &&
|
||||
requestedModuleSpecifiers_.put(specifier);
|
||||
return requestedModuleSpecifiers_.put(specifier);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -1660,25 +1729,6 @@ ArrayObject* js::CreateArray(JSContext* cx,
|
|||
return array;
|
||||
}
|
||||
|
||||
template <typename K, typename V>
|
||||
ArrayObject* ModuleBuilder::createArrayFromHashMap(
|
||||
const JS::Rooted<GCHashMap<K, V>>& map) {
|
||||
uint32_t length = map.count();
|
||||
RootedArrayObject array(cx_, NewDenseFullyAllocatedArray(cx_, length));
|
||||
if (!array) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
array->setDenseInitializedLength(length);
|
||||
|
||||
uint32_t i = 0;
|
||||
for (auto r = map.all(); !r.empty(); r.popFront()) {
|
||||
array->initDenseElement(i++, ObjectValue(*r.front().value()));
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
JSObject* js::GetOrCreateModuleMetaObject(JSContext* cx,
|
||||
HandleObject moduleArg) {
|
||||
HandleModuleObject module = moduleArg.as<ModuleObject>();
|
||||
|
|
|
@ -551,7 +551,8 @@ ModuleObject* frontend::ModuleCompiler<Unit>::compile(
|
|||
|
||||
MOZ_ASSERT(compilationInfo.script);
|
||||
|
||||
if (!builder.initModule(module)) {
|
||||
StencilModuleMetadata& moduleMetadata = compilationInfo.moduleMetadata.get();
|
||||
if (!moduleMetadata.initModule(cx, module)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -199,6 +199,9 @@ struct MOZ_RAII CompilationInfo : public JS::CustomAutoRooter {
|
|||
// an index (and CompilationInfo reference).
|
||||
JS::RootedVector<ScopeCreationData> scopeCreationData;
|
||||
|
||||
// Module metadata if this is a module compile.
|
||||
JS::Rooted<StencilModuleMetadata> moduleMetadata;
|
||||
|
||||
// AsmJS modules generated by parsing.
|
||||
HashMap<FunctionIndex, RefPtr<const JS::WasmModule>> asmJS;
|
||||
|
||||
|
@ -238,6 +241,7 @@ struct MOZ_RAII CompilationInfo : public JS::CustomAutoRooter {
|
|||
enclosingScope(cx),
|
||||
topLevel(cx),
|
||||
scopeCreationData(cx),
|
||||
moduleMetadata(cx),
|
||||
asmJS(cx),
|
||||
sourceObject(cx) {}
|
||||
|
||||
|
|
|
@ -1622,13 +1622,17 @@ ModuleNode* Parser<FullParseHandler, Unit>::moduleBody(
|
|||
return null();
|
||||
}
|
||||
|
||||
if (!modulesc->builder.buildTables()) {
|
||||
// Generate the Import/Export tables and store in CompilationInfo.
|
||||
if (!modulesc->builder.buildTables(
|
||||
this->compilationInfo_.moduleMetadata.get())) {
|
||||
return null();
|
||||
}
|
||||
|
||||
// Check exported local bindings exist and mark them as closed over.
|
||||
for (auto entry : modulesc->builder.localExportEntries()) {
|
||||
JSAtom* name = entry->localName();
|
||||
StencilModuleMetadata& moduleMetadata =
|
||||
this->compilationInfo_.moduleMetadata.get();
|
||||
for (auto entry : moduleMetadata.localExportEntries) {
|
||||
JSAtom* name = entry.localName;
|
||||
MOZ_ASSERT(name);
|
||||
|
||||
DeclaredNamePtr p = modulepc.varScope().lookupDeclaredName(name);
|
||||
|
|
|
@ -229,6 +229,29 @@ uint32_t ScopeCreationData::nextFrameSlot() const {
|
|||
MOZ_CRASH("Not an enclosing intra-frame scope");
|
||||
}
|
||||
|
||||
void StencilModuleEntry::trace(JSTracer* trc) {
|
||||
if (specifier) {
|
||||
TraceManuallyBarrieredEdge(trc, &specifier, "module specifier");
|
||||
}
|
||||
if (localName) {
|
||||
TraceManuallyBarrieredEdge(trc, &localName, "module local name");
|
||||
}
|
||||
if (importName) {
|
||||
TraceManuallyBarrieredEdge(trc, &importName, "module import name");
|
||||
}
|
||||
if (exportName) {
|
||||
TraceManuallyBarrieredEdge(trc, &exportName, "module export name");
|
||||
}
|
||||
}
|
||||
|
||||
void StencilModuleMetadata::trace(JSTracer* trc) {
|
||||
requestedModules.trace(trc);
|
||||
importEntries.trace(trc);
|
||||
localExportEntries.trace(trc);
|
||||
indirectExportEntries.trace(trc);
|
||||
starExportEntries.trace(trc);
|
||||
}
|
||||
|
||||
void ScriptStencil::trace(JSTracer* trc) {
|
||||
for (ScriptThingVariant& thing : gcThings) {
|
||||
if (thing.is<ScriptAtom>()) {
|
||||
|
|
|
@ -330,6 +330,108 @@ class ScopeCreationData {
|
|||
|
||||
class EmptyGlobalScopeType {};
|
||||
|
||||
// Common type for ImportEntry / ExportEntry / ModuleRequest within frontend. We
|
||||
// use a shared stencil class type to simplify serialization.
|
||||
//
|
||||
// https://tc39.es/ecma262/#importentry-record
|
||||
// https://tc39.es/ecma262/#exportentry-record
|
||||
//
|
||||
// Note: We subdivide the spec's ExportEntry into ExportAs / ExportFrom forms
|
||||
// for readability.
|
||||
class StencilModuleEntry {
|
||||
public:
|
||||
// | ModuleRequest | ImportEntry | ExportAs | ExportFrom |
|
||||
// |-----------------------------------------------------|
|
||||
// specifier | required | required | nullptr | required |
|
||||
// localName | null | required | required | nullptr |
|
||||
// importName | null | required | nullptr | required |
|
||||
// exportName | null | null | required | optional |
|
||||
JSAtom* specifier = nullptr;
|
||||
JSAtom* localName = nullptr;
|
||||
JSAtom* importName = nullptr;
|
||||
JSAtom* exportName = nullptr;
|
||||
|
||||
// Location used for error messages. If this is for a module request entry
|
||||
// then it is the module specifier string, otherwise the import/export spec
|
||||
// that failed. Exports may not fill these fields if an error cannot be
|
||||
// generated such as `export let x;`.
|
||||
uint32_t lineno = 0;
|
||||
uint32_t column = 0;
|
||||
|
||||
private:
|
||||
StencilModuleEntry(uint32_t lineno, uint32_t column)
|
||||
: lineno(lineno), column(column) {}
|
||||
|
||||
public:
|
||||
static StencilModuleEntry moduleRequest(JSAtom* specifier, uint32_t lineno,
|
||||
uint32_t column) {
|
||||
MOZ_ASSERT(specifier);
|
||||
StencilModuleEntry entry(lineno, column);
|
||||
entry.specifier = specifier;
|
||||
return entry;
|
||||
}
|
||||
|
||||
static StencilModuleEntry importEntry(JSAtom* specifier, JSAtom* localName,
|
||||
JSAtom* importName, uint32_t lineno,
|
||||
uint32_t column) {
|
||||
MOZ_ASSERT(specifier && localName && importName);
|
||||
StencilModuleEntry entry(lineno, column);
|
||||
entry.specifier = specifier;
|
||||
entry.localName = localName;
|
||||
entry.importName = importName;
|
||||
return entry;
|
||||
}
|
||||
|
||||
static StencilModuleEntry exportAsEntry(JSAtom* localName, JSAtom* exportName,
|
||||
uint32_t lineno, uint32_t column) {
|
||||
MOZ_ASSERT(localName && exportName);
|
||||
StencilModuleEntry entry(lineno, column);
|
||||
entry.localName = localName;
|
||||
entry.exportName = exportName;
|
||||
return entry;
|
||||
}
|
||||
|
||||
static StencilModuleEntry exportFromEntry(JSAtom* specifier,
|
||||
JSAtom* importName,
|
||||
JSAtom* exportName, uint32_t lineno,
|
||||
uint32_t column) {
|
||||
// NOTE: The `export * from "mod";` syntax generates nullptr exportName.
|
||||
MOZ_ASSERT(specifier && importName);
|
||||
StencilModuleEntry entry(lineno, column);
|
||||
entry.specifier = specifier;
|
||||
entry.importName = importName;
|
||||
entry.exportName = exportName;
|
||||
return entry;
|
||||
}
|
||||
|
||||
// This traces the JSAtoms. This will be removed once atoms are deferred from
|
||||
// parsing.
|
||||
void trace(JSTracer* trc);
|
||||
};
|
||||
|
||||
// Metadata generated by parsing module scripts, including import/export tables.
|
||||
class StencilModuleMetadata {
|
||||
public:
|
||||
using EntryVector = JS::GCVector<StencilModuleEntry>;
|
||||
|
||||
EntryVector requestedModules;
|
||||
EntryVector importEntries;
|
||||
EntryVector localExportEntries;
|
||||
EntryVector indirectExportEntries;
|
||||
EntryVector starExportEntries;
|
||||
|
||||
explicit StencilModuleMetadata(JSContext* cx)
|
||||
: requestedModules(cx),
|
||||
importEntries(cx),
|
||||
localExportEntries(cx),
|
||||
indirectExportEntries(cx),
|
||||
starExportEntries(cx) {}
|
||||
|
||||
bool initModule(JSContext* cx, JS::Handle<ModuleObject*> module);
|
||||
|
||||
void trace(JSTracer* trc);
|
||||
};
|
||||
|
||||
// The lazy closed-over-binding info is represented by these types that will
|
||||
// convert to a GCCellPtr(nullptr), GCCellPtr(JSAtom*).
|
||||
class NullScriptThing {};
|
||||
|
|
|
@ -11,7 +11,9 @@
|
|||
|
||||
#include "jstypes.h" // JS_PUBLIC_API
|
||||
#include "builtin/ModuleObject.h" // js::{{Im,Ex}portEntry,Requested{Module,}}Object
|
||||
#include "frontend/CompilationInfo.h" // js::frontend::CompilationInfo
|
||||
#include "frontend/EitherParser.h" // js::frontend::EitherParser
|
||||
#include "frontend/Stencil.h" // js::frontend::StencilModuleEntry
|
||||
#include "js/GCHashTable.h" // JS::GCHash{Map,Set}
|
||||
#include "js/GCVector.h" // JS::GCVector
|
||||
#include "js/RootingAPI.h" // JS::{Handle,Rooted}
|
||||
|
@ -47,18 +49,13 @@ class MOZ_STACK_CLASS ModuleBuilder {
|
|||
|
||||
bool hasExportedName(JSAtom* name) const;
|
||||
|
||||
using ExportEntryVector = GCVector<ExportEntryObject*>;
|
||||
const ExportEntryVector& localExportEntries() const {
|
||||
return localExportEntries_;
|
||||
}
|
||||
|
||||
bool buildTables();
|
||||
bool initModule(JS::Handle<ModuleObject*> module);
|
||||
bool buildTables(frontend::StencilModuleMetadata& metadata);
|
||||
|
||||
private:
|
||||
using RequestedModuleVector = JS::GCVector<RequestedModuleObject*>;
|
||||
using RequestedModuleVector = JS::GCVector<frontend::StencilModuleEntry>;
|
||||
using AtomSet = JS::GCHashSet<JSAtom*>;
|
||||
using ImportEntryMap = JS::GCHashMap<JSAtom*, ImportEntryObject*>;
|
||||
using ExportEntryVector = GCVector<frontend::StencilModuleEntry>;
|
||||
using ImportEntryMap = JS::GCHashMap<JSAtom*, frontend::StencilModuleEntry>;
|
||||
using RootedExportEntryVector = JS::Rooted<ExportEntryVector>;
|
||||
using RootedRequestedModuleVector = JS::Rooted<RequestedModuleVector>;
|
||||
using RootedAtomSet = JS::Rooted<AtomSet>;
|
||||
|
@ -66,23 +63,19 @@ class MOZ_STACK_CLASS ModuleBuilder {
|
|||
|
||||
JSContext* cx_;
|
||||
frontend::EitherParser eitherParser_;
|
||||
|
||||
RootedAtomSet requestedModuleSpecifiers_;
|
||||
RootedRequestedModuleVector requestedModules_;
|
||||
RootedImportEntryMap importEntries_;
|
||||
RootedExportEntryVector exportEntries_;
|
||||
RootedAtomSet exportNames_;
|
||||
RootedExportEntryVector localExportEntries_;
|
||||
RootedExportEntryVector indirectExportEntries_;
|
||||
RootedExportEntryVector starExportEntries_;
|
||||
|
||||
ImportEntryObject* importEntryFor(JSAtom* localName) const;
|
||||
frontend::StencilModuleEntry* importEntryFor(JSAtom* localName) const;
|
||||
|
||||
bool processExportBinding(frontend::ParseNode* pn);
|
||||
bool processExportArrayBinding(frontend::ListNode* array);
|
||||
bool processExportObjectBinding(frontend::ListNode* obj);
|
||||
|
||||
bool appendImportEntryObject(JS::Handle<ImportEntryObject*> importEntry);
|
||||
|
||||
bool appendExportEntry(JS::Handle<JSAtom*> exportName,
|
||||
JS::Handle<JSAtom*> localName,
|
||||
frontend::ParseNode* node = nullptr);
|
||||
|
@ -92,14 +85,8 @@ class MOZ_STACK_CLASS ModuleBuilder {
|
|||
JS::Handle<JSAtom*> importName,
|
||||
frontend::ParseNode* node);
|
||||
|
||||
bool appendExportEntryObject(JS::Handle<ExportEntryObject*> exportEntry);
|
||||
|
||||
bool maybeAppendRequestedModule(JS::Handle<JSAtom*> specifier,
|
||||
frontend::ParseNode* node);
|
||||
|
||||
template <typename K, typename V>
|
||||
ArrayObject* createArrayFromHashMap(
|
||||
const JS::Rooted<JS::GCHashMap<K, V>>& map);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
|
Загрузка…
Ссылка в новой задаче