Skip to content

Commit 1c22ba5

Browse files
committed
Update JsBuiltIn register functions to use common logic
1 parent 06dd001 commit 1c22ba5

File tree

3 files changed

+39
-54
lines changed

3 files changed

+39
-54
lines changed

lib/Runtime/Library/EngineInterfaceObject.cpp

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -268,11 +268,9 @@ namespace Js
268268
}
269269

270270
/* static */
271-
template <bool isConstructor>
272-
ScriptFunction *EngineInterfaceObject::CreateLibraryCodeScriptFunction(ScriptFunction *scriptFunction, JavascriptString *displayName)
271+
ScriptFunction *EngineInterfaceObject::CreateLibraryCodeScriptFunction(ScriptFunction *scriptFunction, JavascriptString *displayName, bool isConstructor, bool isJsBuiltIn, bool isPublic)
273272
{
274273
ScriptContext *scriptContext = scriptFunction->GetScriptContext();
275-
scriptFunction->GetFunctionProxy()->SetIsPublicLibraryCode();
276274

277275
// Use GetSz rather than GetString because we use wcsrchr below, which expects a null-terminated string
278276
// Callers can pass in a string like "get compare" or "Intl.Collator.prototype.resolvedOptions" -- only for the
@@ -310,6 +308,7 @@ namespace Js
310308
AssertMsg((scriptFunction->GetFunctionInfo()->GetAttributes() & FunctionInfo::Attributes::ErrorOnNew) == 0, "Why is the function not constructable by default?");
311309
}
312310

311+
// handle the name property AFTER handling isConstructor, because this can initialize the function's deferred type
313312
Var existingName = nullptr;
314313
if (JavascriptOperators::GetOwnProperty(scriptFunction, PropertyIds::name, &existingName, scriptContext, nullptr))
315314
{
@@ -334,6 +333,24 @@ namespace Js
334333
scriptFunction->SetPropertyWithAttributes(PropertyIds::name, funcName, PropertyConfigurable, nullptr);
335334
}
336335

336+
if (isJsBuiltIn)
337+
{
338+
scriptFunction->GetFunctionProxy()->SetIsJsBuiltInCode();
339+
340+
// This makes it so that the given scriptFunction can't reference/close over any outside variables,
341+
// which is desirable for JsBuiltIns (though currently not for Intl)
342+
scriptFunction->SetEnvironment(const_cast<FrameDisplay *>(&StrictNullFrameDisplay));
343+
344+
// TODO(jahorto): investigate force-inlining Intl code
345+
AssertOrFailFast(scriptFunction->HasFunctionBody());
346+
scriptFunction->GetFunctionBody()->SetJsBuiltInForceInline();
347+
}
348+
349+
if (isPublic)
350+
{
351+
scriptFunction->GetFunctionProxy()->SetIsPublicLibraryCode();
352+
}
353+
337354
return scriptFunction;
338355
}
339356

@@ -349,17 +366,15 @@ namespace Js
349366
ScriptFunction *func = ScriptFunction::UnsafeFromVar(args[1]);
350367
JavascriptString *methodName = JavascriptString::UnsafeFromVar(args[2]);
351368

369+
bool isConstructor = true;
352370
if (args.Info.Count == 4)
353371
{
354372
AssertOrFailFast(JavascriptBoolean::Is(args.Values[3]));
355-
if (!JavascriptBoolean::UnsafeFromVar(args.Values[3])->GetValue())
356-
{
357-
return CreateLibraryCodeScriptFunction<false>(func, methodName);
358-
}
373+
isConstructor = JavascriptBoolean::UnsafeFromVar(args.Values[3])->GetValue();
359374
}
360375

361376
// isConstructor = true is the default (when no 3rd arg is provided)
362-
return CreateLibraryCodeScriptFunction<true>(func, methodName);
377+
return CreateLibraryCodeScriptFunction(func, methodName, isConstructor, false /* isJsBuiltIn */, true /* isPublic */);
363378
}
364379

