11cb0ef41Sopenharmony_ci// Copyright 2020 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_cinamespace function { 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ciextern macro OrdinaryHasInstance(Context, Object, Object): JSAny; 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ci// ES6 section 19.2.3.6 Function.prototype[@@hasInstance] 101cb0ef41Sopenharmony_cijavascript builtin FunctionPrototypeHasInstance( 111cb0ef41Sopenharmony_ci js-implicit context: NativeContext, receiver: JSAny)(value: JSAny): JSAny { 121cb0ef41Sopenharmony_ci return OrdinaryHasInstance(context, receiver, value); 131cb0ef41Sopenharmony_ci} 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_ciextern transitioning builtin 161cb0ef41Sopenharmony_ciFunctionPrototypeBind(implicit context: Context)( 171cb0ef41Sopenharmony_ci JSFunction, JSAny, int32): JSAny; 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_ciconst kLengthDescriptorIndex: constexpr int32 201cb0ef41Sopenharmony_ci generates 'JSFunctionOrBoundFunctionOrWrappedFunction::kLengthDescriptorIndex' 211cb0ef41Sopenharmony_ci ; 221cb0ef41Sopenharmony_ciconst kNameDescriptorIndex: constexpr int32 231cb0ef41Sopenharmony_ci generates 'JSFunctionOrBoundFunctionOrWrappedFunction::kNameDescriptorIndex' 241cb0ef41Sopenharmony_ci ; 251cb0ef41Sopenharmony_ciconst kMinDescriptorsForFastBindAndWrap: constexpr int31 261cb0ef41Sopenharmony_ci generates 'JSFunction::kMinDescriptorsForFastBindAndWrap'; 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_cimacro CheckAccessor(implicit context: Context)( 291cb0ef41Sopenharmony_ci array: DescriptorArray, index: constexpr int32, 301cb0ef41Sopenharmony_ci name: Name): void labels Slow { 311cb0ef41Sopenharmony_ci const descriptor: DescriptorEntry = array.descriptors[index]; 321cb0ef41Sopenharmony_ci const key: Name|Undefined = descriptor.key; 331cb0ef41Sopenharmony_ci if (!TaggedEqual(key, name)) goto Slow; 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ci // The descriptor value must be an AccessorInfo. 361cb0ef41Sopenharmony_ci Cast<AccessorInfo>(descriptor.value) otherwise goto Slow; 371cb0ef41Sopenharmony_ci} 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci// ES6 section 19.2.3.2 Function.prototype.bind 401cb0ef41Sopenharmony_citransitioning javascript builtin 411cb0ef41Sopenharmony_ciFastFunctionPrototypeBind( 421cb0ef41Sopenharmony_ci js-implicit context: NativeContext, receiver: JSAny, newTarget: JSAny, 431cb0ef41Sopenharmony_ci target: JSFunction)(...arguments): JSAny { 441cb0ef41Sopenharmony_ci const argc: intptr = arguments.actual_count; 451cb0ef41Sopenharmony_ci try { 461cb0ef41Sopenharmony_ci typeswitch (receiver) { 471cb0ef41Sopenharmony_ci case (fn: JSFunction|JSBoundFunction|JSWrappedFunction): { 481cb0ef41Sopenharmony_ci // Disallow binding of slow-mode functions. We need to figure out 491cb0ef41Sopenharmony_ci // whether the length and name property are in the original state. 501cb0ef41Sopenharmony_ci Comment('Disallow binding of slow-mode functions'); 511cb0ef41Sopenharmony_ci if (IsDictionaryMap(fn.map)) goto Slow; 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ci // Check whether the length and name properties are still present as 541cb0ef41Sopenharmony_ci // AccessorInfo objects. If so, their value can be recomputed even if 551cb0ef41Sopenharmony_ci // the actual value on the object changes. 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ci if (fn.map.bit_field3.number_of_own_descriptors < 581cb0ef41Sopenharmony_ci kMinDescriptorsForFastBindAndWrap) { 591cb0ef41Sopenharmony_ci goto Slow; 601cb0ef41Sopenharmony_ci } 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ci const descriptors: DescriptorArray = fn.map.instance_descriptors; 631cb0ef41Sopenharmony_ci CheckAccessor( 641cb0ef41Sopenharmony_ci descriptors, kLengthDescriptorIndex, LengthStringConstant()) 651cb0ef41Sopenharmony_ci otherwise Slow; 661cb0ef41Sopenharmony_ci CheckAccessor(descriptors, kNameDescriptorIndex, NameStringConstant()) 671cb0ef41Sopenharmony_ci otherwise Slow; 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_ci // Choose the right bound function map based on whether the target is 701cb0ef41Sopenharmony_ci // constructable. 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ci const boundFunctionMap: Map = 731cb0ef41Sopenharmony_ci IsConstructor(fn) ? 741cb0ef41Sopenharmony_ci *NativeContextSlot( 751cb0ef41Sopenharmony_ci ContextSlot::BOUND_FUNCTION_WITH_CONSTRUCTOR_MAP_INDEX) : 761cb0ef41Sopenharmony_ci *NativeContextSlot(ContextSlot:: 771cb0ef41Sopenharmony_ci BOUND_FUNCTION_WITHOUT_CONSTRUCTOR_MAP_INDEX); 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_ci // Verify that prototype matches that of the target bound function. 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci if (fn.map.prototype != boundFunctionMap.prototype) goto Slow; 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_ci // Allocate the arguments array. 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_ci const argumentsArray = arguments.length <= 1 ? 861cb0ef41Sopenharmony_ci kEmptyFixedArray : 871cb0ef41Sopenharmony_ci NewFixedArray( 881cb0ef41Sopenharmony_ci arguments.length - 1, ArgumentsIterator{arguments, current: 1}); 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_ci const boundReceiver: JSAny = arguments[0]; 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_ci const result = new JSBoundFunction{ 931cb0ef41Sopenharmony_ci map: boundFunctionMap, 941cb0ef41Sopenharmony_ci properties_or_hash: kEmptyFixedArray, 951cb0ef41Sopenharmony_ci elements: kEmptyFixedArray, 961cb0ef41Sopenharmony_ci bound_target_function: fn, 971cb0ef41Sopenharmony_ci bound_this: boundReceiver, 981cb0ef41Sopenharmony_ci bound_arguments: argumentsArray 991cb0ef41Sopenharmony_ci }; 1001cb0ef41Sopenharmony_ci return result; 1011cb0ef41Sopenharmony_ci } 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_ci case (JSAny): { 1041cb0ef41Sopenharmony_ci goto Slow; 1051cb0ef41Sopenharmony_ci } 1061cb0ef41Sopenharmony_ci } 1071cb0ef41Sopenharmony_ci } label Slow { 1081cb0ef41Sopenharmony_ci tail FunctionPrototypeBind( 1091cb0ef41Sopenharmony_ci LoadTargetFromFrame(), newTarget, Convert<int32>(argc)); 1101cb0ef41Sopenharmony_ci } 1111cb0ef41Sopenharmony_ci} 1121cb0ef41Sopenharmony_ci} // namespace function 113