| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305 |
- //-------------------------------------------------------------------------------------------------------
- // 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;
- }
- HRESULT GlobalObject::SetDirectHostObject(RecyclableObject* hostObject, RecyclableObject* secureDirectHostObject)
- {
- HRESULT hr = S_OK;
- this->directHostObject = hostObject;
- this->secureDirectHostObject = secureDirectHostObject;
- BEGIN_TRANSLATE_OOM_TO_HRESULT_NESTED
- {
- // In fastDOM scenario, we should use the host object to lookup the prototype.
- this->SetPrototype(library->GetNull());
- // Host can call to set the direct host object after the GlobalObject has been initialized but
- // before user script has run. (This happens even before the previous call to SetPrototype)
- // If that happens, we'll need to update the 'globalThis' property to point to the secure
- // host object so that we don't hand a reference to the bare GlobalObject out to user script.
- if (this->GetScriptContext()->GetConfig()->IsESGlobalThisEnabled())
- {
- this->SetProperty(PropertyIds::globalThis, this->ToThis(), PropertyOperation_None, nullptr);
- }
- }
- END_TRANSLATE_OOM_TO_HRESULT(hr)
- 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::VarIs<Js::JavascriptString>(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 (!VarIs<JavascriptString>(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 = VarTo<JavascriptString>(evalArg);
- char16 const * sourceString = argString->GetSz();
- charcount_t sourceLen = argString->GetLength();
- FastEvalMapString key(argString, 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 = VarTo<ScriptFunction>(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->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)
- {
- 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::MulAdd<3, 1>(sourceLength);
- LPUTF8 utf8Source = AnewArray(&tempAlloc, utf8char_t, cbUtf8Buffer);
- Assert(cchSource < MAXLONG);
- size_t cbSource = utf8::EncodeIntoAndNullTerminate<utf8::Utf8EncodingKind::Cesu8>(utf8Source, cbUtf8Buffer, 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;
- uint sourceIndex = Constants::InvalidSourceIndex;
- BEGIN_LEAVE_SCRIPT_INTERNAL(scriptContext);
- BEGIN_TRANSLATE_EXCEPTION_TO_HRESULT
- {
- uint cchSource = sourceLength;
- size_t cbUtf8Buffer = UInt32Math::MulAdd<3, 1>(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<utf8::Utf8EncodingKind::Cesu8>(utf8Source, cbUtf8Buffer, 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);
- 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 failed, retry with asm.js disabled
- grfscr |= fscrNoAsmJs;
- if (sourceIndex != Constants::InvalidSourceIndex)
- {
- // If we registered source, we should remove it or we will register another source info
- scriptContext->RemoveSource(sourceIndex);
- }
- 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 (VarIs<JavascriptString>(args[1]))
- {
- str = VarTo<JavascriptString>(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 (VarIs<JavascriptString>(args[1]))
- {
- str = VarTo<JavascriptString>(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();
- 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
- 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::VarIs<Js::JavascriptString>(args[1]), "Bad arguments!!!");
- Js::JavascriptString* jsString = Js::VarTo<Js::JavascriptString>(args[1]);
- bool doPrint = (args.Info.Count == 3) && Js::VarIs<Js::JavascriptBoolean>(args[2]) && (Js::VarTo<Js::JavascriptBoolean>(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::VarIs<Js::JavascriptString>(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::VarTo<Js::JavascriptString>(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 = VarTo<JavascriptString>(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
|