| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #include "RuntimeLibraryPch.h"
- #ifndef USING_PAL_STDLIB
- #include <strsafe.h>
- #endif
- #include "ByteCode/ByteCodeApi.h"
- #include "Exceptions/EvalDisabledException.h"
- #include "Types/PropertyIndexRanges.h"
- #include "Types/SimpleDictionaryPropertyDescriptor.h"
- #include "Types/SimpleDictionaryTypeHandler.h"
- using namespace Js;
- GlobalObject * GlobalObject::New(ScriptContext * scriptContext)
- {
- SimpleDictionaryTypeHandler* globalTypeHandler = SimpleDictionaryTypeHandler::New(
- scriptContext->GetRecycler(), InitialCapacity, InlineSlotCapacity, sizeof(Js::GlobalObject));
- DynamicType* globalType = DynamicType::New(
- scriptContext, TypeIds_GlobalObject, nullptr, nullptr, globalTypeHandler);
- GlobalObject* globalObject = RecyclerNewPlus(scriptContext->GetRecycler(),
- sizeof(Var) * InlineSlotCapacity, GlobalObject, globalType, scriptContext);
- #if ENABLE_FIXED_FIELDS
- globalTypeHandler->SetSingletonInstanceIfNeeded(scriptContext->GetRecycler()->CreateWeakReferenceHandle<DynamicObject>(globalObject));
- #endif
- return globalObject;
- }
- GlobalObject::GlobalObject(DynamicType * type, ScriptContext* scriptContext) :
- RootObjectBase(type, scriptContext),
- directHostObject(nullptr),
- secureDirectHostObject(nullptr),
- EvalHelper(&GlobalObject::DefaultEvalHelper),
- reservedProperties(nullptr)
- {
- }
- void GlobalObject::Initialize(ScriptContext * scriptContext)
- {
- Assert(type->javascriptLibrary == nullptr);
- Recycler * recycler = scriptContext->GetRecycler();
- JavascriptLibrary* localLibrary = RecyclerNewFinalized(recycler, JavascriptLibrary, this, recycler);
- scriptContext->SetLibrary(localLibrary);
- type->javascriptLibrary = localLibrary;
- scriptContext->InitializeCache();
- localLibrary->Initialize(scriptContext, this);
- library = localLibrary;
- }
- bool GlobalObject::Is(Var aValue)
- {
- return RecyclableObject::Is(aValue) && (RecyclableObject::UnsafeFromVar(aValue)->GetTypeId() == TypeIds_GlobalObject);
- }
- GlobalObject* GlobalObject::FromVar(Var aValue)
- {
- AssertOrFailFastMsg(Is(aValue), "Ensure var is actually a 'GlobalObject'");
- return static_cast<GlobalObject*>(aValue);
- }
- GlobalObject* GlobalObject::UnsafeFromVar(Var aValue)
- {
- AssertMsg(Is(aValue), "Ensure var is actually a 'GlobalObject'");
- return static_cast<GlobalObject*>(aValue);
- }
- HRESULT GlobalObject::SetDirectHostObject(RecyclableObject* hostObject, RecyclableObject* secureDirectHostObject)
- {
- HRESULT hr = S_OK;
- BEGIN_TRANSLATE_OOM_TO_HRESULT_NESTED
- {
- // In fastDOM scenario, we should use the host object to lookup the prototype.
- this->SetPrototype(library->GetNull());
- }
- END_TRANSLATE_OOM_TO_HRESULT(hr)
- this->directHostObject = hostObject;
- this->secureDirectHostObject = secureDirectHostObject;
- return hr;
- }
- RecyclableObject* GlobalObject::GetDirectHostObject()
- {
- return this->directHostObject;
- }
- RecyclableObject* GlobalObject::GetSecureDirectHostObject()
- {
- return this->secureDirectHostObject;
- }
- // Converts the global object into the object that should be used as the 'this' parameter.
- // In a non-hosted environment, the global object (this) is returned.
- // In a hosted environment, the host object is returned.
- Var GlobalObject::ToThis()
- {
- Var ret;
- // In fast DOM, we need to give user the secure version of host object
- if (secureDirectHostObject)
- {
- ret = secureDirectHostObject;
- }
- else if (hostObject)
- {
- // If the global object has the host object, use that as "this"
- ret = hostObject->GetHostDispatchVar();
- Assert(ret);
- }
- else
- {
- // Otherwise just use the global object
- ret = this;
- }
- return ret;
- }
- BOOL GlobalObject::ReserveGlobalProperty(PropertyId propertyId)
- {
- if (JavascriptConversion::PropertyQueryFlagsToBoolean(DynamicObject::HasPropertyQuery(propertyId, nullptr /*info*/)))
- {
- return false;
- }
- if (reservedProperties == nullptr)
- {
- Recycler* recycler = this->GetScriptContext()->GetRecycler();
- reservedProperties = RecyclerNew(recycler, ReservedPropertiesHashSet, recycler, 3);
- }
- reservedProperties->AddNew(propertyId);
- return true;
- }
- BOOL GlobalObject::IsReservedGlobalProperty(PropertyId propertyId)
- {
- return reservedProperties != nullptr && reservedProperties->Contains(propertyId);
- }
- #ifdef IR_VIEWER
- Var GlobalObject::EntryParseIR(RecyclableObject *function, CallInfo callInfo, ...)
- {
- //
- // retrieve arguments
- //
- RUNTIME_ARGUMENTS(args, callInfo);
- Js::Var codeVar = args[1]; // args[0] is (this)
- Js::JavascriptString *codeStringVar = nullptr;
- const char16 *source = nullptr;
- size_t sourceLength = 0;
- if (Js::JavascriptString::Is(codeVar))
- {
- codeStringVar = (Js::JavascriptString *)codeVar;
- source = codeStringVar->GetString();
- sourceLength = codeStringVar->GetLength();
- }
- else
- {
- AssertMsg(false, "The input to parseIR was not a string.");
- }
- //
- // collect arguments for eval
- //
- /* @see NativeCodeGenerator::CodeGen */
- ScriptContext *scriptContext = function->GetScriptContext();
- // used arbitrary defaults for these, but it seems to work
- ModuleID moduleID = 0;
- uint32 grfscr = 0;
- LPCOLESTR pszTitle = _u("");
- BOOL registerDocument = false;
- BOOL strictMode = true;
- return IRDumpEvalHelper(scriptContext, source, sourceLength, moduleID, grfscr,
- pszTitle, registerDocument, FALSE, strictMode);
- }
- // TODO remove when refactor
- Js::PropertyId GlobalObject::CreateProperty(Js::ScriptContext *scriptContext, const char16 *propertyName)
- {
- Js::PropertyRecord const *propertyRecord;
- scriptContext->GetOrAddPropertyRecord(propertyName, (int) wcslen(propertyName), &propertyRecord);
- Js::PropertyId propertyId = propertyRecord->GetPropertyId();
- return propertyId;
- }
- // TODO remove when refactor
- void GlobalObject::SetProperty(Js::DynamicObject *obj, const char16 *propertyName, Js::Var value)
- {
- const size_t len = wcslen(propertyName);
- if (!(len > 0))
- {
- return;
- }
- Js::PropertyId id = CreateProperty(obj->GetScriptContext(), propertyName);
- SetProperty(obj, id, value);
- }
- // TODO remove when refactor
- void GlobalObject::SetProperty(Js::DynamicObject *obj, Js::PropertyId id, Js::Var value)
- {
- if (value == NULL)
- {
- return;
- }
- Js::JavascriptOperators::SetProperty(obj, obj, id, value, obj->GetScriptContext());
- }
- Var GlobalObject::FunctionInfoObjectBuilder(ScriptContext *scriptContext, const char16 *file,
- const char16 *function, ULONG lineNum, ULONG colNum,
- uint functionId, Js::Utf8SourceInfo *utf8SrcInfo, Js::Var source)
- {
- Js::DynamicObject *fnInfoObj = scriptContext->GetLibrary()->CreateObject();
- // create javascript objects for properties
- Js::Var filenameString = Js::JavascriptString::NewCopyBuffer(file, wcslen(file), scriptContext);
- Js::Var funcnameString = Js::JavascriptString::NewCopyBuffer(function, wcslen(function), scriptContext);
- Js::Var lineNumber = Js::JavascriptNumber::ToVar((int64) lineNum, scriptContext);
- Js::Var colNumber = Js::JavascriptNumber::ToVar((int64) colNum, scriptContext);
- Js::Var functionIdNumberVar = Js::JavascriptNumber::ToVar(functionId, scriptContext);
- Js::Var utf8SourceInfoVar = Js::JavascriptNumber::ToVar((int32) utf8SrcInfo, scriptContext);
- // assign properties to function info object
- SetProperty(fnInfoObj, _u("filename"), filenameString);
- SetProperty(fnInfoObj, _u("function"), funcnameString);
- SetProperty(fnInfoObj, _u("line"), lineNumber);
- SetProperty(fnInfoObj, _u("col"), colNumber);
- SetProperty(fnInfoObj, _u("funcId"), functionIdNumberVar);
- SetProperty(fnInfoObj, _u("utf8SrcInfoPtr"), utf8SourceInfoVar);
- SetProperty(fnInfoObj, _u("source"), source);
- return fnInfoObj;
- }
- /**
- * Return a list of functions visible in the current ScriptContext.
- */
- Var GlobalObject::EntryFunctionList(RecyclableObject *function, CallInfo callInfo, ...)
- {
- // Note: the typedefs below help make the following code more readable
- // See: Js::ScriptContext::SourceList (declaration not visible from this file)
- typedef JsUtil::List<RecyclerWeakReference<Utf8SourceInfo>*, Recycler, false, Js::FreeListedRemovePolicy> SourceList;
- typedef RecyclerWeakReference<Js::Utf8SourceInfo> Utf8SourceInfoRef;
- ScriptContext *originalScriptContext = function->GetScriptContext();
- ThreadContext *threadContext = originalScriptContext->GetThreadContext();
- ScriptContext *scriptContext;
- int fnCount = 0;
- for (scriptContext = threadContext->GetScriptContextList();
- scriptContext;
- scriptContext = scriptContext->next)
- {
- if (scriptContext->IsClosed()) continue;
- //
- // get count of functions in all files in script context
- //
- SourceList *sourceList = scriptContext->GetSourceList();
- sourceList->Map([&fnCount](uint i, Utf8SourceInfoRef *sourceInfoWeakRef)
- {
- Js::Utf8SourceInfo *sourceInfo = sourceInfoWeakRef->Get();
- if (sourceInfo == nullptr || sourceInfo->GetIsLibraryCode()) // library code has no source, skip
- {
- return;
- }
- fnCount += sourceInfo->GetFunctionBodyCount();
- });
- }
- #ifdef ENABLE_IR_VIEWER_DBG_DUMP
- if (Js::Configuration::Global.flags.Verbose)
- {
- Output::Print(_u(">> There are %d total functions\n"), fnCount);
- Output::Flush();
- }
- #endif
- //
- // create a javascript array to hold info for all of the functions
- //
- Js::JavascriptArray *functionList = originalScriptContext->GetLibrary()->CreateArray(fnCount);
- int count = 0;
- for (scriptContext = threadContext->GetScriptContextList();
- scriptContext;
- scriptContext = scriptContext->next)
- {
- if (scriptContext->IsClosed()) continue;
- // if (scriptContext == originalScriptContext) continue; // uncomment to ignore the originalScriptContext
- SourceList *sourceList = scriptContext->GetSourceList();
- sourceList->Map([&fnCount, &count, functionList, scriptContext](uint i, Utf8SourceInfoRef *sourceInfoWeakRef)
- {
- Js::Utf8SourceInfo *sourceInfo = sourceInfoWeakRef->Get();
- if (sourceInfo == nullptr || sourceInfo->GetIsLibraryCode()) // library code has no source, skip
- {
- return;
- }
- const SRCINFO *srcInfo = sourceInfo->GetSrcInfo();
- SourceContextInfo *srcContextInfo = srcInfo->sourceContextInfo;
- //
- // get URL of source file
- //
- char16 filenameBuffer[128]; // hold dynamically built filename
- char16 const *srcFileUrl = NULL;
- if (!srcContextInfo->IsDynamic())
- {
- Assert(srcContextInfo->url != NULL);
- srcFileUrl = srcContextInfo->url;
- }
- else
- {
- StringCchPrintf(filenameBuffer, 128, _u("[dynamic(hash:%u)]"), srcContextInfo->hash);
- srcFileUrl = filenameBuffer;
- }
- sourceInfo->MapFunction([scriptContext, &count, functionList, srcFileUrl](Js::FunctionBody *functionBody)
- {
- char16 const *functionName = functionBody->GetExternalDisplayName();
- ULONG lineNum = functionBody->GetLineNumber();
- ULONG colNum = functionBody->GetColumnNumber();
- uint funcId = functionBody->GetLocalFunctionId();
- Js::Utf8SourceInfo *utf8SrcInfo = functionBody->GetUtf8SourceInfo();
- if (utf8SrcInfo == nullptr)
- {
- return;
- }
- Assert(utf8SrcInfo->FindFunction(funcId) == functionBody);
- BufferStringBuilder builder(functionBody->LengthInChars(), scriptContext);
- utf8::DecodeOptions options = utf8SrcInfo->IsCesu8() ? utf8::doAllowThreeByteSurrogates : utf8::doDefault;
- utf8::DecodeInto(builder.DangerousGetWritableBuffer(), functionBody->GetSource(), functionBody->LengthInChars(), options);
- Var cachedSourceString = builder.ToString();
- Js::Var obj = FunctionInfoObjectBuilder(scriptContext, srcFileUrl,
- functionName, lineNum, colNum, funcId, utf8SrcInfo, cachedSourceString);
- functionList->SetItem(count, obj, Js::PropertyOperationFlags::PropertyOperation_None);
- ++count;
- });
- });
- }
- #ifdef ENABLE_IR_VIEWER_DBG_DUMP
- if (Js::Configuration::Global.flags.Verbose)
- {
- Output::Print(_u(">> Returning from functionList()\n"));
- Output::Flush();
- }
- #endif
- return functionList;
- }
- /**
- * Return the parsed IR for the given function.
- */
- Var GlobalObject::EntryRejitFunction(RecyclableObject *function, CallInfo callInfo, ...)
- {
- #ifdef ENABLE_IR_VIEWER_DBG_DUMP
- if (Js::Configuration::Global.flags.Verbose)
- {
- Output::Print(_u(">> Entering rejitFunction()\n"));
- Output::Flush();
- }
- #endif
- //
- // retrieve and coerce arguments
- //
- RUNTIME_ARGUMENTS(args, callInfo); // args[0] is (callInfo)
- Js::Var jsVarUtf8SourceInfo = args[1];
- Js::Var jsVarFunctionId = args[2];
- #ifdef ENABLE_IR_VIEWER_DBG_DUMP
- if (Js::Configuration::Global.flags.Verbose)
- {
- Output::Print(_u("jsVarUtf8SourceInfo: %d (0x%08X)\n"), jsVarUtf8SourceInfo, jsVarUtf8SourceInfo);
- Output::Print(_u("jsVarFunctionId: %d (0x%08X)\n"), jsVarFunctionId, jsVarFunctionId);
- }
- #endif
- Js::JavascriptNumber *jsUtf8SourceInfoNumber = NULL;
- Js::JavascriptNumber *jsFunctionIdNumber = NULL;
- int32 utf8SourceInfoNumber = 0; // null
- int32 functionIdNumber = -1; // start with invalid function id
- // extract value of jsVarUtf8SourceInfo
- if (Js::TaggedInt::Is(jsVarUtf8SourceInfo))
- {
- utf8SourceInfoNumber = (int32)TaggedInt::ToInt64(jsVarUtf8SourceInfo); // REVIEW: just truncate?
- }
- else if (Js::JavascriptNumber::Is(jsVarUtf8SourceInfo))
- {
- jsUtf8SourceInfoNumber = (Js::JavascriptNumber *)jsVarUtf8SourceInfo;
- utf8SourceInfoNumber = (int32)JavascriptNumber::GetValue(jsUtf8SourceInfoNumber); // REVIEW: just truncate?
- }
- else
- {
- // should not reach here
- AssertMsg(false, "Failed to extract value for jsVarUtf8SourceInfo as either TaggedInt or JavascriptNumber.\n");
- }
- // extract value of jsVarFunctionId
- if (Js::TaggedInt::Is(jsVarFunctionId))
- {
- functionIdNumber = (int32)TaggedInt::ToInt64(jsVarFunctionId); // REVIEW: just truncate?
- }
- else if (Js::JavascriptNumber::Is(jsVarFunctionId))
- {
- jsFunctionIdNumber = (Js::JavascriptNumber *)jsVarFunctionId;
- functionIdNumber = (int32)JavascriptNumber::GetValue(jsFunctionIdNumber); // REVIEW: just truncate?
- }
- else
- {
- // should not reach here
- AssertMsg(false, "Failed to extract value for jsVarFunctionId as either TaggedInt or JavascriptNumber.\n");
- }
- #ifdef ENABLE_IR_VIEWER_DBG_DUMP
- if (Js::Configuration::Global.flags.Verbose)
- {
- Output::Print(_u("utf8SourceInfoNumber (value): %d (0x%08X)\n"), utf8SourceInfoNumber, utf8SourceInfoNumber);
- Output::Print(_u("jsVarFunctionId (value): %d (0x%08X)\n"), functionIdNumber, functionIdNumber);
- Output::Print(_u(">> Executing rejitFunction(%d, %d)\n"), utf8SourceInfoNumber, functionIdNumber);
- Output::Flush();
- }
- #endif
- //
- // recover functionBody
- //
- Js::Utf8SourceInfo *sourceInfo = (Js::Utf8SourceInfo *)(utf8SourceInfoNumber);
- if (sourceInfo == NULL)
- {
- return NULL;
- }
- Js::FunctionBody *functionBody = sourceInfo->FindFunction((Js::LocalFunctionId)functionIdNumber);
- //
- // rejit the function body
- //
- Js::ScriptContext *scriptContext = function->GetScriptContext();
- NativeCodeGenerator *nativeCodeGenerator = scriptContext->GetNativeCodeGenerator();
- if (!functionBody || !functionBody->GetByteCode())
- {
- return scriptContext->GetLibrary()->GetUndefined();
- }
- Js::Var retVal = RejitIRViewerFunction(nativeCodeGenerator, functionBody, scriptContext);
- //
- // return the parsed IR object
- //
- #ifdef ENABLE_IR_VIEWER_DBG_DUMP
- if (Js::Configuration::Global.flags.Verbose)
- {
- Output::Print(_u("rejitFunction - retVal: 0x%08X\n"), retVal);
- Output::Flush();
- }
- #endif
- return retVal;
- }
- #endif /* IR_VIEWER */
- Var GlobalObject::EntryEvalHelper(ScriptContext* scriptContext, RecyclableObject* function, Js::Arguments& args)
- {
- FrameDisplay* environment = (FrameDisplay*)&NullFrameDisplay;
- ModuleID moduleID = kmodGlobal;
- BOOL strictMode = FALSE;
- // TODO: Handle call from global scope, strict mode
- BOOL isIndirect = FALSE;
- if (args.IsDirectEvalCall())
- {
- // This was recognized as an eval call at compile time. The last one or two args are internal to us.
- // Argcount will be one of the following when called from global code
- // - eval("...") : argcount 3 : this, evalString, frameDisplay
- // - eval.call("..."): argcount 2 : this(which is string) , frameDisplay
- if (args.Info.Count >= 1)
- {
- environment = args.GetFrameDisplay();
- strictMode = environment->GetStrictMode();
- }
- }
- else
- {
- // This must be an indirect "eval" call that we didn't detect at compile time.
- // Pass null as the environment, which will force all lookups in the eval code
- // to use the root for the current module.
- // Also pass "null" for "this", which will force the callee to use the current module root.
- isIndirect = !PHASE_OFF1(Js::FastIndirectEvalPhase);
- }
- return GlobalObject::VEval(function->GetLibrary(), environment, moduleID, !!strictMode, !!isIndirect, args,
- /* isLibraryCode = */ false, /* registerDocument */ true, /*additionalGrfscr */ 0);
- }
- Var GlobalObject::EntryEvalRestrictedMode(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- RUNTIME_ARGUMENTS(args, callInfo);
- Assert(!(callInfo.Flags & CallFlags_New));
- JavascriptLibrary* library = function->GetLibrary();
- ScriptContext* scriptContext = library->GetScriptContext();
- scriptContext->CheckEvalRestriction();
- return EntryEvalHelper(scriptContext, function, args);
- }
- // This function is used to decipher eval function parameters and we don't want the stack arguments optimization by C++ compiler so turning off the optimization
- Var GlobalObject::EntryEval(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- RUNTIME_ARGUMENTS(args, callInfo);
- Assert(!(callInfo.Flags & CallFlags_New));
- JavascriptLibrary* library = function->GetLibrary();
- ScriptContext* scriptContext = library->GetScriptContext();
- return EntryEvalHelper(scriptContext, function, args);
- }
- Var GlobalObject::VEval(JavascriptLibrary* library, FrameDisplay* environment, ModuleID moduleID, bool strictMode, bool isIndirect,
- Arguments& args, bool isLibraryCode, bool registerDocument, uint32 additionalGrfscr, ScriptContext* debugEvalScriptContext)
- {
- Assert(library);
- ScriptContext* scriptContext = library->GetScriptContext();
- unsigned argCount = args.Info.Count;
- AssertMsg(argCount > 0, "Should always have implicit 'this'");
- bool doRegisterDocument = registerDocument & !isLibraryCode;
- Var varThis = library->GetUndefined();
- if (argCount < 2)
- {
- return library->GetUndefined();
- }
- Var evalArg = args[1];
- if (!JavascriptString::Is(evalArg))
- {
- // "If x is not a string value, return x."
- return evalArg;
- }
- #ifdef ENABLE_SCRIPT_DEBUGGING
- // It might happen that no script parsed on this context (scriptContext) till now,
- // so this Eval acts as the first source compile for scriptContext, transition to debugMode as needed
- scriptContext->TransitionToDebugModeIfFirstSource(/* utf8SourceInfo = */ nullptr);
- #endif
- ScriptFunction *pfuncScript = nullptr;
- JavascriptString *argString = JavascriptString::FromVar(evalArg);
- char16 const * sourceString = argString->GetSz();
- charcount_t sourceLen = argString->GetLength();
- FastEvalMapString key(sourceString, sourceLen, moduleID, strictMode, isLibraryCode);
- // PropertyString's buffer references to PropertyRecord's inline buffer, if both PropertyString and PropertyRecord are collected
- // we'll leave the PropertyRecord's interior buffer pointer in the EvalMap. So do not use evalmap if we are evaluating PropertyString
- bool useEvalMap = !VirtualTableInfo<PropertyString>::HasVirtualTable(argString) && debugEvalScriptContext == nullptr; // Don't use the cache in case of debugEval
-
- bool found = useEvalMap && scriptContext->IsInEvalMap(key, isIndirect, &pfuncScript);
- if (!found || (!isIndirect && pfuncScript->GetEnvironment() != &NullFrameDisplay))
- {
- uint32 grfscr = additionalGrfscr | fscrReturnExpression | fscrEval | fscrEvalCode | fscrGlobalCode;
- if (isLibraryCode)
- {
- grfscr |= fscrIsLibraryCode;
- }
- if (!(grfscr & fscrConsoleScopeEval))
- {
- grfscr |= fscrCanDeferFncParse;
- }
- pfuncScript = library->GetGlobalObject()->EvalHelper(scriptContext, argString->GetSz(), argString->GetLength(), moduleID,
- grfscr, Constants::EvalCode, doRegisterDocument, isIndirect, strictMode);
- if (debugEvalScriptContext != nullptr && CrossSite::NeedMarshalVar(pfuncScript, debugEvalScriptContext))
- {
- // This is console scope scenario. DebugEval script context is on the top of the stack. But we are going
- // to execute the user script from target script context. In order to fix the script context stack we
- // need to marshall the function object.
- pfuncScript = ScriptFunction::FromVar(CrossSite::MarshalVar(debugEvalScriptContext, pfuncScript));
- }
- if (useEvalMap && !found)
- {
- scriptContext->AddToEvalMap(key, isIndirect, pfuncScript);
- }
- }
- #ifdef ENABLE_DEBUG_CONFIG_OPTIONS
- else
- {
- Js::Utf8SourceInfo* utf8SourceInfo = pfuncScript->GetFunctionBody()->GetUtf8SourceInfo();
- if (scriptContext->IsScriptContextInDebugMode() && !utf8SourceInfo->GetIsLibraryCode() && !utf8SourceInfo->IsInDebugMode())
- {
- // Identifying if any non library function escaped for not being in debug mode.
- Throw::FatalInternalError();
- }
- }
- #endif
- #if ENABLE_TTD
- //
- //TODO: We may (probably?) want to use the debugger source rundown functionality here instead
- //
- if(!isLibraryCode && pfuncScript != nullptr && (scriptContext->IsTTDRecordModeEnabled() || scriptContext->ShouldPerformReplayAction()))
- {
- //Make sure we have the body and text information available
- FunctionBody* globalBody = TTD::JsSupport::ForceAndGetFunctionBody(pfuncScript->GetParseableFunctionInfo());
- if(!scriptContext->TTDContextInfo->IsBodyAlreadyLoadedAtTopLevel(globalBody))
- {
- uint32 bodyIdCtr = 0;
- if(scriptContext->IsTTDRecordModeEnabled())
- {
- const TTD::NSSnapValues::TopLevelEvalFunctionBodyResolveInfo* tbfi = scriptContext->GetThreadContext()->TTDLog->AddEvalFunction(globalBody, moduleID, sourceString, sourceLen, additionalGrfscr, registerDocument, isIndirect, strictMode);
- //We always want to register the top-level load but we don't always need to log the event
- if(scriptContext->ShouldPerformRecordAction())
- {
- scriptContext->GetThreadContext()->TTDLog->RecordTopLevelCodeAction(tbfi->TopLevelBase.TopLevelBodyCtr);
- }
- bodyIdCtr = tbfi->TopLevelBase.TopLevelBodyCtr;
- }
- if(scriptContext->ShouldPerformReplayAction())
- {
- bodyIdCtr = scriptContext->GetThreadContext()->TTDLog->ReplayTopLevelCodeAction();
- }
- //walk global body to (1) add functions to pin set (2) build parent map
- scriptContext->TTDContextInfo->ProcessFunctionBodyOnLoad(globalBody, nullptr);
- scriptContext->TTDContextInfo->RegisterEvalScript(globalBody, bodyIdCtr);
- if(scriptContext->ShouldPerformRecordOrReplayAction())
- {
- globalBody->GetUtf8SourceInfo()->SetSourceInfoForDebugReplay_TTD(bodyIdCtr);
- }
- if(scriptContext->ShouldPerformReplayDebuggerAction())
- {
- scriptContext->GetThreadContext()->TTDExecutionInfo->ProcessScriptLoad(scriptContext, bodyIdCtr, globalBody, globalBody->GetUtf8SourceInfo(), nullptr);
- }
- }
- }
- #endif
- //We shouldn't be serializing eval functions; unless with -ForceSerialized flag
- if (CONFIG_FLAG(ForceSerialized)) {
- pfuncScript->GetFunctionProxy()->EnsureDeserialized();
- }
- if (pfuncScript->GetFunctionBody()->GetHasThis())
- {
- // The eval expression refers to "this"
- if (args.Info.Flags & CallFlags_ExtraArg)
- {
- JavascriptFunction* pfuncCaller = nullptr;
- // If we are non-hidden call to eval then look for the "this" object in the frame display if the caller is a lambda else get "this" from the caller's frame.
- bool successful = false;
- if (JavascriptStackWalker::GetCaller(&pfuncCaller, scriptContext))
- {
- FunctionInfo* functionInfo = pfuncCaller->GetFunctionInfo();
- if (functionInfo != nullptr && (functionInfo->IsLambda() || functionInfo->IsClassConstructor()))
- {
- Var defaultInstance = (moduleID == kmodGlobal) ? JavascriptOperators::OP_LdRoot(scriptContext)->ToThis() : (Var)JavascriptOperators::GetModuleRoot(moduleID, scriptContext);
- varThis = JavascriptOperators::OP_GetThisScoped(environment, defaultInstance, scriptContext);
- UpdateThisForEval(varThis, moduleID, scriptContext, strictMode);
- successful = true;
- }
- }
- if (!successful)
- {
- JavascriptStackWalker::GetThis(&varThis, moduleID, scriptContext);
- UpdateThisForEval(varThis, moduleID, scriptContext, strictMode);
- }
- }
- else
- {
- // The expression, which refers to "this", is evaluated by an indirect eval.
- // Set "this" to the current module root.
- varThis = JavascriptOperators::OP_GetThis(scriptContext->GetLibrary()->GetUndefined(), moduleID, scriptContext);
- }
- }
- if (pfuncScript->HasSuperReference())
- {
- // Indirect evals cannot have a super reference.
- if (!(args.Info.Flags & CallFlags_ExtraArg))
- {
- JavascriptError::ThrowSyntaxError(scriptContext, ERRSuperInIndirectEval, _u("super"));
- }
- }
- return library->GetGlobalObject()->ExecuteEvalParsedFunction(pfuncScript, environment, varThis, scriptContext);
- }
- void GlobalObject::UpdateThisForEval(Var &varThis, ModuleID moduleID, ScriptContext *scriptContext, BOOL strictMode)
- {
- if (strictMode)
- {
- varThis = JavascriptOperators::OP_StrictGetThis(varThis, scriptContext);
- }
- else
- {
- varThis = JavascriptOperators::OP_GetThisNoFastPath(varThis, moduleID, scriptContext);
- }
- }
- Var GlobalObject::ExecuteEvalParsedFunction(ScriptFunction *pfuncScript, FrameDisplay* environment, Var &varThis, ScriptContext *scriptContext)
- {
- Assert(pfuncScript != nullptr);
- pfuncScript->SetEnvironment(environment);
- //This function is supposed to be deserialized
- Assert(pfuncScript->GetFunctionBody());
- if (pfuncScript->GetFunctionBody()->GetFuncEscapes())
- {
- // Executing the eval causes the scope chain to escape.
- pfuncScript->InvalidateCachedScopeChain();
- }
- Var varResult = nullptr;
- BEGIN_SAFE_REENTRANT_CALL(scriptContext->GetThreadContext())
- {
- varResult = CALL_FUNCTION(scriptContext->GetThreadContext(), pfuncScript, CallInfo(CallFlags_Eval, 1), varThis);
- }
- END_SAFE_REENTRANT_CALL
- pfuncScript->SetEnvironment((FrameDisplay*)&NullFrameDisplay);
- return varResult;
- }
- #ifdef ENABLE_SCRIPT_PROFILING
- ScriptFunction* GlobalObject::ProfileModeEvalHelper(ScriptContext* scriptContext, const char16 *source, int sourceLength, ModuleID moduleID, uint32 grfscr, LPCOLESTR pszTitle, BOOL registerDocument, BOOL isIndirect, BOOL strictMode)
- {
- #if ENABLE_DEBUG_CONFIG_OPTIONS
- char16 debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
- #endif
- ScriptFunction *pEvalFunction = DefaultEvalHelper(scriptContext, source, sourceLength, moduleID, grfscr, pszTitle, registerDocument, isIndirect, strictMode);
- Assert(pEvalFunction);
- Js::FunctionProxy *proxy = pEvalFunction->GetFunctionProxy();
- Assert(proxy);
- OUTPUT_TRACE(Js::ScriptProfilerPhase, _u("GlobalObject::ProfileModeEvalHelper FunctionNumber : %s, Entrypoint : 0x%08X IsFunctionDefer : %d\n"),
- proxy->GetDebugNumberSet(debugStringBuffer), pEvalFunction->GetEntryPoint(), proxy->IsDeferred());
- if (proxy->IsDeferred())
- {
- // This could happen if the top level function is marked as deferred, we need to parse this to generate the script compile information (RegisterScript depends on that)
- Js::JavascriptFunction::DeferredParse(&pEvalFunction);
- proxy = pEvalFunction->GetFunctionProxy();
- }
- scriptContext->RegisterScript(proxy);
- return pEvalFunction;
- }
- #endif
- void GlobalObject::ValidateSyntax(ScriptContext* scriptContext, const char16 *source, int sourceLength, bool isGenerator, bool isAsync, void (Parser::*validateSyntax)())
- {
- Assert(sourceLength >= 0);
- HRESULT hr = S_OK;
- HRESULT hrParser = E_FAIL;
- CompileScriptException se;
- BEGIN_LEAVE_SCRIPT_INTERNAL(scriptContext);
- BEGIN_TRANSLATE_EXCEPTION_TO_HRESULT
- {
- ArenaAllocator tempAlloc(_u("ValidateSyntaxArena"), scriptContext->GetThreadContext()->GetPageAllocator(), Throw::OutOfMemory);
- size_t cchSource = sourceLength;
- size_t cbUtf8Buffer = UInt32Math::AddMul<1, 3>(sourceLength);
- LPUTF8 utf8Source = AnewArray(&tempAlloc, utf8char_t, cbUtf8Buffer);
- Assert(cchSource < MAXLONG);
- size_t cbSource = utf8::EncodeIntoAndNullTerminate(utf8Source, source, static_cast< charcount_t >(cchSource));
- utf8Source = reinterpret_cast< LPUTF8 >( tempAlloc.Realloc(utf8Source, cbUtf8Buffer, cbSource + 1) );
- Parser parser(scriptContext);
- hrParser = parser.ValidateSyntax(utf8Source, cbSource, isGenerator, isAsync, &se, validateSyntax);
- }
- END_TRANSLATE_EXCEPTION_TO_HRESULT(hr);
- END_LEAVE_SCRIPT_INTERNAL(scriptContext);
- if (FAILED(hr))
- {
- if (hr == E_OUTOFMEMORY)
- {
- JavascriptError::ThrowOutOfMemoryError(scriptContext);
- }
- if (hr == VBSERR_OutOfStack)
- {
- JavascriptError::ThrowStackOverflowError(scriptContext);
- }
- }
- if (!SUCCEEDED(hrParser))
- {
- hrParser = SCRIPT_E_RECORDED;
- EXCEPINFO ei;
- se.GetError(&hrParser, &ei);
- ErrorTypeEnum errorType;
- switch ((HRESULT)ei.scode)
- {
- #define RT_ERROR_MSG(name, errnum, str1, str2, jst, errorNumSource) \
- case name: \
- errorType = jst; \
- break;
- #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
- default:
- errorType = kjstSyntaxError;
- }
- JavascriptError::MapAndThrowError(scriptContext, ei.scode, errorType, &ei);
- }
- }
- ScriptFunction* GlobalObject::DefaultEvalHelper(ScriptContext* scriptContext, const char16 *source, int sourceLength, ModuleID moduleID, uint32 grfscr, LPCOLESTR pszTitle, BOOL registerDocument, BOOL isIndirect, BOOL strictMode)
- {
- Assert(sourceLength >= 0);
- AnalysisAssert(scriptContext);
- if (scriptContext->GetThreadContext()->EvalDisabled())
- {
- throw Js::EvalDisabledException();
- }
- #ifdef PROFILE_EXEC
- scriptContext->ProfileBegin(Js::EvalCompilePhase);
- #endif
- void * frameAddr = nullptr;
- GET_CURRENT_FRAME_ID(frameAddr);
- HRESULT hr = S_OK;
- HRESULT hrParser = S_OK;
- HRESULT hrCodeGen = S_OK;
- CompileScriptException se;
- Js::ParseableFunctionInfo * funcBody = NULL;
- BEGIN_LEAVE_SCRIPT_INTERNAL(scriptContext);
- BEGIN_TRANSLATE_EXCEPTION_TO_HRESULT
- {
- uint cchSource = sourceLength;
- size_t cbUtf8Buffer = UInt32Math::AddMul<1, 3>(cchSource);
- ArenaAllocator tempArena(_u("EvalHelperArena"), scriptContext->GetThreadContext()->GetPageAllocator(), Js::Throw::OutOfMemory);
- LPUTF8 utf8Source = AnewArray(&tempArena, utf8char_t, cbUtf8Buffer);
- Assert(cchSource < MAXLONG);
- size_t cbSource = utf8::EncodeIntoAndNullTerminate(utf8Source, source, static_cast< charcount_t >(cchSource));
- Assert(cbSource + 1 <= cbUtf8Buffer);
- SRCINFO const * pSrcInfo = scriptContext->GetModuleSrcInfo(moduleID);
- // Source Info objects are kept alive by the function bodies that are referencing it
- // The function body is created in GenerateByteCode but the source info isn't passed in, only the index
- // So we need to pin it here (TODO: Change GenerateByteCode to take in the sourceInfo itself)
- ENTER_PINNED_SCOPE(Utf8SourceInfo, sourceInfo);
- sourceInfo = Utf8SourceInfo::New(scriptContext, utf8Source, cchSource,
- cbSource, pSrcInfo, ((grfscr & fscrIsLibraryCode) != 0));
- Parser parser(scriptContext, strictMode);
- bool forceNoNative = false;
- ParseNodeProg * parseTree = nullptr;
- SourceContextInfo * sourceContextInfo = pSrcInfo->sourceContextInfo;
- ULONG deferParseThreshold = Parser::GetDeferralThreshold(sourceContextInfo->IsSourceProfileLoaded());
- if ((ULONG)sourceLength > deferParseThreshold && !PHASE_OFF1(Phase::DeferParsePhase))
- {
- // Defer function bodies declared inside large dynamic blocks.
- grfscr |= fscrWillDeferFncParse;
- }
- grfscr = grfscr | fscrDynamicCode;
- // fscrEval signifies direct eval in parser
- hrParser = parser.ParseCesu8Source(&parseTree, utf8Source, cbSource, isIndirect ? grfscr & ~fscrEval : grfscr, &se, &sourceContextInfo->nextLocalFunctionId,
- sourceContextInfo);
- sourceInfo->SetParseFlags(grfscr);
- if (SUCCEEDED(hrParser) && parseTree)
- {
- // This keeps function bodies generated by the byte code alive till we return
- Js::AutoDynamicCodeReference dynamicFunctionReference(scriptContext);
- Assert(cchSource < MAXLONG);
- uint sourceIndex = scriptContext->SaveSourceNoCopy(sourceInfo, cchSource, true);
- // Tell byte code gen not to attempt to interact with the caller's context if this is indirect eval.
- // TODO: Handle strict mode.
- if (isIndirect &&
- !strictMode &&
- !parseTree->GetStrictMode())
- {
- grfscr &= ~fscrEval;
- }
- hrCodeGen = GenerateByteCode(parseTree, grfscr, scriptContext, &funcBody, sourceIndex, forceNoNative, &parser, &se);
- sourceInfo->SetByteCodeGenerationFlags(grfscr);
- }
- LEAVE_PINNED_SCOPE();
- }
- END_TRANSLATE_EXCEPTION_TO_HRESULT(hr);
- END_LEAVE_SCRIPT_INTERNAL(scriptContext);
- #ifdef PROFILE_EXEC
- scriptContext->ProfileEnd(Js::EvalCompilePhase);
- #endif
- THROW_KNOWN_HRESULT_EXCEPTIONS(hr, scriptContext);
- if (!SUCCEEDED(hrParser))
- {
- JavascriptError::ThrowParserError(scriptContext, hrParser, &se);
- }
- else if (!SUCCEEDED(hrCodeGen))
- {
- Assert(hrCodeGen == SCRIPT_E_RECORDED);
- hrCodeGen = se.ei.scode;
- /*
- * VBSERR_OutOfStack is of type kjstError but we throw a (more specific) StackOverflowError when a hard stack
- * overflow occurs. To keep the behavior consistent I'm special casing it here.
- */
- se.Free();
- if (hrCodeGen == VBSERR_OutOfStack)
- {
- JavascriptError::ThrowStackOverflowError(scriptContext);
- }
- else if (hrCodeGen == JSERR_AsmJsCompileError)
- {
- // if asm.js compilation succeeded, retry with asm.js disabled
- grfscr |= fscrNoAsmJs;
- return DefaultEvalHelper(scriptContext, source, sourceLength, moduleID, grfscr, pszTitle, registerDocument, isIndirect, strictMode);
- }
- JavascriptError::MapAndThrowError(scriptContext, hrCodeGen);
- }
- else
- {
- Assert(funcBody != nullptr);
- funcBody->SetDisplayName(pszTitle);
- // Set the functionbody information to dynamic content PROFILER_SCRIPT_TYPE_DYNAMIC
- funcBody->SetIsTopLevel(true);
- // If not library code then let's find the parent, we may need to register this source if any exception happens later
- if ((grfscr & fscrIsLibraryCode) == 0)
- {
- // For parented eval get the caller's utf8SourceInfo
- JavascriptFunction* pfuncCaller = nullptr;
- if (JavascriptStackWalker::GetCaller(&pfuncCaller, scriptContext) && pfuncCaller && pfuncCaller->IsScriptFunction())
- {
- FunctionBody* parentFuncBody = pfuncCaller->GetFunctionBody();
- Utf8SourceInfo* parentUtf8SourceInfo = parentFuncBody->GetUtf8SourceInfo();
- Utf8SourceInfo* utf8SourceInfo = funcBody->GetUtf8SourceInfo();
- utf8SourceInfo->SetCallerUtf8SourceInfo(parentUtf8SourceInfo);
- }
- }
- if (registerDocument)
- {
- funcBody->RegisterFuncToDiag(scriptContext, pszTitle);
- funcBody = funcBody->GetParseableFunctionInfo(); // RegisterFunction may parse and update function body
- }
- ScriptFunction* pfuncScript = funcBody->IsCoroutine() ?
- scriptContext->GetLibrary()->CreateGeneratorVirtualScriptFunction(funcBody) :
- scriptContext->GetLibrary()->CreateScriptFunction(funcBody);
- return pfuncScript;
- }
- }
- #ifdef IR_VIEWER
- Var GlobalObject::IRDumpEvalHelper(ScriptContext* scriptContext, const char16 *source,
- int sourceLength, ModuleID moduleID, uint32 grfscr, LPCOLESTR pszTitle,
- BOOL registerDocument, BOOL isIndirect, BOOL strictMode)
- {
- // TODO (t-doilij) clean up this function, specifically used for IR dump (don't execute bytecode; potentially dangerous)
- Assert(sourceLength >= 0);
- if (scriptContext->GetThreadContext()->EvalDisabled())
- {
- throw Js::EvalDisabledException();
- }
- #ifdef PROFILE_EXEC
- scriptContext->ProfileBegin(Js::EvalCompilePhase);
- #endif
- void * frameAddr = nullptr;
- GET_CURRENT_FRAME_ID(frameAddr);
- HRESULT hr = S_OK;
- HRESULT hrParser = S_OK;
- HRESULT hrCodeGen = S_OK;
- CompileScriptException se;
- Js::ParseableFunctionInfo * funcBody = NULL;
- BEGIN_LEAVE_SCRIPT_INTERNAL(scriptContext);
- BEGIN_TRANSLATE_EXCEPTION_TO_HRESULT
- {
- size_t cchSource = sourceLength;
- size_t cbUtf8Buffer = UInt32Math::AddMul<1, 3>(sourceLength);
- ArenaAllocator tempArena(_u("EvalHelperArena"), scriptContext->GetThreadContext()->GetPageAllocator(), Js::Throw::OutOfMemory);
- LPUTF8 utf8Source = AnewArray(&tempArena, utf8char_t, cbUtf8Buffer);
- Assert(cchSource < MAXLONG);
- size_t cbSource = utf8::EncodeIntoAndNullTerminate(utf8Source, source, static_cast< charcount_t >(cchSource));
- Assert(cbSource + 1 <= cbUtf8Buffer);
- SRCINFO const * pSrcInfo = scriptContext->GetModuleSrcInfo(moduleID);
- // Source Info objects are kept alive by the function bodies that are referencing it
- // The function body is created in GenerateByteCode but the source info isn't passed in, only the index
- // So we need to pin it here (TODO: Change GenerateByteCode to take in the sourceInfo itself)
- ENTER_PINNED_SCOPE(Utf8SourceInfo, sourceInfo);
- sourceInfo = Utf8SourceInfo::New(scriptContext, utf8Source, cchSource, cbSource, pSrcInfo, ((grfscr & fscrIsLibraryCode) != 0));
- Parser parser(scriptContext, strictMode);
- bool forceNoNative = false;
- ParseNodePtr parseTree = nullptr;
- SourceContextInfo * sourceContextInfo = pSrcInfo->sourceContextInfo;
- grfscr = grfscr | fscrDynamicCode;
- hrParser = parser.ParseCesu8Source(&parseTree, utf8Source, cbSource, grfscr, &se, &sourceContextInfo->nextLocalFunctionId,
- sourceContextInfo);
- sourceInfo->SetParseFlags(grfscr);
- if (SUCCEEDED(hrParser) && parseTree)
- {
- // This keeps function bodies generated by the byte code alive till we return
- Js::AutoDynamicCodeReference dynamicFunctionReference(scriptContext);
- Assert(cchSource < MAXLONG);
- uint sourceIndex = scriptContext->SaveSourceNoCopy(sourceInfo, cchSource, true);
- grfscr = grfscr | fscrIrDumpEnable;
- hrCodeGen = GenerateByteCode(parseTree, grfscr, scriptContext, &funcBody, sourceIndex, forceNoNative, &parser, &se);
- sourceInfo->SetByteCodeGenerationFlags(grfscr);
- }
- LEAVE_PINNED_SCOPE();
- }
- END_TRANSLATE_EXCEPTION_TO_HRESULT(hr);
- END_LEAVE_SCRIPT_INTERNAL(scriptContext);
- #ifdef PROFILE_EXEC
- scriptContext->ProfileEnd(Js::EvalCompilePhase);
- #endif
- THROW_KNOWN_HRESULT_EXCEPTIONS(hr);
- if (!SUCCEEDED(hrParser))
- {
- hrParser = SCRIPT_E_RECORDED;
- EXCEPINFO ei;
- se.GetError(&hrParser, &ei);
- ErrorTypeEnum errorType;
- switch ((HRESULT)ei.scode)
- {
- #define RT_ERROR_MSG(name, errnum, str1, str2, jst, errorNumSource) \
- case name: \
- errorType = jst; \
- break;
- #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
- default:
- errorType = kjstSyntaxError;
- }
- JavascriptError::MapAndThrowError(scriptContext, ei.scode, errorType, &ei);
- }
- else if (!SUCCEEDED(hrCodeGen))
- {
- Assert(hrCodeGen == SCRIPT_E_RECORDED);
- hrCodeGen = se.ei.scode;
- /*
- * VBSERR_OutOfStack is of type kjstError but we throw a (more specific) StackOverflowError when a hard stack
- * overflow occurs. To keep the behavior consistent I'm special casing it here.
- */
- se.Free();
- if (hrCodeGen == VBSERR_OutOfStack)
- {
- JavascriptError::ThrowStackOverflowError(scriptContext);
- }
- JavascriptError::MapAndThrowError(scriptContext, hrCodeGen);
- }
- else
- {
- Assert(funcBody != nullptr);
- funcBody->SetDisplayName(pszTitle);
- // Set the functionbody information to dynamic content PROFILER_SCRIPT_TYPE_DYNAMIC
- funcBody->SetIsTopLevel(true);
- if (registerDocument)
- {
- funcBody->RegisterFuncToDiag(scriptContext, pszTitle);
- funcBody = funcBody->GetParseableFunctionInfo(); // RegisterFunction may parse and update function body
- }
- NativeCodeGenerator *nativeCodeGenerator = scriptContext->GetNativeCodeGenerator();
- Js::FunctionBody *functionBody = funcBody->GetFunctionBody(); // funcBody is ParseableFunctionInfo
- if (!functionBody || !functionBody->GetByteCode())
- {
- return scriptContext->GetLibrary()->GetUndefined();
- }
- Js::Var retVal = RejitIRViewerFunction(nativeCodeGenerator, functionBody, scriptContext);
- return retVal;
- }
- }
- #endif /* IR_VIEWER */
- Var GlobalObject::EntryParseInt(RecyclableObject* function, CallInfo callInfo, ...)
- {
- JIT_HELPER_REENTRANT_HEADER(GlobalObject_ParseInt);
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- Assert(!(callInfo.Flags & CallFlags_New));
- AssertMsg(args.Info.Count > 0, "Should always have implicit 'this'");
- JavascriptString *str;
- int radix = 0;
- if(args.Info.Count < 2)
- {
- // We're really converting "undefined" here, but "undefined" produces
- // NaN, so just return that directly.
- return JavascriptNumber::ToVarNoCheck(JavascriptNumber::NaN, scriptContext);
- }
- // Short cut for numbers and radix 10
- if (((args.Info.Count == 2) ||
- (TaggedInt::Is(args[2]) && TaggedInt::ToInt32(args[2]) == 10) ||
- (JavascriptNumber::Is(args[2]) && JavascriptNumber::GetValue(args[2]) == 10)))
- {
- if (TaggedInt::Is(args[1]))
- {
- return args[1];
- }
- if (JavascriptNumber::Is(args[1]))
- {
- double value = JavascriptNumber::GetValue(args[1]);
- // make sure we are in the ranges that don't have exponential notation.
- double absValue = Math::Abs(value);
- if (absValue < 1.0e21 && absValue >= 1e-5)
- {
- double result;
- #pragma prefast(suppress:6031, "We don't care about the fraction part")
- ::modf(value, &result);
- return JavascriptNumber::ToVarIntCheck(result, scriptContext);
- }
- }
- }
- // convert input to a string
- if (JavascriptString::Is(args[1]))
- {
- str = JavascriptString::FromVar(args[1]);
- }
- else
- {
- str = JavascriptConversion::ToString(args[1], scriptContext);
- }
- if(args.Info.Count > 2)
- {
- // retrieve the radix
- // TODO : verify for ES5 : radix is 10 when undefined or 0, except when it starts with 0x when it is 16.
- radix = JavascriptConversion::ToInt32(args[2], scriptContext);
- if(radix < 0 || radix == 1 || radix > 36)
- {
- //illegal, return NaN
- return JavascriptNumber::ToVarNoCheck(JavascriptNumber::NaN, scriptContext);
- }
- }
- Var result = str->ToInteger(radix);
- return result;
- JIT_HELPER_END(GlobalObject_ParseInt);
- }
- Var GlobalObject::EntryParseFloat(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- Assert(!(callInfo.Flags & CallFlags_New));
- AssertMsg(args.Info.Count > 0, "Should always have implicit 'this'");
- double result = 0;
- ENTER_PINNED_SCOPE(JavascriptString, str);
- if(args.Info.Count < 2)
- {
- // We're really converting "undefined" here, but "undefined" produces
- // NaN, so just return that directly.
- return JavascriptNumber::ToVarNoCheck(JavascriptNumber::NaN, scriptContext);
- }
- // Short cut for numbers
- if (TaggedInt::Is(args[1]))
- {
- return args[1];
- }
- if(JavascriptNumber::Is_NoTaggedIntCheck(args[1]))
- {
- // If the value is negative zero, return positive zero. Since the parameter type is string, -0 would first be
- // converted to the string "0", then parsed to result in positive zero.
- return
- JavascriptNumber::IsNegZero(JavascriptNumber::GetValue(args[1])) ?
- TaggedInt::ToVarUnchecked(0) :
- args[1];
- }
- // convert input to a string
- if (JavascriptString::Is(args[1]))
- {
- str = JavascriptString::FromVar(args[1]);
- }
- else
- {
- str = JavascriptConversion::ToString(args[1], scriptContext);
- }
- // skip preceding whitespace
- const char16 *pch = scriptContext->GetCharClassifier()->SkipWhiteSpace(str->GetSz());
- // perform the string -> float conversion
- result = NumberUtilities::StrToDbl(pch, &pch, scriptContext);
- LEAVE_PINNED_SCOPE(); // str
- return JavascriptNumber::ToVarNoCheck(result, scriptContext);
- }
- Var GlobalObject::EntryIsNaN(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- Assert(!(callInfo.Flags & CallFlags_New));
- AssertMsg(args.Info.Count > 0, "Should always have implicit 'this'");
- if(args.Info.Count < 2)
- {
- return scriptContext->GetLibrary()->GetTrue();
- }
- return JavascriptBoolean::ToVar(
- JavascriptNumber::IsNan(JavascriptConversion::ToNumber(args[1],scriptContext)),
- scriptContext);
- }
- Var GlobalObject::EntryIsFinite(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- Assert(!(callInfo.Flags & CallFlags_New));
- AssertMsg(args.Info.Count > 0, "Should always have implicit 'this'");
- if(args.Info.Count < 2)
- {
- return scriptContext->GetLibrary()->GetFalse();
- }
- return JavascriptBoolean::ToVar(
- NumberUtilities::IsFinite(JavascriptConversion::ToNumber(args[1],scriptContext)),
- scriptContext);
- }
- Var GlobalObject::EntryDecodeURI(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- Assert(!(callInfo.Flags & CallFlags_New));
- AssertMsg(args.Info.Count > 0, "Should always have implicit 'this'");
- return UriHelper::DecodeCoreURI(scriptContext, args, UriHelper::URIReserved);
- }
- Var GlobalObject::EntryDecodeURIComponent(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- Assert(!(callInfo.Flags & CallFlags_New));
- AssertMsg(args.Info.Count > 0, "Should always have implicit 'this'");
- return UriHelper::DecodeCoreURI(scriptContext, args, UriHelper::URINone);
- }
- Var GlobalObject::EntryEncodeURI(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- Assert(!(callInfo.Flags & CallFlags_New));
- AssertMsg(args.Info.Count > 0, "Should always have implicit 'this'");
- return UriHelper::EncodeCoreURI(scriptContext, args, UriHelper::URIReserved | UriHelper::URIUnescaped);
- }
- Var GlobalObject::EntryEncodeURIComponent(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- Assert(!(callInfo.Flags & CallFlags_New));
- AssertMsg(args.Info.Count > 0, "Should always have implicit 'this'");
- return UriHelper::EncodeCoreURI(scriptContext, args, UriHelper::URIUnescaped);
- }
- //
- // Part of Appendix B of ES5 spec
- //
- // This is a bit field for the hex values: 00-29, 2C, 3A-3F, 5B-5E, 60, 7B-FF
- // These are the values escape encodes using the default mask (or mask >= 4)
- static const BYTE _grfbitEscape[] =
- {
- 0xFF, 0xFF, // 00 - 0F
- 0xFF, 0xFF, // 10 - 1F
- 0xFF, 0x13, // 20 - 2F
- 0x00, 0xFC, // 30 - 3F
- 0x00, 0x00, // 40 - 4F
- 0x00, 0x78, // 50 - 5F
- 0x01, 0x00, // 60 - 6F
- 0x00, 0xF8, // 70 - 7F
- 0xFF, 0xFF, // 80 - 8F
- 0xFF, 0xFF, // 90 - 9F
- 0xFF, 0xFF, // A0 - AF
- 0xFF, 0xFF, // B0 - BF
- 0xFF, 0xFF, // C0 - CF
- 0xFF, 0xFF, // D0 - DF
- 0xFF, 0xFF, // E0 - EF
- 0xFF, 0xFF, // F0 - FF
- };
- Var GlobalObject::EntryEscape(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- Assert(!(callInfo.Flags & CallFlags_New));
- if (args.Info.Count <= 1)
- {
- return scriptContext->GetLibrary()->GetUndefinedDisplayString();
- }
- CompoundString * bs = nullptr;
- ENTER_PINNED_SCOPE(JavascriptString, src);
- src = JavascriptConversion::ToString(args[1], scriptContext);
- bs = CompoundString::NewWithCharCapacity(src->GetLength(), scriptContext->GetLibrary());
- char16 chw;
- char16 * pchSrc;
- char16 * pchLim;
- const char _rgchHex[] = "0123456789ABCDEF";
- pchSrc = const_cast<char16 *>(src->GetString());
- pchLim = pchSrc + src->GetLength();
- while (pchSrc < pchLim)
- {
- chw = *pchSrc++;
- if (0 != (chw & 0xFF00))
- {
- bs->AppendChars(_u("%u"));
- bs->AppendChars(static_cast<char16>(_rgchHex[(chw >> 12) & 0x0F]));
- bs->AppendChars(static_cast<char16>(_rgchHex[(chw >> 8) & 0x0F]));
- bs->AppendChars(static_cast<char16>(_rgchHex[(chw >> 4) & 0x0F]));
- bs->AppendChars(static_cast<char16>(_rgchHex[chw & 0x0F]));
- }
- else if (_grfbitEscape[chw >> 3] & (1 << (chw & 7)))
- {
- // Escape the byte.
- bs->AppendChars(_u('%'));
- bs->AppendChars(static_cast<char16>(_rgchHex[chw >> 4]));
- bs->AppendChars(static_cast<char16>(_rgchHex[chw & 0x0F]));
- }
- else
- {
- bs->AppendChars(chw);
- }
- }
- LEAVE_PINNED_SCOPE(); // src
- return bs;
- }
- //
- // Part of Appendix B of ES5 spec
- //
- Var GlobalObject::EntryUnEscape(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- Assert(!(callInfo.Flags & CallFlags_New));
- if (args.Info.Count <= 1)
- {
- return scriptContext->GetLibrary()->GetUndefinedDisplayString();
- }
- char16 chw;
- char16 chT;
- char16 * pchSrc;
- char16 * pchLim;
- char16 * pchMin;
- CompoundString * bs = nullptr;
- ENTER_PINNED_SCOPE(JavascriptString, src);
- src = JavascriptConversion::ToString(args[1], scriptContext);
- bs = CompoundString::NewWithCharCapacity(src->GetLength(), scriptContext->GetLibrary());
- pchSrc = const_cast<char16 *>(src->GetString());
- pchLim = pchSrc + src->GetLength();
- while (pchSrc < pchLim)
- {
- if ('%' != (chT = *pchSrc++))
- {
- bs->AppendChars(chT);
- continue;
- }
- pchMin = pchSrc;
- chT = *pchSrc++;
- if ('u' != chT)
- {
- chw = 0;
- goto LTwoHexDigits;
- }
- // 4 hex digits.
- if ((chT = *pchSrc++ - '0') <= 9)
- chw = chT * 0x1000;
- else if ((chT -= 'A' - '0') <= 5 || (chT -= 'a' - 'A') <= 5)
- chw = (chT + 10) * 0x1000;
- else
- goto LHexError;
- if ((chT = *pchSrc++ - '0') <= 9)
- chw += chT * 0x0100;
- else if ((chT -= 'A' - '0') <= 5 || (chT -= 'a' - 'A') <= 5)
- chw += (chT + 10) * 0x0100;
- else
- goto LHexError;
- chT = *pchSrc++;
- LTwoHexDigits:
- if ((chT -= '0') <= 9)
- chw += chT * 0x0010;
- else if ((chT -= 'A' - '0') <= 5 || (chT -= 'a' - 'A') <= 5)
- chw += (chT + 10) * 0x0010;
- else
- goto LHexError;
- if ((chT = *pchSrc++ - '0') <= 9)
- chw += chT;
- else if ((chT -= 'A' - '0') <= 5 || (chT -= 'a' - 'A') <= 5)
- chw += chT + 10;
- else
- {
- LHexError:
- pchSrc = pchMin;
- chw = '%';
- }
- bs->AppendChars(chw);
- }
- LEAVE_PINNED_SCOPE(); // src
- return bs;
- }
- #if DBG
- void DebugClearStack()
- {
- char buffer[1024];
- memset(buffer, 0, sizeof(buffer));
- }
- #endif
- Var GlobalObject::EntryCollectGarbage(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- #if DBG_DUMP
- if (Js::Configuration::Global.flags.TraceWin8Allocations)
- {
- Output::Print(_u("MemoryTrace: GlobalObject::EntryCollectGarbage Invoke\n"));
- Output::Flush();
- }
- #endif
- #if DBG
- // Clear 1K of stack to avoid false positive in debug build.
- // Because we don't debug build don't stack pack
- DebugClearStack();
- #endif
- Assert(!(callInfo.Flags & CallFlags_New));
- ScriptContext* scriptContext = function->GetScriptContext();
- if (!scriptContext->GetConfig()->IsCollectGarbageEnabled()
- #ifdef ENABLE_PROJECTION
- && scriptContext->GetConfig()->GetHostType() != HostType::HostTypeApplication
- && scriptContext->GetConfig()->GetHostType() != HostType::HostTypeWebview
- #endif
- )
- {
- // We expose the CollectGarbage API with flag for compat reasons.
- // If CollectGarbage key is not enabled, and if the HostType is neither
- // HostType::HostTypeApplication nor HostType::HostTypeWebview,
- // then we do not trigger collection.
- return scriptContext->GetLibrary()->GetUndefined();
- }
- Recycler* recycler = scriptContext->GetRecycler();
- if (recycler)
- {
- #if DBG && defined(RECYCLER_DUMP_OBJECT_GRAPH)
- ARGUMENTS(args, callInfo);
- if (args.Info.Count > 1)
- {
- double value = JavascriptConversion::ToNumber(args[1], function->GetScriptContext());
- if (value == 1.0)
- {
- recycler->dumpObjectOnceOnCollect = true;
- }
- }
- #endif
- recycler->CollectNow<CollectNowDecommitNowExplicit>();
- }
- #if DBG_DUMP
- #ifdef ENABLE_PROJECTION
- scriptContext->GetThreadContext()->DumpProjectionContextMemoryStats(_u("Stats after GlobalObject::EntryCollectGarbage call"));
- #endif
- if (Js::Configuration::Global.flags.TraceWin8Allocations)
- {
- Output::Print(_u("MemoryTrace: GlobalObject::EntryCollectGarbage Exit\n"));
- Output::Flush();
- }
- #endif
- return scriptContext->GetLibrary()->GetUndefined();
- }
- #ifdef ENABLE_DEBUG_CONFIG_OPTIONS
- Var GlobalObject::EntryChWriteTraceEvent(RecyclableObject *function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- if (args.Info.Count < 2)
- {
- return function->GetScriptContext()->GetLibrary()->GetUndefined();
- }
- JS_ETW(EventWriteJSCRIPT_INTERNAL_GENERIC_EVENT(Js::JavascriptConversion::ToString(args[1], function->GetScriptContext())->GetSz()));
- return function->GetScriptContext()->GetLibrary()->GetUndefined();
- }
- #endif
- #if ENABLE_TTD
- //Log a string in the telemetry system (and print to the console)
- Var GlobalObject::EntryTelemetryLog(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- TTDAssert(args.Info.Count >= 2 && Js::JavascriptString::Is(args[1]), "Bad arguments!!!");
- Js::JavascriptString* jsString = Js::JavascriptString::FromVar(args[1]);
- bool doPrint = (args.Info.Count == 3) && Js::JavascriptBoolean::Is(args[2]) && (Js::JavascriptBoolean::FromVar(args[2])->GetValue());
- if(function->GetScriptContext()->ShouldPerformReplayAction())
- {
- function->GetScriptContext()->GetThreadContext()->TTDLog->ReplayTelemetryLogEvent(jsString);
- }
- if(function->GetScriptContext()->ShouldPerformRecordAction())
- {
- function->GetScriptContext()->GetThreadContext()->TTDLog->RecordTelemetryLogEvent(jsString, doPrint);
- }
- if(doPrint)
- {
- //
- //TODO: the host should give us a print callback which we can use here
- //
- Output::Print(_u("%ls\n"), jsString->GetSz());
- fflush(stdout);
- }
- return function->GetScriptContext()->GetLibrary()->GetUndefined();
- }
- //Check if diagnostic trace writing is enabled
- Var GlobalObject::EntryEnabledDiagnosticsTrace(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- if (function->GetScriptContext()->ShouldPerformReplayAction())
- {
- TTD::EventLog* ttlog = function->GetScriptContext()->GetThreadContext()->TTDLog;
- bool isEnabled = ttlog->ReplayTTDFetchAutoTraceStatusLogEvent();
- return function->GetScriptContext()->GetLibrary()->CreateBoolean(isEnabled);
- }
- else if (function->GetScriptContext()->ShouldPerformRecordAction())
- {
- TTD::EventLog* ttlog = function->GetScriptContext()->GetThreadContext()->TTDLog;
- bool isEnabled = ttlog->GetAutoTraceEnabled();
- ttlog->RecordTTDFetchAutoTraceStatusEvent(isEnabled);
- return function->GetScriptContext()->GetLibrary()->CreateBoolean(isEnabled);
- }
- else
- {
- return function->GetScriptContext()->GetLibrary()->GetFalse();
- }
- }
- //Write a copy of the current TTD log to a specified location
- Var GlobalObject::EntryEmitTTDLog(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- Js::JavascriptLibrary* jslib = function->GetScriptContext()->GetLibrary();
- if(args.Info.Count != 2 || !Js::JavascriptString::Is(args[1]))
- {
- return jslib->GetFalse();
- }
- if(function->GetScriptContext()->ShouldPerformReplayAction())
- {
- function->GetScriptContext()->GetThreadContext()->TTDLog->ReplayEmitLogEvent();
- return jslib->GetTrue();
- }
- if(function->GetScriptContext()->ShouldPerformRecordAction())
- {
- Js::JavascriptString* jsString = Js::JavascriptString::FromVar(args[1]);
- function->GetScriptContext()->GetThreadContext()->TTDLog->RecordEmitLogEvent(jsString);
- return jslib->GetTrue();
- }
- return jslib->GetFalse();
- }
- #endif
- //Pattern match is unique to RuntimeObject. Only leading and trailing * are implemented
- //Example: *pat*tern* actually matches all the strings having pat*tern as substring.
- BOOL GlobalObject::MatchPatternHelper(JavascriptString *propertyName, JavascriptString *pattern, ScriptContext *scriptContext)
- {
- if (nullptr == propertyName || nullptr == pattern)
- {
- return FALSE;
- }
- charcount_t patternLength = pattern->GetLength();
- charcount_t nameLength = propertyName->GetLength();
- BOOL bStart;
- BOOL bEnd;
- if (0 == patternLength)
- {
- return TRUE; // empty pattern matches all
- }
- bStart = (_u('*') == pattern->GetItem(0));// Is there a start star?
- bEnd = (_u('*') == pattern->GetItem(patternLength - 1));// Is there an end star?
- //deal with the stars
- if (bStart || bEnd)
- {
- JavascriptString *subPattern;
- int idxStart = bStart? 1: 0;
- int idxEnd = bEnd? (patternLength - 1): patternLength;
- if (idxEnd <= idxStart)
- {
- return TRUE; //scenario double star **
- }
- //get a pattern which doesn't contain leading and trailing stars
- subPattern = JavascriptString::FromVar(JavascriptString::SubstringCore(pattern, idxStart, idxEnd - idxStart, scriptContext));
- uint index = JavascriptString::strstr(propertyName, subPattern, false);
- if (index == (uint)-1)
- {
- return FALSE;
- }
- if (FALSE == bStart)
- {
- return index == 0; //begin at the same place;
- }
- else if (FALSE == bEnd)
- {
- return (index + patternLength - 1) == (nameLength);
- }
- return TRUE;
- }
- else
- {
- //full match
- if (0 == JavascriptString::strcmp(propertyName, pattern))
- {
- return TRUE;
- }
- }
- return FALSE;
- }
- PropertyQueryFlags GlobalObject::HasPropertyQuery(PropertyId propertyId, _Inout_opt_ PropertyValueInfo* info)
- {
- return JavascriptConversion::BooleanToPropertyQueryFlags(JavascriptConversion::PropertyQueryFlagsToBoolean(DynamicObject::HasPropertyQuery(propertyId, info)) ||
- (this->directHostObject && JavascriptOperators::HasProperty(this->directHostObject, propertyId)) ||
- (this->hostObject && JavascriptOperators::HasProperty(this->hostObject, propertyId)));
- }
- BOOL GlobalObject::HasRootProperty(PropertyId propertyId)
- {
- return __super::HasRootProperty(propertyId) ||
- (this->directHostObject && JavascriptOperators::HasProperty(this->directHostObject, propertyId)) ||
- (this->hostObject && JavascriptOperators::HasProperty(this->hostObject, propertyId));
- }
- BOOL GlobalObject::HasOwnProperty(PropertyId propertyId)
- {
- return JavascriptConversion::PropertyQueryFlagsToBoolean(DynamicObject::HasPropertyQuery(propertyId, nullptr /*info*/)) ||
- (this->directHostObject && this->directHostObject->HasProperty(propertyId));
- }
- BOOL GlobalObject::HasOwnPropertyNoHostObject(PropertyId propertyId)
- {
- return JavascriptConversion::PropertyQueryFlagsToBoolean(DynamicObject::HasPropertyQuery(propertyId, nullptr /*info*/));
- }
- PropertyQueryFlags GlobalObject::GetPropertyQuery(Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext)
- {
- if (JavascriptConversion::PropertyQueryFlagsToBoolean(DynamicObject::GetPropertyQuery(originalInstance, propertyId, value, info, requestContext)))
- {
- return PropertyQueryFlags::Property_Found;
- }
- return JavascriptConversion::BooleanToPropertyQueryFlags((this->directHostObject && JavascriptOperators::GetProperty(this->directHostObject, propertyId, value, requestContext, info)) ||
- (this->hostObject && JavascriptOperators::GetProperty(this->hostObject, propertyId, value, requestContext, info)));
- }
- PropertyQueryFlags GlobalObject::GetPropertyQuery(Var originalInstance, JavascriptString* propertyNameString, Var* value, PropertyValueInfo* info, ScriptContext* requestContext)
- {
- PropertyRecord const* propertyRecord;
- this->GetScriptContext()->GetOrAddPropertyRecord(propertyNameString, &propertyRecord);
- return GlobalObject::GetPropertyQuery(originalInstance, propertyRecord->GetPropertyId(), value, info, requestContext);
- }
- BOOL GlobalObject::GetRootProperty(Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext)
- {
- if (__super::GetRootProperty(originalInstance, propertyId, value, info, requestContext))
- {
- return TRUE;
- }
- return (this->directHostObject && JavascriptOperators::GetProperty(this->directHostObject, propertyId, value, requestContext, info)) ||
- (this->hostObject && JavascriptOperators::GetProperty(this->hostObject, propertyId, value, requestContext, info));
- }
- _Check_return_ _Success_(return) BOOL GlobalObject::GetAccessors(PropertyId propertyId, _Outptr_result_maybenull_ Var* getter, _Outptr_result_maybenull_ Var* setter, ScriptContext* requestContext)
- {
- if (DynamicObject::GetAccessors(propertyId, getter, setter, requestContext))
- {
- return TRUE;
- }
- if (this->directHostObject)
- {
- return this->directHostObject->GetAccessors(propertyId, getter, setter, requestContext);
- }
- else if (this->hostObject)
- {
- return this->hostObject->GetAccessors(propertyId, getter, setter, requestContext);
- }
- return FALSE;
- }
- PropertyQueryFlags GlobalObject::GetPropertyReferenceQuery(Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info,
- ScriptContext* requestContext)
- {
- if (JavascriptConversion::PropertyQueryFlagsToBoolean(DynamicObject::GetPropertyReferenceQuery(originalInstance, propertyId, value, info, requestContext)))
- {
- return PropertyQueryFlags::Property_Found;
- }
- return JavascriptConversion::BooleanToPropertyQueryFlags((this->directHostObject && JavascriptOperators::GetPropertyReference(this->directHostObject, propertyId, value, requestContext, info)) ||
- (this->hostObject && JavascriptOperators::GetPropertyReference(this->hostObject, propertyId, value, requestContext, info)));
- }
- BOOL GlobalObject::GetRootPropertyReference(Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info,
- ScriptContext* requestContext)
- {
- if (__super::GetRootPropertyReference(originalInstance, propertyId, value, info, requestContext))
- {
- return true;
- }
- return (this->directHostObject && JavascriptOperators::GetPropertyReference(this->directHostObject, propertyId, value, requestContext, info)) ||
- (this->hostObject && JavascriptOperators::GetPropertyReference(this->hostObject, propertyId, value, requestContext, info));
- }
- BOOL GlobalObject::InitProperty(PropertyId propertyId, Var value, PropertyOperationFlags flags, PropertyValueInfo* info)
- {
- // var x = 10; variables declared with "var" at global scope
- // These cannot be deleted
- // In ES5 they are enumerable.
- PropertyAttributes attributes = PropertyWritable | PropertyEnumerable | PropertyDeclaredGlobal;
- flags = static_cast<PropertyOperationFlags>(flags | PropertyOperation_ThrowIfNotExtensible);
- return DynamicObject::SetPropertyWithAttributes(propertyId, value, attributes, info, flags);
- }
- BOOL GlobalObject::InitPropertyInEval(PropertyId propertyId, Var value, PropertyOperationFlags flags, PropertyValueInfo* info)
- {
- // This is var/function declared inside the 'eval'
- PropertyAttributes attributes = PropertyDynamicTypeDefaults | PropertyDeclaredGlobal;
- flags = static_cast<PropertyOperationFlags>(flags | PropertyOperation_ThrowIfNotExtensible);
- return DynamicObject::SetPropertyWithAttributes(propertyId, value, attributes, info, flags);
- }
- BOOL GlobalObject::InitPropertyScoped(PropertyId propertyId, Var value)
- {
- // var x = 10; variables declared with "var" inside "eval"
- // These CAN be deleted
- // in ES5 they are enumerable.
- //
- PropertyAttributes attributes = PropertyDynamicTypeDefaults | PropertyDeclaredGlobal;
- return DynamicObject::SetPropertyWithAttributes(propertyId, value, attributes, NULL, PropertyOperation_ThrowIfNotExtensible);
- }
- BOOL GlobalObject::InitFuncScoped(PropertyId propertyId, Var value)
- {
- // Var binding of functions declared in eval are elided when conflicting
- // with global scope let/const variables, so do not actually set the
- // property if it exists and is a let/const variable.
- bool noRedecl = false;
- if (!GetTypeHandler()->HasRootProperty(this, propertyId, &noRedecl) || !noRedecl)
- {
- //
- // var x = 10; variables declared with "var" inside "eval"
- // These CAN be deleted
- // in ES5 they are enumerable.
- PropertyAttributes attributes = PropertyDynamicTypeDefaults;
- DynamicObject::SetPropertyWithAttributes(propertyId, value, attributes, NULL, PropertyOperation_ThrowIfNotExtensible);
- }
- return true;
- }
- BOOL GlobalObject::SetExistingProperty(PropertyId propertyId, Var value, PropertyValueInfo* info, BOOL *setAttempted)
- {
- BOOL hasOwnProperty = JavascriptConversion::PropertyQueryFlagsToBoolean(DynamicObject::HasPropertyQuery(propertyId, nullptr /*info*/));
- BOOL hasProperty = JavascriptOperators::HasProperty(this->GetPrototype(), propertyId);
- *setAttempted = TRUE;
- if (this->directHostObject &&
- !hasOwnProperty &&
- !hasProperty &&
- this->directHostObject->HasProperty(propertyId))
- {
- // directHostObject->HasProperty returns true for things in global collections, however, they are not able to be set.
- // When we call SetProperty we'll return FALSE which means fall back to GlobalObject::SetProperty and shadow our collection
- // object rather than failing the set altogether. See bug Windows Out Of Band Releases 1144780 and linked bugs for details.
- if (this->directHostObject->SetProperty(propertyId, value, PropertyOperation_None, info))
- {
- return TRUE;
- }
- }
- else
- if (this->hostObject &&
- // Consider to revert to the commented line and ignore the prototype chain when direct host is on by default in IE9 mode
- !hasOwnProperty &&
- !hasProperty &&
- this->hostObject->HasProperty(propertyId))
- {
- return this->hostObject->SetProperty(propertyId, value, PropertyOperation_None, NULL);
- }
- if (hasOwnProperty || hasProperty)
- {
- return DynamicObject::SetProperty(propertyId, value, PropertyOperation_None, info);
- }
- *setAttempted = FALSE;
- return FALSE;
- }
- BOOL GlobalObject::SetExistingRootProperty(PropertyId propertyId, Var value, PropertyValueInfo* info, BOOL *setAttempted)
- {
- BOOL hasOwnProperty = __super::HasRootProperty(propertyId);
- BOOL hasProperty = JavascriptOperators::HasProperty(this->GetPrototype(), propertyId);
- *setAttempted = TRUE;
- if (this->directHostObject &&
- !hasOwnProperty &&
- !hasProperty &&
- this->directHostObject->HasProperty(propertyId))
- {
- // directHostObject->HasProperty returns true for things in global collections, however, they are not able to be set.
- // When we call SetProperty we'll return FALSE which means fall back to GlobalObject::SetProperty and shadow our collection
- // object rather than failing the set altogether. See bug Windows Out Of Band Releases 1144780 and linked bugs for details.
- if (this->directHostObject->SetProperty(propertyId, value, PropertyOperation_None, info))
- {
- return TRUE;
- }
- }
- else
- if (this->hostObject &&
- // Consider to revert to the commented line and ignore the prototype chain when direct host is on by default in IE9 mode
- !hasOwnProperty &&
- !hasProperty &&
- this->hostObject->HasProperty(propertyId))
- {
- return this->hostObject->SetProperty(propertyId, value, PropertyOperation_None, NULL);
- }
- if (hasOwnProperty || hasProperty)
- {
- return __super::SetRootProperty(propertyId, value, PropertyOperation_None, info);
- }
- *setAttempted = FALSE;
- return FALSE;
- }
- BOOL GlobalObject::SetProperty(PropertyId propertyId, Var value, PropertyOperationFlags flags, PropertyValueInfo* info)
- {
- Assert(!(flags & PropertyOperation_Root));
- BOOL setAttempted = TRUE;
- if (this->SetExistingProperty(propertyId, value, info, &setAttempted))
- {
- return TRUE;
- }
- //
- // Set was attempted. But the set operation returned false.
- // This happens, when the property is read only.
- // In those scenarios, we should be setting the property with default attributes
- //
- if (setAttempted)
- {
- return FALSE;
- }
- // Windows 8 430092: When we set a new property on globalObject there may be stale inline caches holding onto directHostObject->prototype
- // properties of the same name. So we need to clear proto caches in this scenario. But check for same property in directHostObject->prototype
- // chain is expensive (call to DOM) compared to just invalidating the cache.
- // If this blind invalidation is expensive in any scenario then we need to revisit this.
- // Another solution proposed was not to cache any of the properties of window->directHostObject->prototype.
- // if ((this->directHostObject && JavascriptOperators::HasProperty(this->directHostObject->GetPrototype(), propertyId)) ||
- // (this->hostObject && JavascriptOperators::HasProperty(this->hostObject->GetPrototype(), propertyId)))
- this->GetScriptContext()->InvalidateProtoCaches(propertyId);
- //
- // x = 10; implicit/phantom variable at global scope
- // These CAN be deleted
- // In ES5 they are enumerable.
- PropertyAttributes attributes = PropertyDynamicTypeDefaults;
- return DynamicObject::SetPropertyWithAttributes(propertyId, value, attributes, info);
- }
- BOOL GlobalObject::SetProperty(JavascriptString* propertyNameString, Var value, PropertyOperationFlags flags, PropertyValueInfo* info)
- {
- PropertyRecord const * propertyRecord;
- this->GetScriptContext()->GetOrAddPropertyRecord(propertyNameString, &propertyRecord);
- return GlobalObject::SetProperty(propertyRecord->GetPropertyId(), value, flags, info);
- }
- BOOL GlobalObject::SetRootProperty(PropertyId propertyId, Var value, PropertyOperationFlags flags, PropertyValueInfo* info)
- {
- Assert(flags & PropertyOperation_Root);
- BOOL setAttempted = TRUE;
- if (this->SetExistingRootProperty(propertyId, value, info, &setAttempted))
- {
- return TRUE;
- }
- //
- // Set was attempted. But the set operation returned false.
- // This happens, when the property is read only.
- // In those scenarios, we should be setting the property with default attributes
- //
- if (setAttempted)
- {
- return FALSE;
- }
- if (flags & PropertyOperation_StrictMode)
- {
- if (!GetScriptContext()->GetThreadContext()->RecordImplicitException())
- {
- return FALSE;
- }
- JavascriptError::ThrowReferenceError(GetScriptContext(), JSERR_RefErrorUndefVariable);
- }
- // Windows 8 430092: When we set a new property on globalObject there may be stale inline caches holding onto directHostObject->prototype
- // properties of the same name. So we need to clear proto caches in this scenario. But check for same property in directHostObject->prototype
- // chain is expensive (call to DOM) compared to just invalidating the cache.
- // If this blind invalidation is expensive in any scenario then we need to revisit this.
- // Another solution proposed was not to cache any of the properties of window->directHostObject->prototype.
- // if ((this->directHostObject && JavascriptOperators::HasProperty(this->directHostObject->GetPrototype(), propertyId)) ||
- // (this->hostObject && JavascriptOperators::HasProperty(this->hostObject->GetPrototype(), propertyId)))
- this->GetScriptContext()->InvalidateProtoCaches(propertyId);
- return __super::SetRootProperty(propertyId, value, flags, info);
- }
- BOOL GlobalObject::SetAccessors(PropertyId propertyId, Var getter, Var setter, PropertyOperationFlags flags)
- {
- if (DynamicObject::SetAccessors(propertyId, getter, setter, flags))
- {
- return TRUE;
- }
- if (this->directHostObject)
- {
- return this->directHostObject->SetAccessors(propertyId, getter, setter, flags);
- }
- if (this->hostObject)
- {
- return this->hostObject->SetAccessors(propertyId, getter, setter, flags);
- }
- return TRUE;
- }
- DescriptorFlags GlobalObject::GetSetter(PropertyId propertyId, Var* setterValue, PropertyValueInfo* info, ScriptContext* requestContext)
- {
- DescriptorFlags flags = DynamicObject::GetSetter(propertyId, setterValue, info, requestContext);
- if (flags == None)
- {
- if (this->directHostObject)
- {
- // We need to look up the prototype chain here.
- JavascriptOperators::CheckPrototypesForAccessorOrNonWritableProperty(this->directHostObject, propertyId, setterValue, &flags, info, requestContext);
- }
- else if (this->hostObject)
- {
- JavascriptOperators::CheckPrototypesForAccessorOrNonWritableProperty(this->hostObject, propertyId, setterValue, &flags, info, requestContext);
- }
- }
- return flags;
- }
- DescriptorFlags GlobalObject::GetSetter(JavascriptString* propertyNameString, Var* setterValue, PropertyValueInfo* info, ScriptContext* requestContext)
- {
- PropertyRecord const* propertyRecord;
- this->GetScriptContext()->GetOrAddPropertyRecord(propertyNameString, &propertyRecord);
- return GlobalObject::GetSetter(propertyRecord->GetPropertyId(), setterValue, info, requestContext);
- }
- DescriptorFlags GlobalObject::GetRootSetter(PropertyId propertyId, Var* setterValue, PropertyValueInfo* info, ScriptContext* requestContext)
- {
- DescriptorFlags flags = __super::GetRootSetter(propertyId, setterValue, info, requestContext);
- if (flags == None)
- {
- if (this->directHostObject)
- {
- // We need to look up the prototype chain here.
- JavascriptOperators::CheckPrototypesForAccessorOrNonWritableProperty(this->directHostObject, propertyId, setterValue, &flags, info, requestContext);
- }
- else if (this->hostObject)
- {
- JavascriptOperators::CheckPrototypesForAccessorOrNonWritableProperty(this->hostObject, propertyId, setterValue, &flags, info, requestContext);
- }
- }
- return flags;
- }
- DescriptorFlags GlobalObject::GetItemSetter(uint32 index, Var* setterValue, ScriptContext* requestContext)
- {
- DescriptorFlags flags = DynamicObject::GetItemSetter(index, setterValue, requestContext);
- if (flags == None)
- {
- if (this->directHostObject)
- {
- // We need to look up the prototype chain here.
- JavascriptOperators::CheckPrototypesForAccessorOrNonWritableItem(this->directHostObject, index, setterValue, &flags, requestContext);
- }
- else if (this->hostObject)
- {
- JavascriptOperators::CheckPrototypesForAccessorOrNonWritableItem(this->hostObject, index, setterValue, &flags, requestContext);
- }
- }
- return flags;
- }
- BOOL GlobalObject::DeleteProperty(PropertyId propertyId, PropertyOperationFlags flags)
- {
- if (JavascriptConversion::PropertyQueryFlagsToBoolean(__super::HasPropertyQuery(propertyId, nullptr /*info*/)))
- {
- return __super::DeleteProperty(propertyId, flags);
- }
- else if (this->directHostObject && this->directHostObject->HasProperty(propertyId))
- {
- return this->directHostObject->DeleteProperty(propertyId, flags);
- }
- else if (this->hostObject && this->hostObject->HasProperty(propertyId))
- {
- return this->hostObject->DeleteProperty(propertyId, flags);
- }
- // Non-existent property
- return TRUE;
- }
- BOOL GlobalObject::DeleteProperty(JavascriptString *propertyNameString, PropertyOperationFlags flags)
- {
- PropertyRecord const *propertyRecord = nullptr;
- if (JavascriptOperators::ShouldTryDeleteProperty(this, propertyNameString, &propertyRecord))
- {
- Assert(propertyRecord);
- return DeleteProperty(propertyRecord->GetPropertyId(), flags);
- }
- return TRUE;
- }
- BOOL GlobalObject::DeleteRootProperty(PropertyId propertyId, PropertyOperationFlags flags)
- {
- if (__super::HasRootProperty(propertyId))
- {
- return __super::DeleteRootProperty(propertyId, flags);
- }
- else if (this->directHostObject && this->directHostObject->HasProperty(propertyId))
- {
- return this->directHostObject->DeleteProperty(propertyId, flags);
- }
- else if (this->hostObject && this->hostObject->HasProperty(propertyId))
- {
- return this->hostObject->DeleteProperty(propertyId, flags);
- }
- // Non-existent property
- return TRUE;
- }
- PropertyQueryFlags GlobalObject::HasItemQuery(uint32 index)
- {
- return JavascriptConversion::BooleanToPropertyQueryFlags(JavascriptConversion::PropertyQueryFlagsToBoolean((DynamicObject::HasItemQuery(index)))
- || (this->directHostObject && JavascriptOperators::HasItem(this->directHostObject, index))
- || (this->hostObject && JavascriptOperators::HasItem(this->hostObject, index)));
- }
- BOOL GlobalObject::HasOwnItem(uint32 index)
- {
- return JavascriptConversion::PropertyQueryFlagsToBoolean(DynamicObject::HasItemQuery(index))
- || (this->directHostObject && this->directHostObject->HasItem(index));
- }
- PropertyQueryFlags GlobalObject::GetItemReferenceQuery(Var originalInstance, uint32 index, Var* value, ScriptContext* requestContext)
- {
- if (JavascriptConversion::PropertyQueryFlagsToBoolean(DynamicObject::GetItemReferenceQuery(originalInstance, index, value, requestContext)))
- {
- return PropertyQueryFlags::Property_Found;
- }
- return JavascriptConversion::BooleanToPropertyQueryFlags(
- (this->directHostObject && JavascriptConversion::PropertyQueryFlagsToBoolean(this->directHostObject->GetItemReferenceQuery(originalInstance, index, value, requestContext))) ||
- (this->hostObject && JavascriptConversion::PropertyQueryFlagsToBoolean(this->hostObject->GetItemReferenceQuery(originalInstance, index, value, requestContext))));
- }
- BOOL GlobalObject::SetItem(uint32 index, Var value, PropertyOperationFlags flags)
- {
- BOOL result = DynamicObject::SetItem(index, value, flags);
- return result;
- }
- PropertyQueryFlags GlobalObject::GetItemQuery(Var originalInstance, uint32 index, Var* value, ScriptContext* requestContext)
- {
- if (JavascriptConversion::PropertyQueryFlagsToBoolean(DynamicObject::GetItemQuery(originalInstance, index, value, requestContext)))
- {
- return PropertyQueryFlags::Property_Found;
- }
- return JavascriptConversion::BooleanToPropertyQueryFlags((this->directHostObject && this->directHostObject->GetItem(originalInstance, index, value, requestContext)) ||
- (this->hostObject && this->hostObject->GetItem(originalInstance, index, value, requestContext)));
- }
- BOOL GlobalObject::DeleteItem(uint32 index, PropertyOperationFlags flags)
- {
- if (DynamicObject::DeleteItem(index, flags))
- {
- return TRUE;
- }
- if (this->directHostObject)
- {
- return this->directHostObject->DeleteItem(index, flags);
- }
- if (this->hostObject)
- {
- return this->hostObject->DeleteItem(index, flags);
- }
- return FALSE;
- }
- BOOL GlobalObject::GetDiagValueString(StringBuilder<ArenaAllocator>* stringBuilder, ScriptContext* requestContext)
- {
- stringBuilder->AppendCppLiteral(_u("{...}"));
- return TRUE;
- }
- BOOL GlobalObject::GetDiagTypeString(StringBuilder<ArenaAllocator>* stringBuilder, ScriptContext* requestContext)
- {
- stringBuilder->AppendCppLiteral(_u("Object, (Global)"));
- return TRUE;
- }
- BOOL GlobalObject::StrictEquals(__in Js::Var other, __out BOOL* value, ScriptContext * requestContext)
- {
- if (this == other)
- {
- *value = TRUE;
- return TRUE;
- }
- else if (this->directHostObject)
- {
- return this->directHostObject->StrictEquals(other, value, requestContext);
- }
- else if (this->hostObject)
- {
- return this->hostObject->StrictEquals(other, value, requestContext);
- }
- *value = FALSE;
- return FALSE;
- }
- BOOL GlobalObject::Equals(__in Js::Var other, __out BOOL* value, ScriptContext * requestContext)
- {
- if (this == other)
- {
- *value = TRUE;
- return TRUE;
- }
- else if (this->directHostObject)
- {
- return this->directHostObject->Equals(other, value, requestContext);
- }
- else if (this->hostObject)
- {
- return this->hostObject->Equals(other, value, requestContext);
- }
- *value = FALSE;
- return TRUE;
- }
- #if ENABLE_TTD
- TTD::NSSnapObjects::SnapObjectType GlobalObject::GetSnapTag_TTD() const
- {
- return TTD::NSSnapObjects::SnapObjectType::SnapWellKnownObject;
- }
- void GlobalObject::ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc)
- {
- //
- //TODO: we assume that the global object is always set right (e.g., ignore the directHostObject and secureDirectHostObject values) we need to verify that this is ok and/or what to do about it
- //
- TTD::NSSnapObjects::StdExtractSetKindSpecificInfo<void*, TTD::NSSnapObjects::SnapObjectType::SnapWellKnownObject>(objData, nullptr);
- }
- #endif
|