EngineInterfaceObject.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "RuntimeLibraryPch.h"
  6. #if defined(ENABLE_INTL_OBJECT) || defined(ENABLE_JS_BUILTINS)
  7. #include "errstr.h"
  8. #include "Library/EngineInterfaceObject.h"
  9. #include "Types/DeferredTypeHandler.h"
  10. #define IfFailThrowHr(op) \
  11. if (FAILED(hr=(op))) \
  12. { \
  13. JavascriptError::MapAndThrowError(scriptContext, hr); \
  14. } \
  15. #define IfFailAssertAndThrowHr(op) \
  16. if (FAILED(hr=(op))) \
  17. { \
  18. AssertMsg(false, "HRESULT was a failure."); \
  19. JavascriptError::MapAndThrowError(scriptContext, hr); \
  20. } \
  21. #define SetPropertyOn(obj, propID, value) \
  22. obj->SetProperty(propID, value, Js::PropertyOperationFlags::PropertyOperation_None, nullptr) \
  23. #define SetStringPropertyOn(obj, propID, propValue) \
  24. SetPropertyOn(obj, propID, Js::JavascriptString::NewCopySz(propValue, scriptContext)) \
  25. #define SetHSTRINGPropertyOn(obj, propID, hstringValue) \
  26. SetStringPropertyOn(obj, propID, wgl->WindowsGetStringRawBuffer(hstringValue, &length)) \
  27. #define SetPropertyLOn(obj, literalProperty, value) \
  28. obj->SetProperty(Js::JavascriptString::NewCopySz(literalProperty, scriptContext), value, Js::PropertyOperationFlags::PropertyOperation_None, nullptr) \
  29. #define SetStringPropertyLOn(obj, literalProperty, propValue) \
  30. SetPropertyLOn(obj, literalProperty, Js::JavascriptString::NewCopySz(propValue, scriptContext)) \
  31. #define SetHSTRINGPropertyLOn(obj, literalProperty, hstringValue) \
  32. SetStringPropertyLOn(obj, literalProperty, wgl->WindowsGetStringRawBuffer(hstringValue, &length)) \
  33. #define SetPropertyBuiltInOn(obj, builtInPropID, value) \
  34. SetPropertyOn(obj, Js::PropertyIds::builtInPropID, value) \
  35. #define SetStringPropertyBuiltInOn(obj, builtInPropID, propValue) \
  36. SetPropertyBuiltInOn(obj, builtInPropID, Js::JavascriptString::NewCopySz(propValue, scriptContext))
  37. #define SetHSTRINGPropertyBuiltInOn(obj, builtInPropID, hstringValue) \
  38. SetStringPropertyBuiltInOn(obj, builtInPropID, wgl->WindowsGetStringRawBuffer(hstringValue, &length)) \
  39. #define GetPropertyFrom(obj, propertyID) \
  40. Js::JavascriptOperators::GetProperty(obj, propertyID, &propertyValue, scriptContext) \
  41. #define GetPropertyLFrom(obj, propertyName) \
  42. GetPropertyFrom(obj, scriptContext->GetOrAddPropertyIdTracked(propertyName, wcslen(propertyName)))
  43. #define GetPropertyBuiltInFrom(obj, builtInPropID) \
  44. GetPropertyFrom(obj, Js::PropertyIds::builtInPropID) \
  45. #define GetTypedPropertyBuiltInFrom(obj, builtInPropID, Type) \
  46. (GetPropertyFrom(obj, Js::PropertyIds::builtInPropID) && VarIs<Type>(propertyValue)) \
  47. #define HasPropertyOn(obj, propID) \
  48. Js::JavascriptOperators::HasProperty(obj, propID) \
  49. #define HasPropertyBuiltInOn(obj, builtInPropID) \
  50. HasPropertyOn(obj, Js::PropertyIds::builtInPropID) \
  51. #define HasPropertyLOn(obj, propertyName) \
  52. HasPropertyOn(obj, scriptContext->GetOrAddPropertyIdTracked(propertyName, wcslen(propertyName)))
  53. namespace Js
  54. {
  55. EngineExtensionObjectBase* EngineInterfaceObject::GetEngineExtension(EngineInterfaceExtensionKind extensionKind) const
  56. {
  57. AnalysisAssert(extensionKind >= 0 && extensionKind <= MaxEngineInterfaceExtensionKind);
  58. if (extensionKind <= MaxEngineInterfaceExtensionKind)
  59. {
  60. Assert(engineExtensions[extensionKind] == nullptr || engineExtensions[extensionKind]->GetExtensionKind() == extensionKind);
  61. return engineExtensions[extensionKind];
  62. }
  63. return nullptr;
  64. }
  65. void EngineInterfaceObject::SetEngineExtension(EngineInterfaceExtensionKind extensionKind, EngineExtensionObjectBase* extensionObject)
  66. {
  67. AnalysisAssert(extensionKind >= 0 && extensionKind <= MaxEngineInterfaceExtensionKind);
  68. if (extensionKind <= MaxEngineInterfaceExtensionKind)
  69. {
  70. Assert(engineExtensions[extensionKind] == nullptr);
  71. engineExtensions[extensionKind] = extensionObject;
  72. // Init the extensionObject if this was already initialized
  73. if (this->IsInitialized())
  74. {
  75. extensionObject->Initialize();
  76. }
  77. }
  78. }
  79. // initialize EngineInterfaceObject::EntryInfo
  80. #define EngineInterfaceBuiltIn2(propId, nativeMethod) NoProfileFunctionInfo EngineInterfaceObject::EntryInfo::nativeMethod(FORCE_NO_WRITE_BARRIER_TAG(EngineInterfaceObject::Entry_##nativeMethod));
  81. #define BuiltInRaiseException(exceptionType, exceptionID) NoProfileFunctionInfo EngineInterfaceObject::EntryInfo::BuiltIn_raise##exceptionID(FORCE_NO_WRITE_BARRIER_TAG(EngineInterfaceObject::Entry_BuiltIn_raise##exceptionID));
  82. #include "EngineInterfaceObjectBuiltIns.h"
  83. EngineInterfaceObject * EngineInterfaceObject::New(Recycler * recycler, DynamicType * type)
  84. {
  85. EngineInterfaceObject* newObject = NewObject<EngineInterfaceObject>(recycler, type);
  86. for (uint i = 0; i <= MaxEngineInterfaceExtensionKind; i++)
  87. {
  88. newObject->engineExtensions[i] = nullptr;
  89. }
  90. return newObject;
  91. }
  92. void EngineInterfaceObject::Initialize()
  93. {
  94. Recycler* recycler = this->GetRecycler();
  95. ScriptContext* scriptContext = this->GetScriptContext();
  96. JavascriptLibrary* library = scriptContext->GetLibrary();
  97. // CommonNativeInterfaces is used as a prototype for the other native interface objects
  98. // to share the common APIs without requiring everyone to access EngineInterfaceObject.Common.
  99. this->commonNativeInterfaces = DynamicObject::New(recycler,
  100. DynamicType::New(scriptContext, TypeIds_Object, library->GetNull(), nullptr,
  101. DeferredTypeHandler<InitializeCommonNativeInterfaces>::GetDefaultInstance()));
  102. library->AddMember(this, Js::PropertyIds::Common, this->commonNativeInterfaces);
  103. for (uint i = 0; i <= MaxEngineInterfaceExtensionKind; i++)
  104. {
  105. if (engineExtensions[i] != nullptr)
  106. {
  107. engineExtensions[i]->Initialize();
  108. }
  109. }
  110. }
  111. #if ENABLE_TTD
  112. void EngineInterfaceObject::MarkVisitKindSpecificPtrs(TTD::SnapshotExtractor* extractor)
  113. {
  114. extractor->MarkVisitVar(this->commonNativeInterfaces);
  115. }
  116. void EngineInterfaceObject::ProcessCorePaths()
  117. {
  118. this->GetScriptContext()->TTDWellKnownInfo->EnqueueNewPathVarAsNeeded(this, this->commonNativeInterfaces, _u("!commonNativeInterfaces"));
  119. }
  120. TTD::NSSnapObjects::SnapObjectType EngineInterfaceObject::GetSnapTag_TTD() const
  121. {
  122. return TTD::NSSnapObjects::SnapObjectType::SnapWellKnownObject;
  123. }
  124. void EngineInterfaceObject::ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc)
  125. {
  126. TTD::NSSnapObjects::StdExtractSetKindSpecificInfo<void*, TTD::NSSnapObjects::SnapObjectType::SnapWellKnownObject>(objData, nullptr);
  127. }
  128. #endif
  129. bool EngineInterfaceObject::InitializeCommonNativeInterfaces(DynamicObject* commonNativeInterfaces, DeferredTypeHandlerBase * typeHandler, DeferredInitializeMode mode)
  130. {
  131. // start with 1 for CallInstanceFunction
  132. int initSlotCapacity = 1;
  133. #define GlobalMathBuiltIn(mathMethod) initSlotCapacity++;
  134. #define GlobalBuiltIn(global, method) initSlotCapacity++;
  135. #define GlobalBuiltInConstructor(global) initSlotCapacity++;
  136. #define BuiltInRaiseException(exceptionType, exceptionID) initSlotCapacity++;
  137. #define EngineInterfaceBuiltIn2(propId, nativeMethod) initSlotCapacity++;
  138. #include "EngineInterfaceObjectBuiltIns.h"
  139. typeHandler->Convert(commonNativeInterfaces, mode, initSlotCapacity);
  140. JavascriptLibrary* library = commonNativeInterfaces->GetScriptContext()->GetLibrary();
  141. #define GlobalMathBuiltIn(mathMethod) library->AddFunctionToLibraryObject(commonNativeInterfaces, PropertyIds::builtInMath##mathMethod, &Math::EntryInfo::mathMethod, 1);
  142. #define GlobalBuiltIn(global, method) library->AddFunctionToLibraryObject(commonNativeInterfaces, PropertyIds::builtIn##global##Entry##method, &global::EntryInfo::method, 1);
  143. #define GlobalBuiltInConstructor(global) SetPropertyOn(commonNativeInterfaces, PropertyIds::##global##, library->Get##global##Constructor());
  144. #define BuiltInRaiseException(exceptionType, exceptionID) library->AddFunctionToLibraryObject(commonNativeInterfaces, PropertyIds::raise##exceptionID, &EngineInterfaceObject::EntryInfo::BuiltIn_raise##exceptionID, 1);
  145. #define EngineInterfaceBuiltIn2(propId, nativeMethod) library->AddFunctionToLibraryObject(commonNativeInterfaces, PropertyIds::propId, &EngineInterfaceObject::EntryInfo::nativeMethod, 1);
  146. #include "EngineInterfaceObjectBuiltIns.h"
  147. library->AddFunctionToLibraryObject(commonNativeInterfaces, PropertyIds::builtInCallInstanceFunction, &EngineInterfaceObject::EntryInfo::CallInstanceFunction, 1);
  148. commonNativeInterfaces->SetHasNoEnumerableProperties(true);
  149. return true;
  150. }
  151. Var EngineInterfaceObject::Entry_GetErrorMessage(RecyclableObject *function, CallInfo callInfo, ...)
  152. {
  153. EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
  154. if (callInfo.Count < 2)
  155. {
  156. return scriptContext->GetLibrary()->GetUndefined();
  157. }
  158. int hr = Js::JavascriptConversion::ToInt32(args[1], scriptContext);
  159. int resourceId;
  160. switch(hr)
  161. {
  162. case ASYNCERR_NoErrorInErrorState:
  163. resourceId = 5200;
  164. break;
  165. case ASYNCERR_InvalidStatusArg:
  166. resourceId = 5201;
  167. break;
  168. case ASYNCERR_InvalidSenderArg:
  169. resourceId = 5202;
  170. break;
  171. default:
  172. AssertMsg(false, "Invalid HRESULT passed to GetErrorMessage. This shouldn't come from Promise.js - who called us?");
  173. return scriptContext->GetLibrary()->GetUndefined();
  174. }
  175. const int strLength = 1024;
  176. OLECHAR errorString[strLength];
  177. if(FGetResourceString(resourceId, errorString, strLength))
  178. {
  179. return Js::JavascriptString::NewCopySz(errorString, scriptContext);
  180. }
  181. AssertMsg(false, "FGetResourceString returned false.");
  182. return scriptContext->GetLibrary()->GetUndefined();
  183. }
  184. Var EngineInterfaceObject::Entry_LogDebugMessage(RecyclableObject *function, CallInfo callInfo, ...)
  185. {
  186. EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
  187. #if DBG
  188. if (callInfo.Count < 2 || !VarIs<JavascriptString>(args.Values[1]))
  189. {
  190. return scriptContext->GetLibrary()->GetUndefined();
  191. }
  192. JavascriptString* message = VarTo<JavascriptString>(args.Values[1]);
  193. Output::Print(message->GetString());
  194. Output::Flush();
  195. #endif
  196. return scriptContext->GetLibrary()->GetUndefined();
  197. }
  198. /* static */
  199. ScriptFunction *EngineInterfaceObject::CreateLibraryCodeScriptFunction(ScriptFunction *scriptFunction, JavascriptString *displayName, bool isConstructor, bool isJsBuiltIn, bool isPublic)
  200. {
  201. if (scriptFunction->GetFunctionProxy()->IsPublicLibraryCode())
  202. {
  203. // this can happen when we re-initialize Intl for a different mode -- for instance, if we have the following JS:
  204. // print((1).toLocaleString())
  205. // print(new Intl.NumberFormat().format(1))
  206. // Intl will first get initialized for Number, and then will get re-initialized for all of Intl. This will cause
  207. // Number.prototype.toLocaleString to be registered twice, which breaks some of our assertions below.
  208. return scriptFunction;
  209. }
  210. ScriptContext *scriptContext = scriptFunction->GetScriptContext();
  211. if (!isConstructor)
  212. {
  213. // set the ErrorOnNew attribute to disallow construction. JsBuiltIn/Intl functions are usually regular ScriptFunctions
  214. // (not lambdas or class methods), so they are usually constructable by default.
  215. FunctionInfo *info = scriptFunction->GetFunctionInfo();
  216. AssertMsg((info->GetAttributes() & FunctionInfo::Attributes::ErrorOnNew) == 0, "Why are we trying to disable construction of a function that already isn't constructable?");
  217. info->SetAttributes((FunctionInfo::Attributes) (info->GetAttributes() | FunctionInfo::Attributes::ErrorOnNew));
  218. // Assert that the type handler is deferred to ensure that we aren't overwriting previous modifications.
  219. // Script functions start with deferred type handlers, which undefer as soon as any property is modified.
  220. // Since the function that is passed in should be an inline function expression, its type should still be deferred by the time it gets here.
  221. AssertOrFailFast(scriptFunction->GetDynamicType()->GetTypeHandler()->IsDeferredTypeHandler());
  222. // give the function a type handler with name and length but without prototype
  223. DynamicTypeHandler::SetInstanceTypeHandler(scriptFunction, scriptContext->GetLibrary()->GetDeferredFunctionWithLengthTypeHandler());
  224. }
  225. else
  226. {
  227. AssertMsg((scriptFunction->GetFunctionInfo()->GetAttributes() & FunctionInfo::Attributes::ErrorOnNew) == 0, "Why is the function not constructable by default?");
  228. }
  229. if (isPublic)
  230. {
  231. // Use GetSz rather than GetString because we use wcsrchr below, which expects a null-terminated string
  232. // Callers can pass in a string like "get compare" or "Intl.Collator.prototype.resolvedOptions" -- only for the
  233. // latter do we extract a shortName.
  234. const char16 *methodNameBuf = displayName->GetSz();
  235. charcount_t methodNameLength = displayName->GetLength();
  236. const char16 *shortName = wcsrchr(methodNameBuf, _u('.'));
  237. charcount_t shortNameOffset = 0;
  238. if (shortName != nullptr)
  239. {
  240. shortName++;
  241. shortNameOffset = static_cast<charcount_t>(shortName - methodNameBuf);
  242. }
  243. scriptFunction->GetFunctionProxy()->EnsureDeserialized()->SetDisplayName(methodNameBuf, methodNameLength, shortNameOffset);
  244. // handle the name property AFTER handling isConstructor, because this can initialize the function's deferred type
  245. Var existingName = nullptr;
  246. if (JavascriptOperators::GetOwnProperty(scriptFunction, PropertyIds::name, &existingName, scriptContext, nullptr))
  247. {
  248. JavascriptString *existingNameString = VarTo<JavascriptString>(existingName);
  249. if (existingNameString->GetLength() == 0)
  250. {
  251. // Only overwrite the name of the function object if it was anonymous coming in
  252. // If the input function was named, it is likely intentional
  253. existingName = nullptr;
  254. }
  255. }
  256. if (existingName == nullptr || JavascriptOperators::IsUndefined(existingName))
  257. {
  258. // It is convenient to set the name here rather than in script, since it is often duplicated.
  259. JavascriptString *funcName = displayName;
  260. if (shortName)
  261. {
  262. funcName = JavascriptString::NewCopyBuffer(shortName, methodNameLength - shortNameOffset, scriptContext);
  263. }
  264. scriptFunction->SetPropertyWithAttributes(PropertyIds::name, funcName, PropertyConfigurable, nullptr);
  265. }
  266. scriptFunction->GetFunctionProxy()->SetIsPublicLibraryCode();
  267. }
  268. if (isJsBuiltIn)
  269. {
  270. scriptFunction->GetFunctionProxy()->SetIsJsBuiltInCode();
  271. // This makes it so that the given scriptFunction can't reference/close over any outside variables,
  272. // which is desirable for JsBuiltIns (though currently not for Intl)
  273. scriptFunction->SetEnvironment(const_cast<FrameDisplay *>(&StrictNullFrameDisplay));
  274. // TODO(jahorto): investigate force-inlining Intl code
  275. scriptFunction->GetFunctionProxy()->EnsureDeserialized();
  276. AssertOrFailFast(scriptFunction->HasFunctionBody());
  277. scriptFunction->GetFunctionBody()->SetJsBuiltInForceInline();
  278. }
  279. return scriptFunction;
  280. }
  281. Var EngineInterfaceObject::Entry_TagPublicLibraryCode(RecyclableObject *function, CallInfo callInfo, ...)
  282. {
  283. #pragma warning(push)
  284. #pragma warning(disable: 4189) // 'scriptContext': local variable is initialized but not referenced
  285. EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
  286. #pragma warning(pop)
  287. AssertOrFailFast((args.Info.Count == 3 || args.Info.Count == 4) && VarIs<ScriptFunction>(args.Values[1]) && VarIs<JavascriptString>(args.Values[2]));
  288. ScriptFunction *func = UnsafeVarTo<ScriptFunction>(args[1]);
  289. JavascriptString *methodName = UnsafeVarTo<JavascriptString>(args[2]);
  290. bool isConstructor = true;
  291. if (args.Info.Count == 4)
  292. {
  293. AssertOrFailFast(VarIs<JavascriptBoolean>(args.Values[3]));
  294. isConstructor = UnsafeVarTo<JavascriptBoolean>(args.Values[3])->GetValue();
  295. }
  296. // isConstructor = true is the default (when no 3rd arg is provided)
  297. return CreateLibraryCodeScriptFunction(func, methodName, isConstructor, false /* isJsBuiltIn */, true /* isPublic */);
  298. }
  299. /*
  300. * First parameter is the object onto which prototype should be set; second is the value
  301. */
  302. Var EngineInterfaceObject::Entry_SetPrototype(RecyclableObject *function, CallInfo callInfo, ...)
  303. {
  304. EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
  305. if (callInfo.Count < 3 || !DynamicObject::IsBaseDynamicObject(args.Values[1]) || !VarIs<RecyclableObject>(args.Values[2]))
  306. {
  307. return scriptContext->GetLibrary()->GetUndefined();
  308. }
  309. DynamicObject* obj = VarTo<DynamicObject>(args.Values[1]);
  310. RecyclableObject* value = VarTo<RecyclableObject>(args.Values[2]);
  311. obj->SetPrototype(value);
  312. return obj;
  313. }
  314. /*
  315. * First parameter is the array object.
  316. */
  317. Var EngineInterfaceObject::Entry_GetArrayLength(RecyclableObject *function, CallInfo callInfo, ...)
  318. {
  319. EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
  320. if (callInfo.Count < 2)
  321. {
  322. return scriptContext->GetLibrary()->GetUndefined();
  323. }
  324. if (DynamicObject::IsAnyArray(args.Values[1]))
  325. {
  326. JavascriptArray* arr = JavascriptArray::FromAnyArray(args.Values[1]);
  327. return TaggedInt::ToVarUnchecked(arr->GetLength());
  328. }
  329. else
  330. {
  331. AssertMsg(false, "Object passed in with unknown type ID, verify Intl.js is correct.");
  332. return TaggedInt::ToVarUnchecked(0);
  333. }
  334. }
  335. /*
  336. * First parameter is the string on which to match.
  337. * Second parameter is the regex object
  338. */
  339. Var EngineInterfaceObject::Entry_RegexMatch(RecyclableObject *function, CallInfo callInfo, ...)
  340. {
  341. EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
  342. if (callInfo.Count < 2 || !VarIs<JavascriptString>(args.Values[1]) || !VarIs<JavascriptRegExp>(args.Values[2]))
  343. {
  344. return scriptContext->GetLibrary()->GetUndefined();
  345. }
  346. JavascriptString *stringToUse = VarTo<JavascriptString>(args.Values[1]);
  347. JavascriptRegExp *regexpToUse = VarTo<JavascriptRegExp>(args.Values[2]);
  348. return RegexHelper::RegexMatchNoHistory(scriptContext, regexpToUse, stringToUse, false);
  349. }
  350. /*
  351. * First parameter is the function, then its the this arg; so at least 2 are needed.
  352. */
  353. Var EngineInterfaceObject::Entry_CallInstanceFunction(RecyclableObject *function, CallInfo callInfo, ...)
  354. {
  355. EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
  356. if (callInfo.Count < 3 || !JavascriptConversion::IsCallable(args.Values[1]))
  357. {
  358. return scriptContext->GetLibrary()->GetUndefined();
  359. }
  360. // TODO: This is marked volatile due to MSVC codegen bug in x86_test_pogo builds. Remove when the bug is fixed
  361. RecyclableObject *volatile func = VarTo<RecyclableObject>(args.Values[1]);
  362. AssertOrFailFastMsg(func != scriptContext->GetLibrary()->GetUndefined(), "Trying to callInstanceFunction(undefined, ...)");
  363. //Shift the arguments by 2 so argument at index 2 becomes the 'this' argument at index 0
  364. for (uint i = 0; i < args.Info.Count - 2; ++i)
  365. {
  366. args.Values[i] = args.Values[i + 2];
  367. }
  368. args.Info.Count -= 2;
  369. BEGIN_SAFE_REENTRANT_CALL(scriptContext->GetThreadContext())
  370. {
  371. return JavascriptFunction::CallFunction<true>(func, func->GetEntryPoint(), args);
  372. }
  373. END_SAFE_REENTRANT_CALL
  374. }
  375. #define BuiltInRaiseException(exceptionType, exceptionID) \
  376. Var EngineInterfaceObject::Entry_BuiltIn_raise##exceptionID(RecyclableObject *function, CallInfo callInfo, ...) \
  377. { \
  378. EngineInterfaceObject_CommonFunctionProlog(function, callInfo); \
  379. \
  380. JavascriptError::Throw##exceptionType(scriptContext, JSERR_##exceptionID); \
  381. }
  382. #define BuiltInRaiseException1(exceptionType, exceptionID) \
  383. Var EngineInterfaceObject::Entry_BuiltIn_raise##exceptionID(RecyclableObject *function, CallInfo callInfo, ...) \
  384. { \
  385. EngineInterfaceObject_CommonFunctionProlog(function, callInfo); \
  386. \
  387. if(args.Info.Count < 2 || !VarIs<JavascriptString>(args.Values[1])) \
  388. { \
  389. Assert(false); \
  390. JavascriptError::Throw##exceptionType(scriptContext, JSERR_##exceptionID); \
  391. } \
  392. JavascriptError::Throw##exceptionType##Var(scriptContext, JSERR_##exceptionID, VarTo<JavascriptString>(args.Values[1])->GetSz()); \
  393. }
  394. #define BuiltInRaiseException2(exceptionType, exceptionID) \
  395. Var EngineInterfaceObject::Entry_BuiltIn_raise##exceptionID(RecyclableObject *function, CallInfo callInfo, ...) \
  396. { \
  397. EngineInterfaceObject_CommonFunctionProlog(function, callInfo); \
  398. \
  399. if(args.Info.Count < 3 || !VarIs<JavascriptString>(args.Values[1]) || !VarIs<JavascriptString>(args.Values[2])) \
  400. { \
  401. Assert(false); \
  402. JavascriptError::Throw##exceptionType(scriptContext, JSERR_##exceptionID); \
  403. } \
  404. JavascriptError::Throw##exceptionType##Var(scriptContext, JSERR_##exceptionID, VarTo<JavascriptString>(args.Values[1])->GetSz(), VarTo<JavascriptString>(args.Values[2])->GetSz()); \
  405. }
  406. #define BuiltInRaiseException3(exceptionType, exceptionID) \
  407. Var EngineInterfaceObject::Entry_BuiltIn_raise##exceptionID##_3(RecyclableObject *function, CallInfo callInfo, ...) \
  408. { \
  409. EngineInterfaceObject_CommonFunctionProlog(function, callInfo); \
  410. \
  411. if(args.Info.Count < 4 || !VarIs<JavascriptString>(args.Values[1]) || !VarIs<JavascriptString>(args.Values[2]) || !VarIs<JavascriptString>(args.Values[3])) \
  412. { \
  413. Assert(false); \
  414. JavascriptError::Throw##exceptionType(scriptContext, JSERR_##exceptionID); \
  415. } \
  416. JavascriptError::Throw##exceptionType##Var(scriptContext, JSERR_##exceptionID, VarTo<JavascriptString>(args.Values[1])->GetSz(), VarTo<JavascriptString>(args.Values[2])->GetSz(), VarTo<JavascriptString>(args.Values[3])->GetSz()); \
  417. }
  418. #include "EngineInterfaceObjectBuiltIns.h"
  419. }
  420. #endif // ENABLE_INTL_OBJECT || ENABLE_JS_BUILTINS