1f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Copyright 2016 the V8 project authors. All rights reserved. 2f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// found in the LICENSE file. 4f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 5f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/builtins/builtins.h" 6f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/builtins/builtins-utils.h" 7f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 8f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/compiler.h" 9f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/string-builder.h" 10f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 11f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace v8 { 12f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace internal { 13f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 14f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace { 15f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 16f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// ES6 section 19.2.1.1.1 CreateDynamicFunction 17f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochMaybeHandle<Object> CreateDynamicFunction(Isolate* isolate, 18f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch BuiltinArguments args, 19f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch const char* token) { 20f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Compute number of arguments, ignoring the receiver. 21f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK_LE(1, args.length()); 22f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int const argc = args.length() - 1; 23f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 24c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Handle<JSFunction> target = args.target(); 25f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<JSObject> target_global_proxy(target->global_proxy(), isolate); 26f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 27f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!Builtins::AllowDynamicFunction(isolate, target, target_global_proxy)) { 28f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch isolate->CountUsage(v8::Isolate::kFunctionConstructorReturnedUndefined); 29f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return isolate->factory()->undefined_value(); 30f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 31f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 32f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Build the source string. 33f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<String> source; 34f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 35f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch IncrementalStringBuilder builder(isolate); 36f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch builder.AppendCharacter('('); 37f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch builder.AppendCString(token); 38f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch builder.AppendCharacter('('); 39f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch bool parenthesis_in_arg_string = false; 40f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (argc > 1) { 41f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (int i = 1; i < argc; ++i) { 42f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (i > 1) builder.AppendCharacter(','); 43f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<String> param; 44f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ASSIGN_RETURN_ON_EXCEPTION( 45f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch isolate, param, Object::ToString(isolate, args.at<Object>(i)), 46f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Object); 47f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch param = String::Flatten(param); 48f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch builder.AppendString(param); 49f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // If the formal parameters string include ) - an illegal 50f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // character - it may make the combined function expression 51f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // compile. We avoid this problem by checking for this early on. 52f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DisallowHeapAllocation no_gc; // Ensure vectors stay valid. 53f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch String::FlatContent param_content = param->GetFlatContent(); 54f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (int i = 0, length = param->length(); i < length; ++i) { 55f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (param_content.Get(i) == ')') { 56f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch parenthesis_in_arg_string = true; 57f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 58f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 59f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 60f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 61f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // If the formal parameters include an unbalanced block comment, the 62f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // function must be rejected. Since JavaScript does not allow nested 63f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // comments we can include a trailing block comment to catch this. 64f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch builder.AppendCString("\n/**/"); 65f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 66f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch builder.AppendCString(") {\n"); 67f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (argc > 0) { 68f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<String> body; 69f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ASSIGN_RETURN_ON_EXCEPTION( 70f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch isolate, body, Object::ToString(isolate, args.at<Object>(argc)), 71f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Object); 72f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch builder.AppendString(body); 73f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 74f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch builder.AppendCString("\n})"); 75f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ASSIGN_RETURN_ON_EXCEPTION(isolate, source, builder.Finish(), Object); 76f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 77f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // The SyntaxError must be thrown after all the (observable) ToString 78f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // conversions are done. 79f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (parenthesis_in_arg_string) { 80f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch THROW_NEW_ERROR(isolate, 81f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch NewSyntaxError(MessageTemplate::kParenthesisInArgString), 82f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Object); 83f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 84f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 85f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 86f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Compile the string in the constructor and not a helper so that errors to 87f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // come from here. 88f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<JSFunction> function; 89f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 90f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ASSIGN_RETURN_ON_EXCEPTION(isolate, function, 91f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Compiler::GetFunctionFromString( 92f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch handle(target->native_context(), isolate), 93f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch source, ONLY_SINGLE_FUNCTION_LITERAL), 94f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Object); 95f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<Object> result; 96f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ASSIGN_RETURN_ON_EXCEPTION( 97f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch isolate, result, 98f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Execution::Call(isolate, function, target_global_proxy, 0, nullptr), 99f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Object); 100f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch function = Handle<JSFunction>::cast(result); 101f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch function->shared()->set_name_should_print_as_anonymous(true); 102f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 103f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 104f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // If new.target is equal to target then the function created 105f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // is already correctly setup and nothing else should be done 106f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // here. But if new.target is not equal to target then we are 107f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // have a Function builtin subclassing case and therefore the 108f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // function has wrong initial map. To fix that we create a new 109f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // function object with correct initial map. 110f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<Object> unchecked_new_target = args.new_target(); 111f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!unchecked_new_target->IsUndefined(isolate) && 112f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch !unchecked_new_target.is_identical_to(target)) { 113f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<JSReceiver> new_target = 114f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<JSReceiver>::cast(unchecked_new_target); 115f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<Map> initial_map; 116f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ASSIGN_RETURN_ON_EXCEPTION( 117f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch isolate, initial_map, 118f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch JSFunction::GetDerivedMap(isolate, target, new_target), Object); 119f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 120f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<SharedFunctionInfo> shared_info(function->shared(), isolate); 121f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<Map> map = Map::AsLanguageMode( 122f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch initial_map, shared_info->language_mode(), shared_info->kind()); 123f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 124f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<Context> context(function->context(), isolate); 125f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch function = isolate->factory()->NewFunctionFromSharedFunctionInfo( 126f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch map, shared_info, context, NOT_TENURED); 127f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 128f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return function; 129f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 130f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 131f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} // namespace 132f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 133f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// ES6 section 19.2.1.1 Function ( p1, p2, ... , pn, body ) 134f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochBUILTIN(FunctionConstructor) { 135f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch HandleScope scope(isolate); 136f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<Object> result; 137f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 138f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch isolate, result, CreateDynamicFunction(isolate, args, "function")); 139f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return *result; 140f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 141f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 142f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// ES6 section 25.2.1.1 GeneratorFunction (p1, p2, ... , pn, body) 143f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochBUILTIN(GeneratorFunctionConstructor) { 144f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch HandleScope scope(isolate); 145f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RETURN_RESULT_OR_FAILURE(isolate, 146f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CreateDynamicFunction(isolate, args, "function*")); 147f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 148f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 149f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochBUILTIN(AsyncFunctionConstructor) { 150f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch HandleScope scope(isolate); 151f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<Object> maybe_func; 152f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 153f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch isolate, maybe_func, 154f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CreateDynamicFunction(isolate, args, "async function")); 155f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!maybe_func->IsJSFunction()) return *maybe_func; 156f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 157f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Do not lazily compute eval position for AsyncFunction, as they may not be 158f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // determined after the function is resumed. 159f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<JSFunction> func = Handle<JSFunction>::cast(maybe_func); 160f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<Script> script = handle(Script::cast(func->shared()->script())); 161f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int position = script->GetEvalPosition(); 162f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch USE(position); 163f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 164f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return *func; 165f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 166f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 167f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace { 168f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 169f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochObject* DoFunctionBind(Isolate* isolate, BuiltinArguments args) { 170f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch HandleScope scope(isolate); 171f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK_LE(1, args.length()); 172f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!args.receiver()->IsCallable()) { 173f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch THROW_NEW_ERROR_RETURN_FAILURE( 174f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch isolate, NewTypeError(MessageTemplate::kFunctionBind)); 175f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 176f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 177f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Allocate the bound function with the given {this_arg} and {args}. 178f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<JSReceiver> target = args.at<JSReceiver>(0); 179f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<Object> this_arg = isolate->factory()->undefined_value(); 180f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ScopedVector<Handle<Object>> argv(std::max(0, args.length() - 2)); 181f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (args.length() > 1) { 182f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch this_arg = args.at<Object>(1); 183f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (int i = 2; i < args.length(); ++i) { 184f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch argv[i - 2] = args.at<Object>(i); 185f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 186f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 187f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<JSBoundFunction> function; 188f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 189f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch isolate, function, 190f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch isolate->factory()->NewJSBoundFunction(target, this_arg, argv)); 191f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 192f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch LookupIterator length_lookup(target, isolate->factory()->length_string(), 193f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch target, LookupIterator::OWN); 194f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Setup the "length" property based on the "length" of the {target}. 195f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // If the targets length is the default JSFunction accessor, we can keep the 196f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // accessor that's installed by default on the JSBoundFunction. It lazily 197f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // computes the value from the underlying internal length. 198f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!target->IsJSFunction() || 199f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch length_lookup.state() != LookupIterator::ACCESSOR || 200f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch !length_lookup.GetAccessors()->IsAccessorInfo()) { 201c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Handle<Object> length(Smi::kZero, isolate); 202f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Maybe<PropertyAttributes> attributes = 203f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch JSReceiver::GetPropertyAttributes(&length_lookup); 204f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!attributes.IsJust()) return isolate->heap()->exception(); 205f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (attributes.FromJust() != ABSENT) { 206f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<Object> target_length; 207f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target_length, 208f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Object::GetProperty(&length_lookup)); 209f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (target_length->IsNumber()) { 210f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch length = isolate->factory()->NewNumber(std::max( 211f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 0.0, DoubleToInteger(target_length->Number()) - argv.length())); 212f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 213f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 214f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch LookupIterator it(function, isolate->factory()->length_string(), function); 215f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK_EQ(LookupIterator::ACCESSOR, it.state()); 216f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RETURN_FAILURE_ON_EXCEPTION(isolate, 217f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch JSObject::DefineOwnPropertyIgnoreAttributes( 218f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch &it, length, it.property_attributes())); 219f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 220f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 221f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Setup the "name" property based on the "name" of the {target}. 222f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // If the targets name is the default JSFunction accessor, we can keep the 223f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // accessor that's installed by default on the JSBoundFunction. It lazily 224f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // computes the value from the underlying internal name. 225f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch LookupIterator name_lookup(target, isolate->factory()->name_string(), target, 226f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch LookupIterator::OWN); 227f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!target->IsJSFunction() || 228f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch name_lookup.state() != LookupIterator::ACCESSOR || 229f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch !name_lookup.GetAccessors()->IsAccessorInfo()) { 230f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<Object> target_name; 231f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target_name, 232f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Object::GetProperty(&name_lookup)); 233f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<String> name; 234f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (target_name->IsString()) { 235f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 236f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch isolate, name, 237f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Name::ToFunctionName(Handle<String>::cast(target_name))); 238f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 239f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch isolate, name, isolate->factory()->NewConsString( 240f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch isolate->factory()->bound__string(), name)); 241f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 242f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch name = isolate->factory()->bound__string(); 243f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 244f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch LookupIterator it(function, isolate->factory()->name_string()); 245f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK_EQ(LookupIterator::ACCESSOR, it.state()); 246f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RETURN_FAILURE_ON_EXCEPTION(isolate, 247f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch JSObject::DefineOwnPropertyIgnoreAttributes( 248f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch &it, name, it.property_attributes())); 249f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 250f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return *function; 251f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 252f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 253f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} // namespace 254f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 255f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// ES6 section 19.2.3.2 Function.prototype.bind ( thisArg, ...args ) 256f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochBUILTIN(FunctionPrototypeBind) { return DoFunctionBind(isolate, args); } 257f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 258f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// TODO(verwaest): This is a temporary helper until the FastFunctionBind stub 259f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// can tailcall to the builtin directly. 260f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochRUNTIME_FUNCTION(Runtime_FunctionBind) { 261f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK_EQ(2, args.length()); 262f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Arguments* incoming = reinterpret_cast<Arguments*>(args[0]); 263f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Rewrap the arguments as builtins arguments. 264f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int argc = incoming->length() + BuiltinArguments::kNumExtraArgsWithReceiver; 265f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch BuiltinArguments caller_args(argc, incoming->arguments() + 1); 266f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return DoFunctionBind(isolate, caller_args); 267f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 268f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 269f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// ES6 section 19.2.3.5 Function.prototype.toString ( ) 270f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochBUILTIN(FunctionPrototypeToString) { 271f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch HandleScope scope(isolate); 272f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<Object> receiver = args.receiver(); 273f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (receiver->IsJSBoundFunction()) { 274f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return *JSBoundFunction::ToString(Handle<JSBoundFunction>::cast(receiver)); 275f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else if (receiver->IsJSFunction()) { 276f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return *JSFunction::ToString(Handle<JSFunction>::cast(receiver)); 277f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 278f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch THROW_NEW_ERROR_RETURN_FAILURE( 279f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch isolate, NewTypeError(MessageTemplate::kNotGeneric, 280f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch isolate->factory()->NewStringFromAsciiChecked( 281f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Function.prototype.toString"))); 282f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 283f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 284f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// ES6 section 19.2.3.6 Function.prototype [ @@hasInstance ] ( V ) 285f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid Builtins::Generate_FunctionPrototypeHasInstance( 286f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CodeStubAssembler* assembler) { 287f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch using compiler::Node; 288f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 289f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* f = assembler->Parameter(0); 290f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* v = assembler->Parameter(1); 291f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* context = assembler->Parameter(4); 292f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* result = assembler->OrdinaryHasInstance(context, f, v); 293f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch assembler->Return(result); 294f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 295f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 296f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} // namespace internal 297f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} // namespace v8 298