@@ -309,17 +309,15 @@ namespace Js
309309
310310 PropertyQueryFlags BoundFunction::HasPropertyQuery (PropertyId propertyId, _Inout_opt_ PropertyValueInfo* info)
311311 {
312- if (propertyId == PropertyIds::length)
313- {
314- return PropertyQueryFlags::Property_Found;
315- }
312+ EnsureLength ();
316313
317314 return JavascriptFunction::HasPropertyQuery (propertyId, info);
318315 }
319316
320317 PropertyQueryFlags BoundFunction::GetPropertyQuery (Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext)
321318 {
322319 BOOL result;
320+ EnsureLength ();
323321 if (GetPropertyBuiltIns (originalInstance, propertyId, value, info, requestContext, &result))
324322 {
325323 return JavascriptConversion::BooleanToPropertyQueryFlags (result);
@@ -332,6 +330,7 @@ namespace Js
332330 {
333331 BOOL result;
334332 PropertyRecord const * propertyRecord;
333+ EnsureLength ();
335334 this ->GetScriptContext ()->FindPropertyRecord (propertyNameString, &propertyRecord);
336335
337336 if (propertyRecord != nullptr && GetPropertyBuiltIns (originalInstance, propertyRecord->GetPropertyId (), value, info, requestContext, &result))
@@ -344,23 +343,13 @@ namespace Js
344343
345344 bool BoundFunction::GetPropertyBuiltIns (Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext, BOOL* result)
346345 {
347- if (propertyId == PropertyIds::length)
346+ if (! EnsureLength () && propertyId == PropertyIds::length)
348347 {
349348 // Get the "length" property of the underlying target function
350- int len = 0 ;
351- Var varLength;
352- if (targetFunction->GetProperty (targetFunction, PropertyIds::length, &varLength, nullptr , requestContext))
349+ if (GetPropertyQuery (originalInstance, propertyId, value, info, requestContext) == PropertyQueryFlags::Property_Found)
353350 {
354- len = JavascriptConversion::ToInt32 (varLength, requestContext) ;
351+ return true ;
355352 }
356-
357- // Reduce by number of bound args
358- len = len - this ->count ;
359- len = max (len, 0 );
360-
361- *value = JavascriptNumber::ToVar (len, requestContext);
362- *result = true ;
363- return true ;
364353 }
365354
366355 return false ;
@@ -374,6 +363,7 @@ namespace Js
374363 BOOL BoundFunction::SetProperty (PropertyId propertyId, Var value, PropertyOperationFlags flags, PropertyValueInfo* info)
375364 {
376365 BOOL result;
366+ EnsureLength ();
377367 if (SetPropertyBuiltIns (propertyId, value, flags, info, &result))
378368 {
379369 return result;
@@ -386,6 +376,7 @@ namespace Js
386376 {
387377 BOOL result;
388378 PropertyRecord const * propertyRecord;
379+ EnsureLength ();
389380 this ->GetScriptContext ()->FindPropertyRecord (propertyNameString, &propertyRecord);
390381
391382 if (propertyRecord != nullptr && SetPropertyBuiltIns (propertyRecord->GetPropertyId (), value, flags, info, &result))
@@ -398,13 +389,7 @@ namespace Js
398389
399390 bool BoundFunction::SetPropertyBuiltIns (PropertyId propertyId, Var value, PropertyOperationFlags flags, PropertyValueInfo* info, BOOL* result)
400391 {
401- if (propertyId == PropertyIds::length)
402- {
403- JavascriptError::ThrowCantAssignIfStrictMode (flags, this ->GetScriptContext ());
404-
405- *result = false ;
406- return true ;
407- }
392+ EnsureLength ();
408393
409394 return false ;
410395 }
@@ -431,52 +416,64 @@ namespace Js
431416
432417 BOOL BoundFunction::DeleteProperty (PropertyId propertyId, PropertyOperationFlags flags)
433418 {
434- if (propertyId == PropertyIds::length)
435- {
436- return false ;
437- }
419+ EnsureLength ();
438420
439421 return JavascriptFunction::DeleteProperty (propertyId, flags);
440422 }
441423
442424 BOOL BoundFunction::DeleteProperty (JavascriptString *propertyNameString, PropertyOperationFlags flags)
443425 {
444- if (BuiltInPropertyRecords::length.Equals (propertyNameString))
445- {
446- return false ;
447- }
426+ EnsureLength ();
448427
449428 return JavascriptFunction::DeleteProperty (propertyNameString, flags);
450429 }
451430
452431 BOOL BoundFunction::IsWritable (PropertyId propertyId)
453432 {
454- if (propertyId == PropertyIds::length)
455- {
456- return false ;
457- }
433+ EnsureLength ();
458434
459435 return JavascriptFunction::IsWritable (propertyId);
460436 }
461437
462438 BOOL BoundFunction::IsConfigurable (PropertyId propertyId)
463439 {
464- if (propertyId == PropertyIds::length)
465- {
466- return false ;
467- }
440+ EnsureLength ();
468441
469442 return JavascriptFunction::IsConfigurable (propertyId);
470443 }
471444
472445 BOOL BoundFunction::IsEnumerable (PropertyId propertyId)
473446 {
474- if (propertyId == PropertyIds::length)
447+ EnsureLength ();
448+
449+ return JavascriptFunction::IsEnumerable (propertyId);
450+ }
451+
452+ bool BoundFunction::EnsureLength ()
453+ {
454+ if (!lengthSet)
475455 {
456+ // Get the "length" property of the underlying target function
457+ int len = 0 ;
458+ if (JavascriptFunction::Is (targetFunction))
459+ {
460+ JavascriptFunction* func = JavascriptFunction::UnsafeFromVar (targetFunction);
461+ FunctionProxy* proxy = func->GetFunctionProxy ();
462+ if (proxy)
463+ {
464+ len = proxy->EnsureDeserialized ()->GetReportedInParamsCount () - 1 ;
465+ }
466+ }
467+
468+ // Reduce by number of bound args
469+ len = len - this ->count ;
470+ len = max (len, 0 );
471+
472+ SetPropertyWithAttributes (PropertyIds::length, TaggedInt::ToVarUnchecked (len), PropertyConfigurable, nullptr , PropertyOperation_None, SideEffects_None);
473+ lengthSet = true ;
476474 return false ;
477475 }
478-
479- return JavascriptFunction::IsEnumerable (propertyId);
476+ return true ;
480477 }
481478
482479 BOOL BoundFunction::HasInstance (Var instance, ScriptContext* scriptContext, IsInstInlineCache* inlineCache)
0 commit comments