| //------------------------------------------------------------------------------------------------------- |
| // 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 <rtErrors errnum> class ErrorTypeMap; |
| |
| #define RT_ERROR_MSG(name, errnum, str1, str2, jst, errorNumSource) \ |
| template <> class ErrorTypeMap<name> \ |
| { \ |
| 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<out>::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, LPCWSTR stringOne, LPCWSTR stringTwo) |
| { |
| // 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; |
| } |
| else if (wcslen(stringOne) > 0) |
| { |
| OLECHAR szT[128]; |
| _snwprintf_s(szT, ARRAYSIZE(szT), ARRAYSIZE(szT)-1, ei.bstrDescription, stringOne, stringTwo); |
| SysFreeString(ei.bstrDescription); |
| ei.bstrDescription = SysAllocString(szT); |
| } |
| |
| 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; |
| } |