Skip to content

Commit c0ae3d3

Browse files
committed
[MERGE #6156 @boingoing] Implement import.meta
Merge pull request #6156 from boingoing:importmeta Implement import.meta The import.meta proposal has reached stage 3. See details: https://github.com/tc39/proposal-import-meta This special name is a meta-property which binds to an object in module code. The import.meta object is unique per-module. Each module's import.meta object is filled-out with properties provided by the host. The object itself is lazily-created and an empty object with a null prototype by default. When loading import.meta for a module, we ask the host to provide a set of properties for the object and allow the host to do other setup of the import.meta object it might need to do. There are two host API provided for in the proposal: HostGetImportMetaProperties and HostFinalizeImportMeta. I've plumbed these callbacks in so hosts can implement them.
2 parents 2751a86 + f0e3325 commit c0ae3d3

39 files changed

+913
-536
lines changed

bin/NativeTests/JsRTApiTest.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2191,7 +2191,7 @@ namespace JsRTApiTest
21912191
return JsNoError;
21922192
}
21932193

2194-
static JsErrorCode CALLBACK Succes_NMRC(_In_opt_ JsModuleRecord referencingModule, _In_opt_ JsValueRef exceptionVar)
2194+
static JsErrorCode CALLBACK Success_NMRC(_In_opt_ JsModuleRecord referencingModule, _In_opt_ JsValueRef exceptionVar)
21952195
{
21962196
if (successTest.mainModule == referencingModule)
21972197
{
@@ -2201,6 +2201,11 @@ namespace JsRTApiTest
22012201
return JsNoError;
22022202
}
22032203

2204+
static JsErrorCode CALLBACK Success_IIMC(_In_opt_ JsModuleRecord referencingModule, _In_opt_ JsValueRef importMetaVar)
2205+
{
2206+
return JsNoError;
2207+
}
2208+
22042209
void ModuleSuccessTest(JsRuntimeAttributes attributes, JsRuntimeHandle runtime)
22052210
{
22062211
JsModuleRecord requestModule = JS_INVALID_REFERENCE;
@@ -2211,7 +2216,8 @@ namespace JsRTApiTest
22112216
successTest.mainModule = requestModule;
22122217
REQUIRE(JsSetModuleHostInfo(requestModule, JsModuleHostInfo_FetchImportedModuleCallback, Success_FIMC) == JsNoError);
22132218
REQUIRE(JsSetModuleHostInfo(requestModule, JsModuleHostInfo_FetchImportedModuleFromScriptCallback, Success_FIMC) == JsNoError);
2214-
REQUIRE(JsSetModuleHostInfo(requestModule, JsModuleHostInfo_NotifyModuleReadyCallback, Succes_NMRC) == JsNoError);
2219+
REQUIRE(JsSetModuleHostInfo(requestModule, JsModuleHostInfo_NotifyModuleReadyCallback, Success_NMRC) == JsNoError);
2220+
REQUIRE(JsSetModuleHostInfo(requestModule, JsModuleHostInfo_InitializeImportMetaCallback, Success_IIMC) == JsNoError);
22152221

22162222
JsValueRef errorObject = JS_INVALID_REFERENCE;
22172223
const char* fileContent = "import {x} from 'foo.js'";
@@ -2279,7 +2285,7 @@ namespace JsRTApiTest
22792285
REQUIRE(JsInitializeModuleRecord(nullptr, specifier, &requestModule) == JsNoError);
22802286

22812287
successTest.mainModule = requestModule;
2282-
REQUIRE(JsSetModuleHostInfo(requestModule, JsModuleHostInfo_NotifyModuleReadyCallback, Succes_NMRC) == JsNoError);
2288+
REQUIRE(JsSetModuleHostInfo(requestModule, JsModuleHostInfo_NotifyModuleReadyCallback, Success_NMRC) == JsNoError);
22832289

22842290
// Parsing
22852291
JsValueRef errorObject1 = JS_INVALID_REFERENCE;
@@ -2327,7 +2333,7 @@ namespace JsRTApiTest
23272333
successTest.mainModule = requestModule;
23282334
REQUIRE(JsSetModuleHostInfo(requestModule, JsModuleHostInfo_FetchImportedModuleCallback, Success_FIMC1) == JsNoError);
23292335
REQUIRE(JsSetModuleHostInfo(requestModule, JsModuleHostInfo_FetchImportedModuleFromScriptCallback, Success_FIMC1) == JsNoError);
2330-
REQUIRE(JsSetModuleHostInfo(requestModule, JsModuleHostInfo_NotifyModuleReadyCallback, Succes_NMRC) == JsNoError);
2336+
REQUIRE(JsSetModuleHostInfo(requestModule, JsModuleHostInfo_NotifyModuleReadyCallback, Success_NMRC) == JsNoError);
23312337

23322338
JsValueRef errorObject = JS_INVALID_REFERENCE;
23332339
const char* fileContent = "import {x} from 'foo.js'";

bin/ch/WScriptJsrt.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -612,9 +612,14 @@ JsErrorCode WScriptJsrt::InitializeModuleInfo(JsValueRef specifier, JsModuleReco
612612
{
613613
errorCode = ChakraRTInterface::JsSetModuleHostInfo(moduleRecord, JsModuleHostInfo_NotifyModuleReadyCallback, (void*)WScriptJsrt::NotifyModuleReadyCallback);
614614

615-
if (errorCode == JsNoError && moduleRecord != nullptr)
615+
if (errorCode == JsNoError)
616616
{
617-
errorCode = ChakraRTInterface::JsSetModuleHostInfo(moduleRecord, JsModuleHostInfo_HostDefined, specifier);
617+
errorCode = ChakraRTInterface::JsSetModuleHostInfo(moduleRecord, JsModuleHostInfo_InitializeImportMetaCallback, (void*)WScriptJsrt::InitializeImportMetaCallback);
618+
619+
if (errorCode == JsNoError && moduleRecord != nullptr)
620+
{
621+
errorCode = ChakraRTInterface::JsSetModuleHostInfo(moduleRecord, JsModuleHostInfo_HostDefined, specifier);
622+
}
618623
}
619624
}
620625
}
@@ -2159,6 +2164,23 @@ JsErrorCode WScriptJsrt::NotifyModuleReadyCallback(_In_opt_ JsModuleRecord refer
21592164
return JsNoError;
21602165
}
21612166

2167+
JsErrorCode __stdcall WScriptJsrt::InitializeImportMetaCallback(_In_opt_ JsModuleRecord referencingModule, _In_opt_ JsValueRef importMetaVar)
2168+
{
2169+
if (importMetaVar != nullptr)
2170+
{
2171+
JsValueRef specifier = JS_INVALID_REFERENCE;
2172+
ChakraRTInterface::JsGetModuleHostInfo(referencingModule, JsModuleHostInfo_HostDefined, &specifier);
2173+
2174+
JsPropertyIdRef urlPropId;
2175+
if (JsNoError == CreatePropertyIdFromString("url", &urlPropId))
2176+
{
2177+
ChakraRTInterface::JsSetProperty(importMetaVar, urlPropId, specifier, false);
2178+
}
2179+
}
2180+
2181+
return JsNoError;
2182+
}
2183+
21622184
void WScriptJsrt::PromiseContinuationCallback(JsValueRef task, void *callbackState)
21632185
{
21642186
Assert(task != JS_INVALID_REFERENCE);

bin/ch/WScriptJsrt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ class WScriptJsrt
6565
static JsErrorCode FetchImportedModule(_In_ JsModuleRecord referencingModule, _In_ JsValueRef specifier, _Outptr_result_maybenull_ JsModuleRecord* dependentModuleRecord);
6666
static JsErrorCode FetchImportedModuleFromScript(_In_ DWORD_PTR dwReferencingSourceContext, _In_ JsValueRef specifier, _Outptr_result_maybenull_ JsModuleRecord* dependentModuleRecord);
6767
static JsErrorCode NotifyModuleReadyCallback(_In_opt_ JsModuleRecord referencingModule, _In_opt_ JsValueRef exceptionVar);
68+
static JsErrorCode CALLBACK InitializeImportMetaCallback(_In_opt_ JsModuleRecord referencingModule, _In_opt_ JsValueRef importMetaVar);
6869
static JsErrorCode InitializeModuleCallbacks();
6970
static void CALLBACK PromiseContinuationCallback(JsValueRef task, void *callbackState);
7071
static void CALLBACK PromiseRejectionTrackerCallback(JsValueRef promise, JsValueRef reason, bool handled, void *callbackState);

lib/Backend/JnHelperMethodList.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,7 @@ HELPERCALLCHK(LdHomeObjProto, Js::JavascriptOperators::OP_LdHomeObjPro
532532
HELPERCALLCHK(LdFuncObjProto, Js::JavascriptOperators::OP_LdFuncObjProto, AttrCanNotBeReentrant)
533533

534534
HELPERCALLCHK(ImportCall, Js::JavascriptOperators::OP_ImportCall, 0)
535+
HELPERCALLCHK(LdImportMeta, Js::JavascriptOperators::OP_LdImportMeta, 0)
535536
HELPERCALLCHK(NewAsyncFromSyncIterator, Js::JavascriptOperators::OP_NewAsyncFromSyncIterator, AttrCanNotBeReentrant)
536537

537538
HELPERCALLCHK(AsyncYieldIsReturn, Js::JavascriptOperators::OP_AsyncYieldIsReturn, AttrCanNotBeReentrant)

lib/Backend/Lower.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2531,6 +2531,16 @@ Lowerer::LowerRange(IR::Instr *instrStart, IR::Instr *instrEnd, bool defaultDoFa
25312531
this->GenerateCheckForCallFlagNew(instr);
25322532
break;
25332533

2534+
case Js::OpCode::LdImportMeta:
2535+
{
2536+
IR::Opnd *src1Opnd = instr->UnlinkSrc1();
2537+
2538+
LoadScriptContext(instr);
2539+
m_lowererMD.LoadHelperArgument(instr, src1Opnd);
2540+
m_lowererMD.ChangeToHelperCall(instr, IR::HelperLdImportMeta);
2541+
break;
2542+
}
2543+
25342544
case Js::OpCode::StFuncExpr:
25352545
// object.propid = src
25362546
LowerStFld(instr, IR::HelperOp_StFunctionExpression, IR::HelperOp_StFunctionExpression, false);

lib/Common/ConfigFlagsList.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,7 @@ PHASE(All)
702702
#define DEFAULT_CONFIG_ES7ValuesEntries (true)
703703
#define DEFAULT_CONFIG_ESObjectGetOwnPropertyDescriptors (true)
704704
#define DEFAULT_CONFIG_ESDynamicImport (false)
705+
#define DEFAULT_CONFIG_ESImportMeta (true)
705706
#define DEFAULT_CONFIG_ESExportNsAs (true)
706707
#define DEFAULT_CONFIG_ES2018AsyncIteration (false)
707708

@@ -1228,6 +1229,9 @@ FLAGR(Boolean, ESHashbang, "Enable Hashbang syntax", DEFAULT_CONFIG_ESHashbang)
12281229
// ES Symbol.prototype.description flag
12291230
FLAGR(Boolean, ESSymbolDescription, "Enable Symbol.prototype.description", DEFAULT_CONFIG_ESSymbolDescription)
12301231

1232+
// ES import.meta keyword meta-property
1233+
FLAGR(Boolean, ESImportMeta, "Enable import.meta keyword", DEFAULT_CONFIG_ESImportMeta)
1234+
12311235
//ES globalThis flag
12321236
FLAGR(Boolean, ESGlobalThis, "Enable globalThis", DEFAULT_CONFIG_ESGlobalThis)
12331237

lib/Jsrt/ChakraCore.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,11 @@ typedef enum JsModuleHostInfoKind
111111
/// <summary>
112112
/// URL for use in error stack traces and debugging.
113113
/// </summary>
114-
JsModuleHostInfo_Url = 0x6
114+
JsModuleHostInfo_Url = 0x6,
115+
/// <summary>
116+
/// Callback to allow host to initialize import.meta object properties.
117+
/// </summary>
118+
JsModuleHostInfo_InitializeImportMetaCallback = 0x7
115119
} JsModuleHostInfoKind;
116120

117121
/// <summary>
@@ -187,6 +191,22 @@ typedef JsErrorCode(CHAKRA_CALLBACK * FetchImportedModuleFromScriptCallBack)(_In
187191
/// </returns>
188192
typedef JsErrorCode(CHAKRA_CALLBACK * NotifyModuleReadyCallback)(_In_opt_ JsModuleRecord referencingModule, _In_opt_ JsValueRef exceptionVar);
189193

194+
/// <summary>
195+
/// User implemented callback to fill in module properties for the import.meta object.
196+
/// </summary>
197+
/// <remarks>
198+
/// This callback allows the host to fill module details for the referencing module in the import.meta object
199+
/// loaded by script.
200+
/// The callback is invoked on the current runtime execution thread, therefore execution is blocked until the
201+
/// callback completes.
202+
/// </remarks>
203+
/// <param name="referencingModule">The referencing module that is loading an import.meta object.</param>
204+
/// <param name="importMetaVar">The object which will be returned to script for the referencing module.</param>
205+
/// <returns>
206+
/// Returns a JsErrorCode - note, the return value is ignored.
207+
/// </returns>
208+
typedef JsErrorCode(CHAKRA_CALLBACK * InitializeImportMetaCallback)(_In_opt_ JsModuleRecord referencingModule, _In_opt_ JsValueRef importMetaVar);
209+
190210
/// <summary>
191211
/// A structure containing information about a native function callback.
192212
/// </summary>

lib/Jsrt/Core/JsrtContextCore.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,23 @@ HRESULT ChakraCoreHostScriptContext::NotifyHostAboutModuleReady(Js::ModuleRecord
159159
return E_INVALIDARG;
160160
}
161161

162+
HRESULT ChakraCoreHostScriptContext::InitializeImportMeta(Js::ModuleRecordBase* referencingModule, Js::Var importMetaObject)
163+
{
164+
if (initializeImportMetaCallback == nullptr)
165+
{
166+
return E_INVALIDARG;
167+
}
168+
{
169+
AUTO_NO_EXCEPTION_REGION;
170+
JsErrorCode errorCode = initializeImportMetaCallback(referencingModule, importMetaObject);
171+
if (errorCode == JsNoError)
172+
{
173+
return NOERROR;
174+
}
175+
}
176+
return E_INVALIDARG;
177+
}
178+
162179
ChakraCoreStreamWriter::~ChakraCoreStreamWriter()
163180
{
164181
HeapDelete(m_serializerCore);

lib/Jsrt/Core/JsrtContextCore.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,10 @@ class ChakraCoreHostScriptContext sealed : public HostScriptContext
101101
public:
102102
ChakraCoreHostScriptContext(Js::ScriptContext* scriptContext)
103103
: HostScriptContext(scriptContext),
104+
fetchImportedModuleCallback(nullptr),
105+
fetchImportedModuleFromScriptCallback(nullptr),
104106
notifyModuleReadyCallback(nullptr),
105-
fetchImportedModuleCallback(nullptr)
107+
initializeImportMetaCallback(nullptr)
106108
{
107109
}
108110
~ChakraCoreHostScriptContext()
@@ -250,6 +252,8 @@ class ChakraCoreHostScriptContext sealed : public HostScriptContext
250252

251253
HRESULT NotifyHostAboutModuleReady(Js::ModuleRecordBase* referencingModule, Js::Var exceptionVar) override;
252254

255+
HRESULT InitializeImportMeta(Js::ModuleRecordBase* referencingModule, Js::Var importMetaObject) override;
256+
253257
void SetNotifyModuleReadyCallback(NotifyModuleReadyCallback notifyCallback) { this->notifyModuleReadyCallback = notifyCallback; }
254258
NotifyModuleReadyCallback GetNotifyModuleReadyCallback() const { return this->notifyModuleReadyCallback; }
255259

@@ -259,6 +263,9 @@ class ChakraCoreHostScriptContext sealed : public HostScriptContext
259263
void SetFetchImportedModuleFromScriptCallback(FetchImportedModuleFromScriptCallBack fetchCallback) { this->fetchImportedModuleFromScriptCallback = fetchCallback; }
260264
FetchImportedModuleFromScriptCallBack GetFetchImportedModuleFromScriptCallback() const { return this->fetchImportedModuleFromScriptCallback; }
261265

266+
void SetInitializeImportMetaCallback(InitializeImportMetaCallback finalizeCallback) { this->initializeImportMetaCallback = finalizeCallback; }
267+
InitializeImportMetaCallback GetInitializeImportMetaCallback() const { return this->initializeImportMetaCallback; }
268+
262269
#if DBG_DUMP || defined(PROFILE_EXEC) || defined(PROFILE_MEM)
263270
void EnsureParentInfo(Js::ScriptContext* scriptContext = NULL) override
264271
{
@@ -273,7 +280,5 @@ class ChakraCoreHostScriptContext sealed : public HostScriptContext
273280
FetchImportedModuleCallBack fetchImportedModuleCallback;
274281
FetchImportedModuleFromScriptCallBack fetchImportedModuleFromScriptCallback;
275282
NotifyModuleReadyCallback notifyModuleReadyCallback;
283+
InitializeImportMetaCallback initializeImportMetaCallback;
276284
};
277-
278-
279-

lib/Jsrt/Core/JsrtCore.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,8 @@ JsSetModuleHostInfo(
158158
{
159159
if (moduleHostInfo != JsModuleHostInfo_FetchImportedModuleCallback &&
160160
moduleHostInfo != JsModuleHostInfo_FetchImportedModuleFromScriptCallback &&
161-
moduleHostInfo != JsModuleHostInfo_NotifyModuleReadyCallback)
161+
moduleHostInfo != JsModuleHostInfo_NotifyModuleReadyCallback &&
162+
moduleHostInfo != JsModuleHostInfo_InitializeImportMetaCallback)
162163
{
163164
return JsErrorInvalidArgument;
164165
}
@@ -191,6 +192,9 @@ JsSetModuleHostInfo(
191192
case JsModuleHostInfo_NotifyModuleReadyCallback:
192193
currentContext->GetHostScriptContext()->SetNotifyModuleReadyCallback(reinterpret_cast<NotifyModuleReadyCallback>(hostInfo));
193194
break;
195+
case JsModuleHostInfo_InitializeImportMetaCallback:
196+
currentContext->GetHostScriptContext()->SetInitializeImportMetaCallback(reinterpret_cast<InitializeImportMetaCallback>(hostInfo));
197+
break;
194198
case JsModuleHostInfo_Url:
195199
moduleRecord->SetModuleUrl(hostInfo);
196200
break;
@@ -238,6 +242,9 @@ JsGetModuleHostInfo(
238242
case JsModuleHostInfo_NotifyModuleReadyCallback:
239243
*hostInfo = reinterpret_cast<void*>(currentContext->GetHostScriptContext()->GetNotifyModuleReadyCallback());
240244
break;
245+
case JsModuleHostInfo_InitializeImportMetaCallback:
246+
*hostInfo = reinterpret_cast<void*>(currentContext->GetHostScriptContext()->GetInitializeImportMetaCallback());
247+
break;
241248
case JsModuleHostInfo_Url:
242249
*hostInfo = reinterpret_cast<void*>(moduleRecord->GetModuleUrl());
243250
break;

0 commit comments

Comments
 (0)