Skip to content

Commit 4d6cf88

Browse files
committed
[MERGE #5803 @rhuanjl] Various module import fixes
Merge pull request #5803 from rhuanjl:moduleFixes This PR fixes a collection of module related issues - some of these are very small so I thought better to combine them into one PR. I hope this isn't too much at once. 1. Restore the use of relative paths for imports within modules in ch - this was implemented a long time ago and then broken - the functionality was mostly still there just broken in a few places - originally this was issue 3257, it also has a newer issue I opened 5237. As well as restoring the functionality I restored the test case from 3257 which was no longer testing what it had been designed for after a previous edit. 2. Don't print messages about failing to load modules or syntax errors in modules when processing dynamic imports - this was purely a ch issue but was problematic for several test262 cases per issue 5796. 3. Reject the promise from import() if a child module of the dynamically imported module throws a runtime error - there was a bug where this promise was never being resolved - this is also part of 5796. 4. `new import(anything)` should be a syntax error - 5797 5. import() should return a different promise each time even when using the same specifier - fix this by using JavascriptPromise::CreatePassThroughPromise 5795 cc @rwaldron @boingoing fix #5796 fix #5795 fix #5797 fix #5237 re-fix #3257
2 parents 2a37c46 + 7eac3e3 commit 4d6cf88

File tree

15 files changed

+254
-90
lines changed

15 files changed

+254
-90
lines changed

bin/ch/Helpers.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ uint ConcatPath(LPCSTR filenameLeft, uint posPathSep, LPCSTR filenameRight, char
155155
return totalLength;
156156
}
157157

158-
HRESULT Helpers::LoadScriptFromFile(LPCSTR filenameToLoad, LPCSTR& contents, UINT* lengthBytesOut /*= nullptr*/)
158+
HRESULT Helpers::LoadScriptFromFile(LPCSTR filenameToLoad, LPCSTR& contents, UINT* lengthBytesOut /*= nullptr*/, std::string* fullPath /*= nullptr*/, bool shouldMute /*=false */)
159159
{
160160
static char sHostApplicationPathBuffer[MAX_URI_LENGTH];
161161
static uint sHostApplicationPathBufferLength = (uint) -1;
@@ -169,7 +169,7 @@ HRESULT Helpers::LoadScriptFromFile(LPCSTR filenameToLoad, LPCSTR& contents, UIN
169169
FILE * file = NULL;
170170
size_t bufferLength = 0;
171171

172-
LPCSTR filename = filenameToLoad;
172+
LPCSTR filename = fullPath == nullptr ? filenameToLoad : LPCSTR(fullPath->c_str());
173173
if (sHostApplicationPathBufferLength == (uint)-1)
174174
{
175175
// consider incoming filename as the host app and base its' path for others
@@ -188,7 +188,7 @@ HRESULT Helpers::LoadScriptFromFile(LPCSTR filenameToLoad, LPCSTR& contents, UIN
188188
}
189189
sHostApplicationPathBuffer[sHostApplicationPathBufferLength] = char(0);
190190
}
191-
else if (filename[0] != '/' && filename[0] != '\\') // make sure it's not a full path
191+
else if (filename[0] != '/' && filename[0] != '\\' && fullPath == nullptr) // make sure it's not a full path
192192
{
193193
// concat host path and filename
194194
uint len = ConcatPath(sHostApplicationPathBuffer, sHostApplicationPathBufferLength,
@@ -216,7 +216,7 @@ HRESULT Helpers::LoadScriptFromFile(LPCSTR filenameToLoad, LPCSTR& contents, UIN
216216
// etc.
217217
if (fopen_s(&file, filename, "rb") != 0)
218218
{
219-
if (!HostConfigFlags::flags.MuteHostErrorMsgIsEnabled)
219+
if (!HostConfigFlags::flags.MuteHostErrorMsgIsEnabled && !shouldMute)
220220
{
221221
#ifdef _WIN32
222222
DWORD lastError = GetLastError();

bin/ch/Helpers.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
class Helpers
88
{
99
public :
10-
static HRESULT LoadScriptFromFile(LPCSTR filename, LPCSTR& contents, UINT* lengthBytesOut = nullptr);
10+
static HRESULT LoadScriptFromFile(LPCSTR filename, LPCSTR& contents, UINT* lengthBytesOut = nullptr, std::string* fullPath = nullptr, bool shouldMute = false);
1111
static LPCWSTR JsErrorCodeToString(JsErrorCode jsErrorCode);
1212
static void LogError(__in __nullterminated const char16 *msg, ...);
1313
static HRESULT LoadBinaryFile(LPCSTR filename, LPCSTR& contents, UINT& lengthBytes, bool printFileOpenError = true);

bin/ch/WScriptJsrt.cpp

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
MessageQueue* WScriptJsrt::messageQueue = nullptr;
4848
std::map<std::string, JsModuleRecord> WScriptJsrt::moduleRecordMap;
4949
std::map<JsModuleRecord, std::string> WScriptJsrt::moduleDirMap;
50+
std::map<JsModuleRecord, ModuleState> WScriptJsrt::moduleErrMap;
5051
std::map<DWORD_PTR, std::string> WScriptJsrt::scriptDirMap;
5152
DWORD_PTR WScriptJsrt::sourceContext = 0;
5253

@@ -223,7 +224,6 @@ JsValueRef WScriptJsrt::LoadScriptFileHelper(JsValueRef callee, JsValueRef *argu
223224
hr = Helpers::LoadScriptFromFile(*fileName, fileContent);
224225
if (FAILED(hr))
225226
{
226-
// check if have it registered
227227
fprintf(stderr, "Couldn't load file '%s'\n", fileName.GetString());
228228
IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
229229
return returnValue;
@@ -482,6 +482,7 @@ JsErrorCode WScriptJsrt::LoadModuleFromString(LPCSTR fileName, LPCSTR fileConten
482482
}
483483

484484
moduleRecordMap[std::string(moduleRecordKey)] = requestModule;
485+
moduleErrMap[requestModule] = RootModule;
485486
}
486487
}
487488
else
@@ -504,9 +505,10 @@ JsErrorCode WScriptJsrt::LoadModuleFromString(LPCSTR fileName, LPCSTR fileConten
504505

505506
errorCode = ChakraRTInterface::JsParseModuleSource(requestModule, dwSourceCookie, (LPBYTE)fileContent,
506507
fileContentLength, JsParseModuleSourceFlags_DataIsUTF8, &errorObject);
507-
if ((errorCode != JsNoError) && errorObject != JS_INVALID_REFERENCE && fileContent != nullptr && !HostConfigFlags::flags.IgnoreScriptErrorCode)
508+
if ((errorCode != JsNoError) && errorObject != JS_INVALID_REFERENCE && fileContent != nullptr && !HostConfigFlags::flags.IgnoreScriptErrorCode && moduleErrMap[requestModule] == RootModule)
508509
{
509510
ChakraRTInterface::JsSetException(errorObject);
511+
moduleErrMap[requestModule] = ErroredModule;
510512
return errorCode;
511513
}
512514
return JsNoError;
@@ -1145,6 +1147,7 @@ bool WScriptJsrt::Uninitialize()
11451147
// to avoid worrying about global destructor order.
11461148
moduleRecordMap.clear();
11471149
moduleDirMap.clear();
1150+
moduleErrMap.clear();
11481151
scriptDirMap.clear();
11491152

11501153
auto& threadData = GetRuntimeThreadLocalData().threadData;
@@ -1232,7 +1235,6 @@ JsValueRef __stdcall WScriptJsrt::LoadTextFileCallback(JsValueRef callee, bool i
12321235

12331236
if (FAILED(hr))
12341237
{
1235-
// check if have it registered
12361238
fprintf(stderr, "Couldn't load file '%s'\n", fileName.GetString());
12371239
IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
12381240
return returnValue;
@@ -1396,7 +1398,6 @@ JsValueRef __stdcall WScriptJsrt::LoadBinaryFileCallback(JsValueRef callee,
13961398

13971399
if (FAILED(hr))
13981400
{
1399-
// check if have it registered
14001401
fprintf(stderr, "Couldn't load file '%s'\n", fileName.GetString());
14011402
IfJsrtErrorSetGoLabel(ChakraRTInterface::JsGetUndefinedValue(&returnValue), Error);
14021403
return returnValue;
@@ -1845,12 +1846,14 @@ HRESULT WScriptJsrt::CallbackMessage::CallFunction(LPCSTR fileName)
18451846
return hr;
18461847
}
18471848

1848-
WScriptJsrt::ModuleMessage::ModuleMessage(JsModuleRecord module, JsValueRef specifier)
1849+
WScriptJsrt::ModuleMessage::ModuleMessage(JsModuleRecord module, JsValueRef specifier, std::string* fullPathPtr)
18491850
: MessageBase(0), moduleRecord(module), specifier(specifier)
18501851
{
1852+
fullPath = nullptr;
18511853
ChakraRTInterface::JsAddRef(module, nullptr);
18521854
if (specifier != nullptr)
18531855
{
1856+
fullPath = new std::string (*fullPathPtr);
18541857
// nullptr specifier means a Promise to execute; non-nullptr means a "fetch" operation.
18551858
ChakraRTInterface::JsAddRef(specifier, nullptr);
18561859
}
@@ -1861,21 +1864,39 @@ WScriptJsrt::ModuleMessage::~ModuleMessage()
18611864
ChakraRTInterface::JsRelease(moduleRecord, nullptr);
18621865
if (specifier != nullptr)
18631866
{
1867+
delete fullPath;
18641868
ChakraRTInterface::JsRelease(specifier, nullptr);
18651869
}
18661870
}
18671871

18681872
HRESULT WScriptJsrt::ModuleMessage::Call(LPCSTR fileName)
18691873
{
1870-
JsErrorCode errorCode;
1874+
JsErrorCode errorCode = JsNoError;
18711875
JsValueRef result = JS_INVALID_REFERENCE;
18721876
HRESULT hr;
18731877
if (specifier == nullptr)
18741878
{
1875-
errorCode = ChakraRTInterface::JsModuleEvaluation(moduleRecord, &result);
1876-
if (errorCode != JsNoError)
1879+
if (moduleErrMap[moduleRecord] != ErroredModule)
18771880
{
1878-
PrintException(fileName, errorCode);
1881+
errorCode = ChakraRTInterface::JsModuleEvaluation(moduleRecord, &result);
1882+
if (errorCode != JsNoError)
1883+
{
1884+
if (moduleErrMap[moduleRecord] == RootModule)
1885+
{
1886+
PrintException(fileName, errorCode);
1887+
}
1888+
else
1889+
{
1890+
bool hasException = false;
1891+
ChakraRTInterface::JsHasException(&hasException);
1892+
if (hasException)
1893+
{
1894+
JsValueRef exception;
1895+
ChakraRTInterface::JsGetAndClearException(&exception);
1896+
exception; //unusued
1897+
}
1898+
}
1899+
}
18791900
}
18801901
}
18811902
else
@@ -1885,19 +1906,22 @@ HRESULT WScriptJsrt::ModuleMessage::Call(LPCSTR fileName)
18851906
errorCode = specifierStr.GetError();
18861907
if (errorCode == JsNoError)
18871908
{
1888-
hr = Helpers::LoadScriptFromFile(*specifierStr, fileContent);
1909+
hr = Helpers::LoadScriptFromFile(*specifierStr, fileContent, nullptr, fullPath, true);
18891910

18901911
if (FAILED(hr))
18911912
{
1892-
// check if have it registered
18931913
if (!HostConfigFlags::flags.MuteHostErrorMsgIsEnabled)
18941914
{
1895-
fprintf(stderr, "Couldn't load file '%s'\n", specifierStr.GetString());
1915+
auto actualModuleRecord = moduleRecordMap.find(*fullPath);
1916+
if (actualModuleRecord == moduleRecordMap.end() || moduleErrMap[actualModuleRecord->second] == RootModule)
1917+
{
1918+
fprintf(stderr, "Couldn't load file '%s'\n", specifierStr.GetString());
1919+
}
18961920
}
1897-
LoadScript(nullptr, *specifierStr, nullptr, "module", true, WScriptJsrt::FinalizeFree, false);
1921+
LoadScript(nullptr, fullPath == nullptr ? *specifierStr : fullPath->c_str(), nullptr, "module", true, WScriptJsrt::FinalizeFree, false);
18981922
goto Error;
18991923
}
1900-
LoadScript(nullptr, *specifierStr, fileContent, "module", true, WScriptJsrt::FinalizeFree, true);
1924+
LoadScript(nullptr, fullPath == nullptr ? *specifierStr : fullPath->c_str(), fileContent, "module", true, WScriptJsrt::FinalizeFree, true);
19011925
}
19021926
}
19031927
Error:
@@ -1936,9 +1960,10 @@ JsErrorCode WScriptJsrt::FetchImportedModuleHelper(JsModuleRecord referencingMod
19361960
{
19371961
GetDir(fullPath, &moduleDirMap[moduleRecord]);
19381962
InitializeModuleInfo(specifier, moduleRecord);
1939-
moduleRecordMap[std::string(fullPath)] = moduleRecord;
1940-
ModuleMessage* moduleMessage =
1941-
WScriptJsrt::ModuleMessage::Create(referencingModule, specifier);
1963+
std::string pathKey = std::string(fullPath);
1964+
moduleRecordMap[pathKey] = moduleRecord;
1965+
moduleErrMap[moduleRecord] = ImportedModule;
1966+
ModuleMessage* moduleMessage = WScriptJsrt::ModuleMessage::Create(referencingModule, specifier, &pathKey);
19421967
if (moduleMessage == nullptr)
19431968
{
19441969
return JsErrorOutOfMemory;
@@ -1973,14 +1998,6 @@ JsErrorCode WScriptJsrt::FetchImportedModule(_In_ JsModuleRecord referencingModu
19731998
JsErrorCode WScriptJsrt::FetchImportedModuleFromScript(_In_ JsSourceContext dwReferencingSourceContext,
19741999
_In_ JsValueRef specifier, _Outptr_result_maybenull_ JsModuleRecord* dependentModuleRecord)
19752000
{
1976-
// ch.exe assumes all imported source files are located at .
1977-
auto scriptDirEntry = scriptDirMap.find(dwReferencingSourceContext);
1978-
if (scriptDirEntry != scriptDirMap.end())
1979-
{
1980-
std::string dir = scriptDirEntry->second;
1981-
return FetchImportedModuleHelper(nullptr, specifier, dependentModuleRecord, dir.c_str());
1982-
}
1983-
19842001
return FetchImportedModuleHelper(nullptr, specifier, dependentModuleRecord);
19852002
}
19862003

@@ -2008,7 +2025,8 @@ JsErrorCode WScriptJsrt::NotifyModuleReadyCallback(_In_opt_ JsModuleRecord refer
20082025
ChakraRTInterface::JsGetAndClearException(&exception);
20092026
exception; // unused
20102027
}
2011-
else
2028+
2029+
if (exceptionVar != nullptr || moduleErrMap[referencingModule] != ErroredModule)
20122030
{
20132031
WScriptJsrt::ModuleMessage* moduleMessage =
20142032
WScriptJsrt::ModuleMessage::Create(referencingModule, nullptr);

bin/ch/WScriptJsrt.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@
55
#pragma once
66
#include <list>
77

8+
enum ModuleState
9+
{
10+
RootModule,
11+
ImportedModule,
12+
ErroredModule
13+
};
14+
815
class WScriptJsrt
916
{
1017
public:
@@ -36,17 +43,18 @@ class WScriptJsrt
3643
private:
3744
JsModuleRecord moduleRecord;
3845
JsValueRef specifier;
46+
std::string* fullPath;
3947

40-
ModuleMessage(JsModuleRecord module, JsValueRef specifier);
48+
ModuleMessage(JsModuleRecord module, JsValueRef specifier, std::string* fullPathPtr);
4149

4250
public:
4351
~ModuleMessage();
4452

4553
virtual HRESULT Call(LPCSTR fileName) override;
4654

47-
static ModuleMessage* Create(JsModuleRecord module, JsValueRef specifier)
55+
static ModuleMessage* Create(JsModuleRecord module, JsValueRef specifier, std::string* fullPath = nullptr)
4856
{
49-
return new ModuleMessage(module, specifier);
57+
return new ModuleMessage(module, specifier, fullPath);
5058
}
5159

5260
};
@@ -140,5 +148,6 @@ class WScriptJsrt
140148
static DWORD_PTR sourceContext;
141149
static std::map<std::string, JsModuleRecord> moduleRecordMap;
142150
static std::map<JsModuleRecord, std::string> moduleDirMap;
151+
static std::map<JsModuleRecord, ModuleState> moduleErrMap;
143152
static std::map<DWORD_PTR, std::string> scriptDirMap;
144153
};

lib/Parser/Parse.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3624,6 +3624,10 @@ ParseNodePtr Parser::ParseTerm(BOOL fAllowCall,
36243624
case tkIMPORT:
36253625
if (m_scriptContext->GetConfig()->IsES6ModuleEnabled() && m_scriptContext->GetConfig()->IsESDynamicImportEnabled())
36263626
{
3627+
if (!fAllowCall)
3628+
{
3629+
Error(ERRTokenAfter, _u("import"), _u("new"));
3630+
}
36273631
this->GetScanner()->Scan();
36283632
ChkCurTokNoScan(tkLParen, ERRnoLparen);
36293633
pnode = ParseImportCall<buildAST>();

0 commit comments

Comments
 (0)