365380
/*

lib/Runtime/Library/EngineInterfaceObject.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,7 @@ namespace Js
8888

8989
static bool __cdecl InitializeCommonNativeInterfaces(DynamicObject* engineInterface, DeferredTypeHandlerBase * typeHandler, DeferredInitializeMode mode);
9090

91-
template <bool isConstructor>
92-
static ScriptFunction *CreateLibraryCodeScriptFunction(ScriptFunction *scriptFunction, JavascriptString *displayName);
91+
static ScriptFunction *CreateLibraryCodeScriptFunction(ScriptFunction *scriptFunction, JavascriptString *displayName, bool isConstructor, bool isJsBuiltIn, bool isPublic);
9392

9493
class EntryInfo
9594
{

lib/Runtime/Library/JsBuiltInEngineInterfaceExtensionObject.cpp

Lines changed: 15 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -310,29 +310,16 @@ namespace Js
310310
{
311311
EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
312312

313-
AssertOrFailFast(args.Info.Count >= 3 && JavascriptString::Is(args.Values[1]) && JavascriptFunction::Is(args.Values[2]));
313+
AssertOrFailFast(args.Info.Count >= 3 && JavascriptString::Is(args.Values[1]) && ScriptFunction::Is(args.Values[2]));
314314

315315
JavascriptLibrary * library = scriptContext->GetLibrary();
316316

317-
// retrieves arguments
318-
JavascriptString* methodName = JavascriptString::FromVar(args.Values[1]);
319-
JavascriptFunction* func = JavascriptFunction::FromVar(args.Values[2]);
320-
321-
func->GetFunctionProxy()->EnsureDeserialized();
317+
JavascriptString* methodName = JavascriptString::UnsafeFromVar(args.Values[1]);
318+
ScriptFunction* func = EngineInterfaceObject::CreateLibraryCodeScriptFunction(ScriptFunction::UnsafeFromVar(args.Values[2]), methodName, false /* isConstructor */, true /* isJsBuiltIn */, false /* isPublic */);
322319

323-
DynamicObject* chakraLibraryObject = GetPrototypeFromName(PropertyIds::__chakraLibrary, false, scriptContext);
324320
PropertyIds functionIdentifier = JavascriptOperators::GetPropertyId(methodName, scriptContext);
325321

326-
// Link the function to __chakraLibrary.
327-
ScriptFunction* scriptFunction = library->CreateScriptFunction(func->GetFunctionProxy());
328-
scriptFunction->GetFunctionProxy()->SetIsJsBuiltInCode();
329-
330-
Assert(scriptFunction->HasFunctionBody());
331-
scriptFunction->GetFunctionBody()->SetJsBuiltInForceInline();
332-
333-
scriptFunction->SetPropertyWithAttributes(PropertyIds::name, methodName, PropertyConfigurable, nullptr);
334-
335-
library->AddMember(chakraLibraryObject, functionIdentifier, scriptFunction);
322+
library->AddMember(library->GetChakraLib(), functionIdentifier, func);
336323

