mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-03 22:38:41 +09:00
Issue #1691 - Part 3: Finish implementing import meta. https://bugzilla.mozilla.org/show_bug.cgi?id=1427610
(cherry picked from commit a8625238ac846fb7eb103646ddb8634a5860f067)
This commit is contained in:
parent
a8ab41b4c6
commit
3f4985ce6c
18 changed files with 207 additions and 9 deletions
|
|
@ -812,7 +812,7 @@ HostResolveImportedModule(JSContext* aCx,
|
|||
if (!string.init(aCx, aSpecifier)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!aModule || !aCx) {
|
||||
if (!script || !aCx) {
|
||||
// Our module context was ripped out from under us...
|
||||
return nullptr;
|
||||
}
|
||||
|
|
@ -839,6 +839,34 @@ HostResolveImportedModule(JSContext* aCx,
|
|||
return ms->ModuleRecord();
|
||||
}
|
||||
|
||||
bool
|
||||
HostPopulateImportMeta(JSContext* aCx, JS::Handle<JSObject*> aModule,
|
||||
JS::Handle<JSObject*> aMetaObject)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(aModule);
|
||||
|
||||
JS::Value value = JS::GetModulePrivate(aModule);
|
||||
if (value.isUndefined()) {
|
||||
JS_ReportErrorASCII(aCx, "Module script not found");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto script = static_cast<ModuleScript*>(value.toPrivate());
|
||||
MOZ_DIAGNOSTIC_ASSERT(script->ModuleRecord() == aModule);
|
||||
|
||||
nsAutoCString url;
|
||||
MOZ_DIAGNOSTIC_ASSERT(script->BaseURL());
|
||||
MOZ_ALWAYS_SUCCEEDS(script->BaseURL()->GetAsciiSpec(url));
|
||||
|
||||
JS::Rooted<JSString*> urlString(aCx, JS_NewStringCopyZ(aCx, url.get()));
|
||||
if (!urlString) {
|
||||
JS_ReportOutOfMemory(aCx);
|
||||
return false;
|
||||
}
|
||||
|
||||
return JS_DefineProperty(aCx, aMetaObject, "url", urlString, JSPROP_ENUMERATE);
|
||||
}
|
||||
|
||||
static void
|
||||
EnsureModuleResolveHook(JSContext* aCx)
|
||||
{
|
||||
|
|
@ -848,6 +876,7 @@ EnsureModuleResolveHook(JSContext* aCx)
|
|||
}
|
||||
|
||||
JS::SetModuleResolveHook(rt, HostResolveImportedModule);
|
||||
JS::SetModuleMetadataHook(aCx, HostPopulateImportMeta);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -876,6 +876,25 @@ ModuleObject::evaluationError() const
|
|||
return getReservedSlot(EvaluationErrorSlot);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
ModuleObject::metaObject() const
|
||||
{
|
||||
Value value = getReservedSlot(MetaObjectSlot);
|
||||
if (value.isObject())
|
||||
return &value.toObject();
|
||||
|
||||
MOZ_ASSERT(value.isUndefined());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
ModuleObject::setMetaObject(JSObject* obj)
|
||||
{
|
||||
MOZ_ASSERT(obj);
|
||||
MOZ_ASSERT(!metaObject());
|
||||
setReservedSlot(MetaObjectSlot, ObjectValue(*obj));
|
||||
}
|
||||
|
||||
Scope*
|
||||
ModuleObject::enclosingScope() const
|
||||
{
|
||||
|
|
@ -1479,3 +1498,24 @@ ArrayObject* ModuleBuilder::createArray(const GCVector<T>& vector)
|
|||
|
||||
return array;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
js::GetOrCreateModuleMetaObject(JSContext* cx, HandleObject moduleArg)
|
||||
{
|
||||
HandleModuleObject module = moduleArg.as<ModuleObject>();
|
||||
if (JSObject* obj = module->metaObject())
|
||||
return obj;
|
||||
|
||||
RootedObject metaObject(cx, NewObjectWithGivenProto<PlainObject>(cx, nullptr));
|
||||
if (!metaObject)
|
||||
return nullptr;
|
||||
|
||||
JS::ModuleMetadataHook func = cx->runtime()->moduleMetadataHook;
|
||||
MOZ_ASSERT(func);
|
||||
if (!func(cx, module, metaObject))
|
||||
return nullptr;
|
||||
|
||||
module->setMetaObject(metaObject);
|
||||
|
||||
return metaObject;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -222,6 +222,7 @@ class ModuleObject : public NativeObject
|
|||
StatusSlot,
|
||||
EvaluationErrorSlot,
|
||||
ScriptSourceObjectSlot,
|
||||
MetaObjectSlot,
|
||||
RequestedModulesSlot,
|
||||
ImportEntriesSlot,
|
||||
LocalExportEntriesSlot,
|
||||
|
|
@ -274,6 +275,7 @@ class ModuleObject : public NativeObject
|
|||
bool hadEvaluationError() const;
|
||||
Value evaluationError() const;
|
||||
ScriptSourceObject* scriptSourceObject() const;
|
||||
JSObject* metaObject() const;
|
||||
ArrayObject& requestedModules() const;
|
||||
ArrayObject& importEntries() const;
|
||||
ArrayObject& localExportEntries() const;
|
||||
|
|
@ -286,6 +288,8 @@ class ModuleObject : public NativeObject
|
|||
static bool Instantiate(JSContext* cx, HandleModuleObject self);
|
||||
static bool Evaluate(JSContext* cx, HandleModuleObject self);
|
||||
|
||||
void setMetaObject(JSObject* obj);
|
||||
|
||||
// For BytecodeEmitter.
|
||||
bool noteFunctionDeclaration(ExclusiveContext* cx, HandleAtom name, HandleFunction fun);
|
||||
|
||||
|
|
@ -367,6 +371,9 @@ class MOZ_STACK_CLASS ModuleBuilder
|
|||
ArrayObject* createArray(const GCVector<T>& vector);
|
||||
};
|
||||
|
||||
JSObject*
|
||||
GetOrCreateModuleMetaObject(JSContext* cx, HandleObject module);
|
||||
|
||||
} // namespace js
|
||||
|
||||
template<>
|
||||
|
|
|
|||
|
|
@ -101,8 +101,8 @@
|
|||
#define MODULE_OBJECT_ENVIRONMENT_SLOT 1
|
||||
#define MODULE_OBJECT_STATUS_SLOT 3
|
||||
#define MODULE_OBJECT_EVALUATION_ERROR_SLOT 4
|
||||
#define MODULE_OBJECT_DFS_INDEX_SLOT 15
|
||||
#define MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT 16
|
||||
#define MODULE_OBJECT_DFS_INDEX_SLOT 16
|
||||
#define MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT 17
|
||||
|
||||
#define MODULE_STATUS_UNINSTANTIATED 0
|
||||
#define MODULE_STATUS_INSTANTIATING 1
|
||||
|
|
|
|||
|
|
@ -9083,7 +9083,8 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::
|
|||
break;
|
||||
|
||||
case PNK_IMPORT_META:
|
||||
MOZ_CRASH("NYI");
|
||||
if (!emit1(JSOP_IMPORTMETA))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case PNK_CALL_IMPORT:
|
||||
|
|
|
|||
|
|
@ -4694,3 +4694,17 @@ BaselineCompiler::emit_JSOP_JUMPTARGET()
|
|||
masm.inc64(AbsoluteAddress(counterAddr));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineCompiler::emit_JSOP_IMPORTMETA()
|
||||
{
|
||||
RootedModuleObject module(cx, GetModuleObjectForScript(script));
|
||||
MOZ_ASSERT(module);
|
||||
|
||||
JSObject* metaObject = GetOrCreateModuleMetaObject(cx, module);
|
||||
if (!metaObject)
|
||||
return false;
|
||||
|
||||
frame.push(ObjectValue(*metaObject));
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -240,7 +240,8 @@ namespace jit {
|
|||
_(JSOP_DEBUGCHECKSELFHOSTED) \
|
||||
_(JSOP_JUMPTARGET) \
|
||||
_(JSOP_IS_CONSTRUCTING) \
|
||||
_(JSOP_TRY_DESTRUCTURING_ITERCLOSE)
|
||||
_(JSOP_TRY_DESTRUCTURING_ITERCLOSE) \
|
||||
_(JSOP_IMPORTMETA)
|
||||
|
||||
class BaselineCompiler : public BaselineCompilerSpecific
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2205,6 +2205,9 @@ IonBuilder::inspectOpcode(JSOp op)
|
|||
case JSOP_CHECKOBJCOERCIBLE:
|
||||
return jsop_checkobjcoercible();
|
||||
|
||||
case JSOP_IMPORTMETA:
|
||||
return jsop_importmeta();
|
||||
|
||||
case JSOP_DEBUGCHECKSELFHOSTED:
|
||||
{
|
||||
#ifdef DEBUG
|
||||
|
|
@ -14246,6 +14249,21 @@ IonBuilder::jsop_debugger()
|
|||
return resumeAt(debugger, pc);
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::jsop_importmeta()
|
||||
{
|
||||
ModuleObject* module = GetModuleObjectForScript(script());
|
||||
MOZ_ASSERT(module);
|
||||
|
||||
// The object must have been created already when we compiled for baseline.
|
||||
JSObject* metaObject = module->metaObject();
|
||||
MOZ_ASSERT(metaObject);
|
||||
|
||||
pushConstant(ObjectValue(*metaObject));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
MInstruction*
|
||||
IonBuilder::addConvertElementsToDoubles(MDefinition* elements)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -788,6 +788,7 @@ class IonBuilder
|
|||
MOZ_MUST_USE bool jsop_checkiscallable(uint8_t kind);
|
||||
MOZ_MUST_USE bool jsop_checkobjcoercible();
|
||||
MOZ_MUST_USE bool jsop_pushcallobj();
|
||||
MOZ_MUST_USE bool jsop_importmeta();
|
||||
|
||||
/* Inlining. */
|
||||
|
||||
|
|
|
|||
|
|
@ -4698,6 +4698,20 @@ JS::SetModuleResolveHook(JSRuntime* rt, JS::ModuleResolveHook func)
|
|||
rt->moduleResolveHook = func;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JS::ModuleMetadataHook)
|
||||
JS::GetModuleMetadataHook(JSContext* cx)
|
||||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
return cx->runtime()->moduleMetadataHook;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::SetModuleMetadataHook(JSContext* cx, JS::ModuleMetadataHook func)
|
||||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
cx->runtime()->moduleMetadataHook = func;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf, JS::MutableHandleObject module)
|
||||
|
|
|
|||
|
|
@ -4338,6 +4338,21 @@ GetModuleResolveHook(JSRuntime* rt);
|
|||
extern JS_PUBLIC_API(void)
|
||||
SetModuleResolveHook(JSRuntime* rt, ModuleResolveHook func);
|
||||
|
||||
using ModuleMetadataHook = bool (*)(JSContext*, HandleObject, HandleObject);
|
||||
|
||||
/**
|
||||
* Get the hook for populating the import.meta metadata object.
|
||||
*/
|
||||
extern JS_PUBLIC_API(ModuleMetadataHook)
|
||||
GetModuleMetadataHook(JSContext* cx);
|
||||
|
||||
/**
|
||||
* Set the hook for populating the import.meta metadata object to the given
|
||||
* function.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
SetModuleMetadataHook(JSContext* cx, ModuleMetadataHook func);
|
||||
|
||||
/**
|
||||
* Parse the given source buffer as a module in the scope of the current global
|
||||
* of cx and return a source text module record.
|
||||
|
|
|
|||
|
|
@ -4102,6 +4102,23 @@ ShellGetModulePrivate(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
ShellModuleMetadataHook(JSContext* cx, HandleObject module, HandleObject metaObject)
|
||||
{
|
||||
// For the shell, just use the script's filename as the base URL.
|
||||
RootedScript script(cx, module->as<ModuleObject>().script());
|
||||
const char* filename = script->scriptSource()->filename();
|
||||
MOZ_ASSERT(filename);
|
||||
|
||||
RootedString url(cx, NewStringCopyZ<CanGC>(cx, filename));
|
||||
if (!url)
|
||||
return false;
|
||||
|
||||
if (!JS_DefineProperty(cx, metaObject, "url", url, JSPROP_ENUMERATE))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
GetModuleLoadPath(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
|
|
@ -8038,6 +8055,7 @@ main(int argc, char** argv, char** envp)
|
|||
js::SetPreserveWrapperCallback(cx, DummyPreserveWrapperCallback);
|
||||
|
||||
JS::SetModuleResolveHook(cx->runtime(), CallModuleResolveHook);
|
||||
JS::SetModuleMetadataHook(cx, ShellModuleMetadataHook);
|
||||
|
||||
result = Shell(cx, &op, envp);
|
||||
|
||||
|
|
|
|||
|
|
@ -3065,10 +3065,20 @@ WithEnvironmentObject::scope() const
|
|||
|
||||
ModuleEnvironmentObject*
|
||||
js::GetModuleEnvironmentForScript(JSScript* script)
|
||||
{
|
||||
ModuleObject* module = GetModuleObjectForScript(script);
|
||||
if (!module)
|
||||
return nullptr;
|
||||
|
||||
return module->environment();
|
||||
}
|
||||
|
||||
ModuleObject*
|
||||
js::GetModuleObjectForScript(JSScript* script)
|
||||
{
|
||||
for (ScopeIter si(script); si; si++) {
|
||||
if (si.kind() == ScopeKind::Module)
|
||||
return si.scope()->as<ModuleScope>().module()->environment();
|
||||
return si.scope()->as<ModuleScope>().module();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1075,6 +1075,8 @@ CreateObjectsForEnvironmentChain(JSContext* cx, AutoObjectVector& chain,
|
|||
HandleObject terminatingEnv,
|
||||
MutableHandleObject envObj);
|
||||
|
||||
ModuleObject* GetModuleObjectForScript(JSScript* script);
|
||||
|
||||
ModuleEnvironmentObject* GetModuleEnvironmentForScript(JSScript* script);
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "jsstr.h"
|
||||
|
||||
#include "builtin/Eval.h"
|
||||
#include "builtin/ModuleObject.h"
|
||||
#include "jit/AtomicOperations.h"
|
||||
#include "jit/BaselineJIT.h"
|
||||
#include "jit/Ion.h"
|
||||
|
|
@ -4187,6 +4188,19 @@ CASE(JSOP_NEWTARGET)
|
|||
MOZ_ASSERT(REGS.sp[-1].isObject() || REGS.sp[-1].isUndefined());
|
||||
END_CASE(JSOP_NEWTARGET)
|
||||
|
||||
CASE(JSOP_IMPORTMETA)
|
||||
{
|
||||
ReservedRooted<JSObject*> module(&rootObject0, GetModuleObjectForScript(script));
|
||||
MOZ_ASSERT(module);
|
||||
|
||||
JSObject* metaObject = GetOrCreateModuleMetaObject(cx, module);
|
||||
if (!metaObject)
|
||||
goto error;
|
||||
|
||||
PUSH_OBJECT(*metaObject);
|
||||
}
|
||||
END_CASE(JSOP_IMPORTMETA)
|
||||
|
||||
CASE(JSOP_SUPERFUN)
|
||||
{
|
||||
ReservedRooted<JSObject*> superEnvFunc(&rootObject0, &GetSuperEnvFunction(cx, REGS));
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@
|
|||
* Super
|
||||
* Arguments
|
||||
* Var Scope
|
||||
* Modules
|
||||
* [Operators]
|
||||
* Comparison Operators
|
||||
* Arithmetic Operators
|
||||
|
|
@ -2335,13 +2336,21 @@
|
|||
* Operands: int32_t offset
|
||||
* Stack: cond => cond
|
||||
*/ \
|
||||
macro(JSOP_COALESCE, 232, "coalesce", NULL, 5, 1, 1, JOF_JUMP|JOF_DETECTING)
|
||||
macro(JSOP_COALESCE, 232, "coalesce", NULL, 5, 1, 1, JOF_JUMP|JOF_DETECTING) \
|
||||
/*
|
||||
* Push "import.meta"
|
||||
*
|
||||
* Category: Variables and Scopes
|
||||
* Type: Modules
|
||||
* Operands:
|
||||
* Stack: => import.meta
|
||||
*/ \
|
||||
macro(JSOP_IMPORTMETA, 233, "importmeta", NULL, 1, 0, 1, JOF_BYTE)
|
||||
/*
|
||||
* In certain circumstances it may be useful to "pad out" the opcode space to
|
||||
* a power of two. Use this macro to do so.
|
||||
*/
|
||||
#define FOR_EACH_TRAILING_UNUSED_OPCODE(macro) \
|
||||
macro(233) \
|
||||
macro(234) \
|
||||
macro(235) \
|
||||
macro(236) \
|
||||
|
|
|
|||
|
|
@ -243,7 +243,8 @@ JSRuntime::JSRuntime(JSRuntime* parentRuntime)
|
|||
stackFormat_(parentRuntime ?
|
||||
js::StackFormat::Default :
|
||||
js::StackFormat::SpiderMonkey),
|
||||
moduleResolveHook()
|
||||
moduleResolveHook(),
|
||||
moduleMetadataHook()
|
||||
{
|
||||
setGCStoreBufferPtr(&gc.storeBuffer);
|
||||
|
||||
|
|
|
|||
|
|
@ -1296,6 +1296,10 @@ struct JSRuntime : public JS::shadow::Runtime,
|
|||
|
||||
// The implementation-defined abstract operation HostResolveImportedModule.
|
||||
JS::ModuleResolveHook moduleResolveHook;
|
||||
|
||||
// A hook that implements the abstract operations
|
||||
// HostGetImportMetaProperties and HostFinalizeImportMeta.
|
||||
JS::ModuleMetadataHook moduleMetadataHook;
|
||||
};
|
||||
|
||||
namespace js {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue