//------------------------------------------------------------------------------------------------------- // Copyright (C) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. //------------------------------------------------------------------------------------------------------- #include "ParserPch.h" #pragma hdrstop #include "errstr.h" void CopyException (EXCEPINFO *peiDest, const EXCEPINFO *peiSource) { FreeExcepInfo(peiDest); *peiDest = *peiSource; if (peiSource->bstrSource) { peiDest->bstrSource = SysAllocStringLen(peiSource->bstrSource, SysStringLen(peiSource->bstrSource)); } if (peiSource->bstrDescription) { peiDest->bstrDescription = SysAllocStringLen(peiSource->bstrDescription, SysStringLen(peiSource->bstrDescription)); } if (peiSource->bstrHelpFile) { peiDest->bstrHelpFile = SysAllocStringLen(peiSource->bstrHelpFile, SysStringLen(peiSource->bstrHelpFile)); } } /*************************************************************************** HRESULT mapping ***************************************************************************/ template class ErrorTypeMap; #define RT_ERROR_MSG(name, errnum, str1, str2, jst, errorNumSource) \ template <> class ErrorTypeMap \ { \ public: \ static const ErrorTypeEnum Type = jst; \ }; #define RT_PUBLICERROR_MSG(name, errnum, str1, str2, jst, errorNumSource) RT_ERROR_MSG(name, errnum, str1, str2, jst, errorNumSource) #include "rterrors.h" #undef RT_PUBLICERROR_MSG #undef RT_ERROR_MSG struct MHR { HRESULT hrIn; HRESULT hrOut; ErrorTypeEnum errorType; }; // This table maps OLE errors to JScript errors. The comment on each line // shows the numeric value. The table must be sorted so we can do a binary // search on it. #define MAPHR(in, out) { HR(in), out, ErrorTypeMap::Type } const MHR g_rgmhr[] = { // FACILITY_NULL errors /*0x80004001*/ MAPHR(E_NOTIMPL, VBSERR_ActionNotSupported), /*0x80004002*/ MAPHR(E_NOINTERFACE, VBSERR_OLENotSupported), // FACILITY_DISPATCH - IDispatch errors. /*0x80020001*/ MAPHR(DISP_E_UNKNOWNINTERFACE, VBSERR_OLENoPropOrMethod), /*0x80020003*/ MAPHR(DISP_E_MEMBERNOTFOUND, VBSERR_OLENoPropOrMethod), /*0x80020004*/ MAPHR(DISP_E_PARAMNOTFOUND, VBSERR_NamedParamNotFound), /*0x80020005*/ MAPHR(DISP_E_TYPEMISMATCH, VBSERR_TypeMismatch), /*0x80020006*/ MAPHR(DISP_E_UNKNOWNNAME, VBSERR_OLENoPropOrMethod), /*0x80020007*/ MAPHR(DISP_E_NONAMEDARGS, VBSERR_NamedArgsNotSupported), /*0x80020008*/ MAPHR(DISP_E_BADVARTYPE, VBSERR_InvalidTypeLibVariable), /*0x8002000A*/ MAPHR(DISP_E_OVERFLOW, VBSERR_Overflow), /*0x8002000B*/ MAPHR(DISP_E_BADINDEX, VBSERR_OutOfBounds), /*0x8002000C*/ MAPHR(DISP_E_UNKNOWNLCID, VBSERR_LocaleSettingNotSupported), /*0x8002000D*/ MAPHR(DISP_E_ARRAYISLOCKED, VBSERR_ArrayLocked), /*0x8002000E*/ MAPHR(DISP_E_BADPARAMCOUNT, VBSERR_FuncArityMismatch), /*0x8002000F*/ MAPHR(DISP_E_PARAMNOTOPTIONAL, VBSERR_ParameterNotOptional), /*0x80020011*/ MAPHR(DISP_E_NOTACOLLECTION, VBSERR_NotEnum), // FACILITY_DISPATCH - Typelib errors. /*0x8002802F*/ MAPHR(TYPE_E_DLLFUNCTIONNOTFOUND, VBSERR_InvalidDllFunctionName), /*0x80028CA0*/ MAPHR(TYPE_E_TYPEMISMATCH, VBSERR_TypeMismatch), /*0x80028CA1*/ MAPHR(TYPE_E_OUTOFBOUNDS, VBSERR_OutOfBounds), /*0x80028CA2*/ MAPHR(TYPE_E_IOERROR, VBSERR_IOError), /*0x80028CA3*/ MAPHR(TYPE_E_CANTCREATETMPFILE, VBSERR_CantCreateTmpFile), /*0x80029C4A*/ MAPHR(TYPE_E_CANTLOADLIBRARY, VBSERR_DLLLoadErr), // FACILITY_STORAGE errors /*0x80030002*/ MAPHR(STG_E_FILENOTFOUND, VBSERR_OLEFileNotFound), /*0x80030003*/ MAPHR(STG_E_PATHNOTFOUND, VBSERR_PathNotFound), /*0x80030004*/ MAPHR(STG_E_TOOMANYOPENFILES, VBSERR_TooManyFiles), /*0x80030005*/ MAPHR(STG_E_ACCESSDENIED, VBSERR_PermissionDenied), /*0x80030008*/ MAPHR(STG_E_INSUFFICIENTMEMORY, VBSERR_OutOfMemory), /*0x80030012*/ MAPHR(STG_E_NOMOREFILES, VBSERR_TooManyFiles), /*0x80030013*/ MAPHR(STG_E_DISKISWRITEPROTECTED, VBSERR_PermissionDenied), /*0x8003001D*/ MAPHR(STG_E_WRITEFAULT, VBSERR_IOError), /*0x8003001E*/ MAPHR(STG_E_READFAULT, VBSERR_IOError), /*0x80030020*/ MAPHR(STG_E_SHAREVIOLATION, VBSERR_PathFileAccess), /*0x80030021*/ MAPHR(STG_E_LOCKVIOLATION, VBSERR_PermissionDenied), /*0x80030050*/ MAPHR(STG_E_FILEALREADYEXISTS, VBSERR_FileAlreadyExists), /*0x80030070*/ MAPHR(STG_E_MEDIUMFULL, VBSERR_DiskFull), /*0x800300FC*/ MAPHR(STG_E_INVALIDNAME, VBSERR_FileNotFound), /*0x80030100*/ MAPHR(STG_E_INUSE, VBSERR_PermissionDenied), /*0x80030101*/ MAPHR(STG_E_NOTCURRENT, VBSERR_PermissionDenied), /*0x80030103*/ MAPHR(STG_E_CANTSAVE, VBSERR_IOError), // FACILITY_ITF errors. /*0x80040154*/ MAPHR(REGDB_E_CLASSNOTREG, VBSERR_CantCreateObject), /*0x800401E3*/ MAPHR(MK_E_UNAVAILABLE, VBSERR_CantCreateObject), /*0x800401E6*/ MAPHR(MK_E_INVALIDEXTENSION, VBSERR_OLEFileNotFound), /*0x800401EA*/ MAPHR(MK_E_CANTOPENFILE, VBSERR_OLEFileNotFound), /*0x800401F3*/ MAPHR(CO_E_CLASSSTRING, VBSERR_CantCreateObject), /*0x800401F5*/ MAPHR(CO_E_APPNOTFOUND, VBSERR_CantCreateObject), /*0x800401FE*/ MAPHR(CO_E_APPDIDNTREG, VBSERR_CantCreateObject), #if _WIN32 // FACILITY_WIN32 errors /*0x80070005*/ MAPHR(E_ACCESSDENIED, VBSERR_PermissionDenied), /*0x8007000E*/ MAPHR(E_OUTOFMEMORY, VBSERR_OutOfMemory), /*0x80070057*/ MAPHR(E_INVALIDARG, VBSERR_IllegalFuncCall), /*0x800706BA*/ MAPHR(_HRESULT_TYPEDEF_(0x800706BA), VBSERR_ServerNotFound), // FACILITY_WINDOWS /*0x80080005*/ MAPHR(CO_E_SERVER_EXEC_FAILURE, VBSERR_CantCreateObject), #endif // _WIN32 }; const int32 kcmhr = sizeof(g_rgmhr) / sizeof(g_rgmhr[0]); HRESULT MapHr(HRESULT hr, ErrorTypeEnum * errorTypeOut) { int imhrMin, imhrLim, imhr; #if DEBUG // In debug, check that all the entries in the error map table are // sorted based on the HRESULT in ascending order. We will then binary // search the sorted array. We need do this only once per invocation. static BOOL fCheckSort = TRUE; if (fCheckSort) { fCheckSort = FALSE; for (imhr = 1; imhr < kcmhr; imhr++) Assert((uint32)g_rgmhr[imhr - 1].hrIn < (uint32)g_rgmhr[imhr].hrIn); } #endif // DEBUG if (errorTypeOut != nullptr) { *errorTypeOut = kjstError; } if (SUCCEEDED(hr)) return NOERROR; if (FACILITY_CONTROL == HRESULT_FACILITY(hr)) return hr; for (imhrMin = 0, imhrLim = kcmhr; imhrMin < imhrLim; ) { imhr = (imhrMin + imhrLim) / 2; if ((uint32)g_rgmhr[imhr].hrIn < (uint32)hr) imhrMin = imhr + 1; else imhrLim = imhr; } if (imhrMin < kcmhr && hr == g_rgmhr[imhrMin].hrIn) { if (errorTypeOut != nullptr) { *errorTypeOut = g_rgmhr[imhrMin].errorType; } return g_rgmhr[imhrMin].hrOut; } return hr; } // === ScriptException === ScriptException::~ScriptException(void) { FreeExcepInfo(&ei); } void ScriptException::CopyInto(ScriptException *pse) { pse->ichMin = ichMin; pse->ichLim = ichLim; CopyException(&(pse->ei), &ei); } void ScriptException::Free(void) { ichMin = ichLim = 0; FreeExcepInfo(&ei); } void ScriptException::GetError(HRESULT *phr, EXCEPINFO *pei) { Assert(phr); if (HR(SCRIPT_E_RECORDED) == *phr) { Assert(FAILED(HR(ei.scode))); if (nullptr == pei) *phr = HR(ei.scode); else { *phr = HR(DISP_E_EXCEPTION); js_memcpy_s(pei, sizeof(*pei), &ei, sizeof(*pei)); memset(&ei, 0, sizeof(ei)); if (nullptr != pei->pfnDeferredFillIn) { pei->pfnDeferredFillIn(pei); pei->pfnDeferredFillIn = nullptr; } } } } // === CompileScriptException === CompileScriptException::~CompileScriptException() { SysFreeString(bstrLine); } void CompileScriptException::Free() { ScriptException::Free(); line = ichMinLine = 0; if (nullptr != bstrLine) { SysFreeString(bstrLine); bstrLine = nullptr; } } void CompileScriptException::CopyInto(CompileScriptException* pse) { ScriptException::CopyInto(pse); pse->line = this->line; pse->ichMinLine = this->ichMinLine; pse->hasLineNumberInfo = this->hasLineNumberInfo; if (this->bstrLine) { pse->bstrLine = SysAllocStringLen(this->bstrLine, SysStringLen(this->bstrLine)); } } HRESULT CompileScriptException::ProcessError(IScanner * pScan, HRESULT hr, ParseNode * pnodeBase) { // fill in the ScriptException structure Free(); ei.scode = GetScode(MapHr(hr)); // get the error string if (FACILITY_CONTROL != HRESULT_FACILITY(ei.scode) || nullptr == (ei.bstrDescription = BstrGetResourceString(HRESULT_CODE(ei.scode)))) { OLECHAR szT[50]; _snwprintf_s(szT, ARRAYSIZE(szT), ARRAYSIZE(szT)-1, _u("error %d"), ei.scode); if (nullptr == (ei.bstrDescription = SysAllocString(szT))) ei.scode = E_OUTOFMEMORY; } ei.bstrSource = BstrGetResourceString(IDS_COMPILATION_ERROR_SOURCE); if (nullptr == pnodeBase && nullptr != pScan) { // parsing phase - get the line number from the scanner Assert(pScan); this->hasLineNumberInfo = true; pScan->GetErrorLineInfo(this->ichMin, this->ichLim, this->line, this->ichMinLine); HRESULT hrSysAlloc = pScan->SysAllocErrorLine(this->ichMinLine, &this->bstrLine); if( FAILED(hrSysAlloc) ) { return hrSysAlloc; } if (ichMin < ichMinLine) ichMin = ichMinLine; } else { // TODO: Variable length registers. // Remove E_FAIL once we have this feature. // error during code gen - no line number info available // E_ABORT may result if compilation does stack probe while thread is in disabled state. Assert(hr == WASMERR_WasmCompileError || hr == JSERR_AsmJsCompileError || hr == ERRnoMemory || hr == VBSERR_OutOfStack || hr == E_OUTOFMEMORY || hr == E_FAIL || hr == E_ABORT); } return SCRIPT_E_RECORDED; }