337324
//Don't need to return anything
338325
return library->GetUndefined();
@@ -342,7 +329,7 @@ namespace Js
342329
{
343330
EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
344331

345-
AssertOrFailFast(args.Info.Count >= 3 && JavascriptObject::Is(args.Values[1]) && JavascriptFunction::Is(args.Values[2]));
332+
AssertOrFailFast(args.Info.Count >= 3 && JavascriptObject::Is(args.Values[1]) && ScriptFunction::Is(args.Values[2]));
346333

347334
JavascriptLibrary * library = scriptContext->GetLibrary();
348335

@@ -370,49 +357,33 @@ namespace Js
370357

371358
BOOL staticMethod = JavascriptConversion::ToBoolean(staticMethodProperty, scriptContext);
372359
BOOL forceInline = JavascriptConversion::ToBoolean(forceInlineProperty, scriptContext);
360+
Assert(forceInline);
373361

374-
JavascriptFunction* func = JavascriptFunction::FromVar(args.Values[2]);
375-
376-
// Set the function's display name, as the function we pass in argument are anonym.
377-
func->GetFunctionProxy()->SetIsPublicLibraryCode();
378-
func->GetFunctionProxy()->EnsureDeserialized()->SetDisplayName(methodName->GetString(), methodName->GetLength(), 0);
362+
ScriptFunction *func = EngineInterfaceObject::CreateLibraryCodeScriptFunction(ScriptFunction::UnsafeFromVar(args.Values[2]), methodName, false /* isConstructor */, true /* isJsBuiltIn */, true /* isPublic */);
379363

380364
DynamicObject* prototype = GetPrototypeFromName(JavascriptOperators::GetPropertyId(className, scriptContext), staticMethod, scriptContext);
381-
PropertyIds functionIdentifier = methodName->BufferEquals(_u("Symbol.iterator"), 15)? PropertyIds::_symbolIterator :
382-
JavascriptOperators::GetPropertyId(methodName, scriptContext);
383-
384-
// Link the function to the prototype.
385-
ScriptFunction* scriptFunction = library->CreateScriptFunction(func->GetFunctionProxy());
386-
scriptFunction->GetFunctionProxy()->SetIsJsBuiltInCode();
387-
388-
if (forceInline)
389-
{
390-
Assert(scriptFunction->HasFunctionBody());
391-
scriptFunction->GetFunctionBody()->SetJsBuiltInForceInline();
392-
}
393-
scriptFunction->SetPropertyWithAttributes(PropertyIds::length, TaggedInt::ToVarUnchecked(argumentsCount), PropertyConfigurable, nullptr);
394-
395-
scriptFunction->SetConfigurable(PropertyIds::prototype, true);
396-
scriptFunction->DeleteProperty(PropertyIds::prototype, Js::PropertyOperationFlags::PropertyOperation_None);
365+
PropertyIds functionIdentifier = methodName->BufferEquals(_u("Symbol.iterator"), 15)
366+
? PropertyIds::_symbolIterator
367+
: JavascriptOperators::GetPropertyId(methodName, scriptContext);
397368

398-
scriptFunction->SetPropertyWithAttributes(PropertyIds::name, methodName, PropertyConfigurable, nullptr);
369+
func->SetPropertyWithAttributes(PropertyIds::length, TaggedInt::ToVarUnchecked(argumentsCount), PropertyConfigurable, nullptr);
399370

400-
library->AddMember(prototype, functionIdentifier, scriptFunction);
371+
library->AddMember(prototype, functionIdentifier, func);
401372

402-
RecordCommonNativeInterfaceBuiltIns(functionIdentifier, scriptContext, scriptFunction);
373+
RecordCommonNativeInterfaceBuiltIns(functionIdentifier, scriptContext, func);
403374

404375
if (!JavascriptOperators::IsUndefinedOrNull(aliasProperty))
405376
{
406377
JavascriptString * alias = JavascriptConversion::ToString(aliasProperty, scriptContext);
407378
// Cannot do a string to property id search here, Symbol.* have different hashing mechanism, so resort to this str compare
408379
PropertyIds aliasFunctionIdentifier = alias->BufferEquals(_u("Symbol.iterator"), 15) ? PropertyIds::_symbolIterator :
409380
JavascriptOperators::GetPropertyId(alias, scriptContext);
410-
library->AddMember(prototype, aliasFunctionIdentifier, scriptFunction);
381+
library->AddMember(prototype, aliasFunctionIdentifier, func);
411382
}
412383

413384
if (prototype == library->arrayPrototype)
414385
{
415-
RecordDefaultIteratorFunctions(functionIdentifier, scriptContext, scriptFunction);
386+
RecordDefaultIteratorFunctions(functionIdentifier, scriptContext, func);
416387
}
417388

418389
//Don't need to return anything

0 commit comments

Comments
 (0)