Skip to content

Commit 72bf19e

Browse files
committed
Syntax error for undefined module export per
1 parent 05bcc0b commit 72bf19e

File tree

5 files changed

+51
-20
lines changed

5 files changed

+51
-20
lines changed

lib/Parser/Parse.cpp

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -335,10 +335,10 @@ void Parser::Error(HRESULT hr, ParseNodePtr pnode)
335335
}
336336
}
337337

338-
void Parser::Error(HRESULT hr, charcount_t ichMin, charcount_t ichLim)
338+
void Parser::Error(HRESULT hr, charcount_t ichMin, charcount_t ichLim, LPCWSTR stringOne, LPCWSTR stringTwo)
339339
{
340340
this->GetScanner()->SetErrorPosition(ichMin, ichLim);
341-
Error(hr);
341+
Error(hr, stringOne, stringTwo);
342342
}
343343

344344
void Parser::IdentifierExpectedError(const Token& token)
@@ -2350,6 +2350,7 @@ void Parser::ParseNamedImportOrExportClause(ModuleImportOrExportEntryList* impor
23502350

23512351
IdentPtr identifierName = m_token.GetIdentifier(this->GetHashTbl());
23522352
IdentPtr identifierAs = identifierName;
2353+
charcount_t offsetForError = this->GetScanner()->IchMinTok();
23532354

23542355
this->GetScanner()->Scan();
23552356

@@ -2392,19 +2393,16 @@ void Parser::ParseNamedImportOrExportClause(ModuleImportOrExportEntryList* impor
23922393
this->GetScanner()->Scan();
23932394
}
23942395

2395-
if (buildAST)
2396+
if (isExportClause)
2397+
{
2398+
identifierName->SetIsModuleExport();
2399+
AddModuleImportOrExportEntry(importOrExportEntryList, nullptr, identifierName, identifierAs, nullptr, offsetForError);
2400+
}
2401+
else if (buildAST)
23962402
{
23972403
// The name we will use 'as' this import/export is a binding identifier in import statements.
2398-
if (!isExportClause)
2399-
{
2400-
CreateModuleImportDeclNode(identifierAs);
2401-
AddModuleImportOrExportEntry(importOrExportEntryList, identifierName, identifierAs, nullptr, nullptr);
2402-
}
2403-
else
2404-
{
2405-
identifierName->SetIsModuleExport();
2406-
AddModuleImportOrExportEntry(importOrExportEntryList, nullptr, identifierName, identifierAs, nullptr);
2407-
}
2404+
CreateModuleImportDeclNode(identifierAs);
2405+
AddModuleImportOrExportEntry(importOrExportEntryList, identifierName, identifierAs, nullptr, nullptr);
24082406
}
24092407
}
24102408

@@ -2417,6 +2415,23 @@ IdentPtrList* Parser::GetRequestedModulesList()
24172415
return m_currentNodeProg->AsParseNodeModule()->requestedModules;
24182416
}
24192417

