@@ -72,16 +72,38 @@ namespace Js
7272 return ;
7373 }
7474
75- FunctionBody * functionBody;
75+ this ->RegisterFunction (func, func->GetHostSourceContext (), title);
76+ }
77+
78+ void DebugContext::RegisterFunction (Js::ParseableFunctionInfo * func, DWORD_PTR dwDebugSourceContext, LPCWSTR title)
79+ {
80+ if (!this ->CanRegisterFunction ())
81+ {
82+ return ;
83+ }
84+
85+ FunctionBody * functionBody = nullptr ;
7686 if (func->IsDeferredParseFunction ())
7787 {
78- functionBody = func->Parse ();
88+ HRESULT hr = S_OK;
89+ Assert (!this ->scriptContext ->GetThreadContext ()->IsScriptActive ());
90+
91+ BEGIN_JS_RUNTIME_CALL_EX_AND_TRANSLATE_EXCEPTION_AND_ERROROBJECT_TO_HRESULT_NESTED (this ->scriptContext , false )
92+ {
93+ functionBody = func->Parse ();
94+ }
95+ END_JS_RUNTIME_CALL_AND_TRANSLATE_EXCEPTION_AND_ERROROBJECT_TO_HRESULT (hr);
96+
97+ if (FAILED (hr))
98+ {
99+ return ;
100+ }
79101 }
80102 else
81103 {
82104 functionBody = func->GetFunctionBody ();
83105 }
84- this ->RegisterFunction (functionBody, functionBody-> GetHostSourceContext () , title);
106+ this ->RegisterFunction (functionBody, dwDebugSourceContext , title);
85107 }
86108
87109 void DebugContext::RegisterFunction (Js::FunctionBody * functionBody, DWORD_PTR dwDebugSourceContext, LPCWSTR title)
@@ -123,7 +145,7 @@ namespace Js
123145 this ->scriptContext , shouldPerformSourceRundown, shouldReparseFunctions);
124146
125147 Js::TempArenaAllocatorObject *tempAllocator = nullptr ;
126- JsUtil::List<Js::FunctionBody *, ArenaAllocator >* pFunctionsToRegister = nullptr ;
148+ JsUtil::List<Js::FunctionInfo *, Recycler >* pFunctionsToRegister = nullptr ;
127149 JsUtil::List<Js::Utf8SourceInfo *, Recycler, false , Js::CopyRemovePolicy, RecyclerPointerComparer>* utf8SourceInfoList = nullptr ;
128150
129151 HRESULT hr = S_OK;
@@ -132,7 +154,6 @@ namespace Js
132154 BEGIN_TRANSLATE_OOM_TO_HRESULT_NESTED
133155 tempAllocator = threadContext->GetTemporaryAllocator (_u (" debuggerAlloc" ));
134156
135- pFunctionsToRegister = JsUtil::List<Js::FunctionBody*, ArenaAllocator>::New (tempAllocator->GetAllocator ());
136157 utf8SourceInfoList = JsUtil::List<Js::Utf8SourceInfo *, Recycler, false , Js::CopyRemovePolicy, RecyclerPointerComparer>::New (this ->scriptContext ->GetRecycler ());
137158
138159 this ->MapUTF8SourceInfoUntil ([&](Js::Utf8SourceInfo * sourceInfo) -> bool
@@ -197,9 +218,9 @@ namespace Js
197218 dwDebugHostSourceContext = this ->hostDebugContext ->GetHostSourceContext (sourceInfo);
198219 }
199220
200- this -> FetchTopLevelFunction ( pFunctionsToRegister, sourceInfo);
221+ pFunctionsToRegister = sourceInfo-> GetTopLevelFunctionInfoList ( );
201222
202- if (pFunctionsToRegister->Count () == 0 )
223+ if (pFunctionsToRegister == nullptr || pFunctionsToRegister ->Count () == 0 )
203224 {
204225 // This could happen if there are no functions to re-compile.
205226 return false ;
@@ -221,21 +242,20 @@ namespace Js
221242 return true ;
222243 }
223244
224- Js::FunctionBody* pFuncBody = pFunctionsToRegister->Item (i);
225- if (pFuncBody == nullptr )
245+ Js::FunctionInfo *functionInfo = pFunctionsToRegister->Item (i);
246+ if (functionInfo == nullptr )
226247 {
227248 continue ;
228249 }
229250
230251 if (shouldReparseFunctions)
231252 {
232-
233253 BEGIN_JS_RUNTIME_CALL_EX_AND_TRANSLATE_EXCEPTION_AND_ERROROBJECT_TO_HRESULT_NESTED (cachedScriptContext, false )
234254 {
235- pFuncBody ->Parse ();
255+ functionInfo-> GetParseableFunctionInfo () ->Parse ();
236256 // This is the first call to the function, ensure dynamic profile info
237257#if ENABLE_PROFILE_INFO
238- pFuncBody ->EnsureDynamicProfileInfo ();
258+ functionInfo-> GetFunctionBody () ->EnsureDynamicProfileInfo ();
239259#endif
240260 }
241261 END_JS_RUNTIME_CALL_AND_TRANSLATE_EXCEPTION_AND_ERROROBJECT_TO_HRESULT (hr);
@@ -244,11 +264,14 @@ namespace Js
244264 DEBUGGER_ATTACHDETACH_FATAL_ERROR_IF_FAILED (hr);
245265 }
246266
267+ // Parsing the function may change its FunctionProxy.
268+ Js::ParseableFunctionInfo *parseableFunctionInfo = functionInfo->GetParseableFunctionInfo ();
269+
247270 if (!fHasDoneSourceRundown && shouldPerformSourceRundown && !cachedScriptContext->IsClosed ())
248271 {
249272 BEGIN_TRANSLATE_OOM_TO_HRESULT_NESTED
250273 {
251- this ->RegisterFunction (pFuncBody , dwDebugHostSourceContext, pFuncBody ->GetSourceName ());
274+ this ->RegisterFunction (parseableFunctionInfo , dwDebugHostSourceContext, parseableFunctionInfo ->GetSourceName ());
252275 }
253276 END_TRANSLATE_OOM_TO_HRESULT (hr);
254277
@@ -294,85 +317,6 @@ namespace Js
294317 return hr;
295318 }
296319
297- void DebugContext::FetchTopLevelFunction (JsUtil::List<Js::FunctionBody *, ArenaAllocator>* pFunctions, Js::Utf8SourceInfo * sourceInfo)
298- {
299- Assert (pFunctions != nullptr );
300- Assert (sourceInfo != nullptr );
301-
302- HRESULT hr = S_OK;
303-
304- // Get FunctionBodys which are distinctly parseable, i.e. they are not enclosed in any other function (finding
305- // out root node of the sub-tree, in which root node is not enclosed in any other available function) this is
306- // by walking over all function and comparing their range.
307-
308- BEGIN_TRANSLATE_OOM_TO_HRESULT_NESTED
309- {
310- pFunctions->Clear ();
311-
312- sourceInfo->MapFunctionUntil ([&](Js::FunctionBody* pFuncBody) -> bool
313- {
314- if (pFuncBody->GetIsGlobalFunc ())
315- {
316- if (pFuncBody->IsFakeGlobalFunc (pFuncBody->GetGrfscr ()))
317- {
318- // This is created due to 'Function' code or deferred parsed functions, there is nothing to
319- // re-compile in this function as this is just a place-holder/fake function.
320-
321- Assert (pFuncBody->GetByteCode () == NULL );
322-
323- return false ;
324- }
325-
326- if (!pFuncBody->GetIsTopLevel ())
327- {
328- return false ;
329- }
330-
331- // If global function, there is no need to find out any other functions.
332-
333- pFunctions->Clear ();
334- pFunctions->Add (pFuncBody);
335- return true ;
336- }
337-
338- if (pFuncBody->IsFunctionParsed ())
339- {
340- bool isNeedToAdd = true ;
341- for (int i = 0 ; i < pFunctions->Count (); i++)
342- {
343- Js::FunctionBody *currentFunction = pFunctions->Item (i);
344- if (currentFunction != nullptr )
345- {
346- if (currentFunction->StartInDocument () > pFuncBody->StartInDocument () || !currentFunction->EndsAfter (pFuncBody->StartInDocument ()))
347- {
348- if (pFuncBody->StartInDocument () <= currentFunction->StartInDocument () && pFuncBody->EndsAfter (currentFunction->StartInDocument ()))
349- {
350- // The stored item has got the parent, remove current Item
351- pFunctions->Item (i, nullptr );
352- }
353- }
354- else
355- {
356- // Parent (the enclosing function) is already in the list
357- isNeedToAdd = false ;
358- break ;
359- }
360- }
361- }
362-
363- if (isNeedToAdd)
364- {
365- pFunctions->Add (pFuncBody);
366- }
367- }
368- return false ;
369- });
370- }
371- END_TRANSLATE_OOM_TO_HRESULT (hr);
372-
373- Assert (hr == S_OK);
374- }
375-
376320 // Create an ordered flat list of sources to reparse. Caller of a source should be added to the list before we add the source itself.
377321 void DebugContext::WalkAndAddUtf8SourceInfo (Js::Utf8SourceInfo* sourceInfo, JsUtil::List<Js::Utf8SourceInfo *, Recycler, false , Js::CopyRemovePolicy, RecyclerPointerComparer> *utf8SourceInfoList)
378322 {
0 commit comments