2418+
void Parser::VerifyModuleLocalExportEntries()
2419+
{
2420+
ModuleImportOrExportEntryList* localExportRecordList = GetModuleLocalExportEntryList();
2421+
if (localExportRecordList != nullptr)
2422+
{
2423+
localExportRecordList->Map([=](ModuleImportOrExportEntry exportEntry) {
2424+
if (exportEntry.pidRefStack!=nullptr)
2425+
{
2426+
if (exportEntry.pidRefStack->GetSym() == nullptr)
2427+
{
2428+
Error(ERRUndeclaredExportName, exportEntry.offset, exportEntry.localName->Cch(), exportEntry.localName->Psz());
2429+
}
2430+
}
2431+
});
2432+
}
2433+
}
2434+
24202435
ModuleImportOrExportEntryList* Parser::GetModuleImportEntryList()
24212436
{
24222437
return m_currentNodeProg->AsParseNodeModule()->importEntries;
@@ -2504,14 +2519,16 @@ ModuleImportOrExportEntry* Parser::AddModuleImportOrExportEntry(ModuleImportOrEx
25042519
return importOrExportEntry;
25052520
}
25062521

2507-
ModuleImportOrExportEntry* Parser::AddModuleImportOrExportEntry(ModuleImportOrExportEntryList* importOrExportEntryList, IdentPtr importName, IdentPtr localName, IdentPtr exportName, IdentPtr moduleRequest)
2522+
ModuleImportOrExportEntry* Parser::AddModuleImportOrExportEntry(ModuleImportOrExportEntryList* importOrExportEntryList, IdentPtr importName, IdentPtr localName, IdentPtr exportName, IdentPtr moduleRequest, charcount_t offsetForError)
25082523
{
25092524
ModuleImportOrExportEntry* importOrExportEntry = Anew(&m_nodeAllocator, ModuleImportOrExportEntry);
25102525

25112526
importOrExportEntry->importName = importName;
25122527
importOrExportEntry->localName = localName;
25132528
importOrExportEntry->exportName = exportName;
25142529
importOrExportEntry->moduleRequest = moduleRequest;
2530+
importOrExportEntry->pidRefStack = offsetForError == 0 ? nullptr : PushPidRef(localName);
2531+
importOrExportEntry->offset = offsetForError;
25152532

25162533
return AddModuleImportOrExportEntry(importOrExportEntryList, importOrExportEntry);
25172534
}
@@ -12002,6 +12019,13 @@ ParseNodeProg * Parser::Parse(LPCUTF8 pszSrc, size_t offset, size_t length, char
1200212019
{
1200312020
JS_ETW(EventWriteJSCRIPT_PARSE_METHOD_STOP(m_sourceContextInfo->dwHostSourceContext, GetScriptContext(), pnodeProg->functionId, *m_pCurrentAstSize, false, Js::Constants::GlobalFunction));
1200412021
}
12022+
12023+
if (isModuleSource)
12024+
{
12025+
// verify that any local module exports are defined
12026+
VerifyModuleLocalExportEntries();
12027+
}
12028+
1200512029
return pnodeProg;
1200612030
}
1200712031

lib/Parser/Parse.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ class Parser
317317
__declspec(noreturn) void Error(HRESULT hr, LPCWSTR stringOne = _u(""), LPCWSTR stringTwo = _u(""));
318318
private:
319319
__declspec(noreturn) void Error(HRESULT hr, ParseNodePtr pnode);
320-
__declspec(noreturn) void Error(HRESULT hr, charcount_t ichMin, charcount_t ichLim);
320+
__declspec(noreturn) void Error(HRESULT hr, charcount_t ichMin, charcount_t ichLim, LPCWSTR stringOne = _u(""), LPCWSTR stringTwo = _u(""));
321321
__declspec(noreturn) static void OutOfMemory();
322322

323323
void EnsureStackAvailable();
@@ -641,11 +641,12 @@ class Parser
641641
ModuleImportOrExportEntryList* EnsureModuleStarExportEntryList();
642642

643643
void AddModuleSpecifier(IdentPtr moduleRequest);
644-
ModuleImportOrExportEntry* AddModuleImportOrExportEntry(ModuleImportOrExportEntryList* importOrExportEntryList, IdentPtr importName, IdentPtr localName, IdentPtr exportName, IdentPtr moduleRequest);
644+
ModuleImportOrExportEntry* AddModuleImportOrExportEntry(ModuleImportOrExportEntryList* importOrExportEntryList, IdentPtr importName, IdentPtr localName, IdentPtr exportName, IdentPtr moduleRequest, charcount_t offsetForError = 0);
645645
ModuleImportOrExportEntry* AddModuleImportOrExportEntry(ModuleImportOrExportEntryList* importOrExportEntryList, ModuleImportOrExportEntry* importOrExportEntry);
646646
void AddModuleLocalExportEntry(ParseNodePtr varDeclNode);
647647
void CheckForDuplicateExportEntry(IdentPtr exportName);
648648
void CheckForDuplicateExportEntry(ModuleImportOrExportEntryList* exportEntryList, IdentPtr exportName);
649+
void VerifyModuleLocalExportEntries();
649650

650651
ParseNodeVar * CreateModuleImportDeclNode(IdentPtr localName);
651652

lib/Parser/ParserCommon.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,17 @@ class ParseNodeFnc;
3939
typedef ParseNode *ParseNodePtr;
4040

4141
struct Ident;
42+
struct PidRefStack;
4243
typedef Ident *IdentPtr;
4344

4445
struct ModuleImportOrExportEntry
4546
{
46-
IdentPtr moduleRequest;
47-
IdentPtr importName;
48-
IdentPtr localName;
49-
IdentPtr exportName;
47+
IdentPtr moduleRequest;
48+
IdentPtr importName;
49+
IdentPtr localName;
50+
IdentPtr exportName;
51+
PidRefStack* pidRefStack;
52+
charcount_t offset;
5053
};
5154

5255
typedef SList<ModuleImportOrExportEntry, ArenaAllocator> ModuleImportOrExportEntryList;

lib/Parser/perrors.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ LSC_ERROR_MSG(1096, ERRAwaitAsLabelInAsync, "Use of 'await' as label in async fu
112112
LSC_ERROR_MSG(1097, ERRExperimental, "Use of disabled experimental feature")
113113
LSC_ERROR_MSG(1098, ERRDuplicateExport, "Duplicate export of name '%s'")
114114
LSC_ERROR_MSG(1099, ERRStmtOfWithIsLabelledFunc, "The statement of a 'with' statement cannot be a labelled function.")
115+
LSC_ERROR_MSG(1100, ERRUndeclaredExportName, "Export of name '%s' which has no local definition.")
115116
//1100-1199 available for future use
116117

117118
// Generic errors intended to be re-usable

test/es6module/module-syntax.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ var tests = [
115115
testModuleScript(`do export default null
116116
while (false);`, 'Syntax error export in while', true);
117117
testModuleScript('function () { export default null; }', 'Syntax error export in function', true);
118+
testModuleScript('export {foo}', 'Syntax error undefined export', true);
119+
testModuleScript('export {Array}', 'Syntax error exporting a global name with no local definition', true);
118120
}
119121
},
120122
{

0 commit comments

Comments
 (0)