OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/builtins.h" | 5 #include "src/builtins.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/api-arguments.h" | 8 #include "src/api-arguments.h" |
9 #include "src/api-natives.h" | 9 #include "src/api-natives.h" |
10 #include "src/base/once.h" | 10 #include "src/base/once.h" |
(...skipping 4048 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4059 this_arg = args.at<Object>(1); | 4059 this_arg = args.at<Object>(1); |
4060 for (int i = 2; i < args.length(); ++i) { | 4060 for (int i = 2; i < args.length(); ++i) { |
4061 argv[i - 2] = args.at<Object>(i); | 4061 argv[i - 2] = args.at<Object>(i); |
4062 } | 4062 } |
4063 } | 4063 } |
4064 Handle<JSBoundFunction> function; | 4064 Handle<JSBoundFunction> function; |
4065 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 4065 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
4066 isolate, function, | 4066 isolate, function, |
4067 isolate->factory()->NewJSBoundFunction(target, this_arg, argv)); | 4067 isolate->factory()->NewJSBoundFunction(target, this_arg, argv)); |
4068 | 4068 |
4069 // TODO(bmeurer): Optimize the rest for the common cases where {target} is | 4069 LookupIterator length_lookup(target, isolate->factory()->length_string(), |
4070 // a function with some initial map or even a bound function. | 4070 target, LookupIterator::HIDDEN); |
4071 // Setup the "length" property based on the "length" of the {target}. | 4071 // Setup the "length" property based on the "length" of the {target}. |
4072 Handle<Object> length(Smi::FromInt(0), isolate); | 4072 // If the targets length is the default JSFunction accessor, we can keep the |
4073 Maybe<bool> target_has_length = | 4073 // accessor that's installed by default on the JSBoundFunction. It lazily |
4074 JSReceiver::HasOwnProperty(target, isolate->factory()->length_string()); | 4074 // computes the value from the underlying internal length. |
4075 if (!target_has_length.IsJust()) { | 4075 if (!target->IsJSFunction() || |
4076 return isolate->heap()->exception(); | 4076 length_lookup.state() != LookupIterator::ACCESSOR || |
4077 } else if (target_has_length.FromJust()) { | 4077 !length_lookup.GetAccessors()->IsAccessorInfo()) { |
4078 Handle<Object> target_length; | 4078 Handle<Object> length(Smi::FromInt(0), isolate); |
4079 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 4079 Maybe<PropertyAttributes> attributes = |
4080 isolate, target_length, | 4080 JSReceiver::GetPropertyAttributes(&length_lookup); |
4081 JSReceiver::GetProperty(target, isolate->factory()->length_string())); | 4081 if (!attributes.IsJust()) return isolate->heap()->exception(); |
4082 if (target_length->IsNumber()) { | 4082 if (attributes.FromJust() != ABSENT) { |
4083 length = isolate->factory()->NewNumber(std::max( | 4083 Handle<Object> target_length; |
4084 0.0, DoubleToInteger(target_length->Number()) - argv.length())); | 4084 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target_length, |
| 4085 Object::GetProperty(&length_lookup)); |
| 4086 if (target_length->IsNumber()) { |
| 4087 length = isolate->factory()->NewNumber(std::max( |
| 4088 0.0, DoubleToInteger(target_length->Number()) - argv.length())); |
| 4089 } |
4085 } | 4090 } |
| 4091 LookupIterator it(function, isolate->factory()->length_string(), function); |
| 4092 DCHECK_EQ(LookupIterator::ACCESSOR, it.state()); |
| 4093 RETURN_FAILURE_ON_EXCEPTION(isolate, |
| 4094 JSObject::DefineOwnPropertyIgnoreAttributes( |
| 4095 &it, length, it.property_attributes())); |
4086 } | 4096 } |
4087 function->set_length(*length); | |
4088 | 4097 |
4089 // Setup the "name" property based on the "name" of the {target}. | 4098 // Setup the "name" property based on the "name" of the {target}. |
4090 Handle<Object> target_name; | 4099 // If the targets name is the default JSFunction accessor, we can keep the |
4091 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 4100 // accessor that's installed by default on the JSBoundFunction. It lazily |
4092 isolate, target_name, | 4101 // computes the value from the underlying internal name. |
4093 JSReceiver::GetProperty(target, isolate->factory()->name_string())); | 4102 LookupIterator name_lookup(target, isolate->factory()->name_string(), target, |
4094 Handle<String> name; | 4103 LookupIterator::HIDDEN); |
4095 if (!target_name->IsString()) { | 4104 if (!target->IsJSFunction() || |
4096 name = isolate->factory()->bound__string(); | 4105 name_lookup.state() != LookupIterator::ACCESSOR || |
4097 } else { | 4106 !name_lookup.GetAccessors()->IsAccessorInfo()) { |
4098 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 4107 Handle<Object> target_name; |
4099 isolate, name, Name::ToFunctionName(Handle<String>::cast(target_name))); | 4108 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target_name, |
4100 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 4109 Object::GetProperty(&name_lookup)); |
4101 isolate, name, isolate->factory()->NewConsString( | 4110 Handle<String> name; |
4102 isolate->factory()->bound__string(), name)); | 4111 if (target_name->IsString()) { |
| 4112 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 4113 isolate, name, |
| 4114 Name::ToFunctionName(Handle<String>::cast(target_name))); |
| 4115 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 4116 isolate, name, isolate->factory()->NewConsString( |
| 4117 isolate->factory()->bound__string(), name)); |
| 4118 } else { |
| 4119 name = isolate->factory()->bound__string(); |
| 4120 } |
| 4121 LookupIterator it(function, isolate->factory()->name_string()); |
| 4122 DCHECK_EQ(LookupIterator::ACCESSOR, it.state()); |
| 4123 RETURN_FAILURE_ON_EXCEPTION(isolate, |
| 4124 JSObject::DefineOwnPropertyIgnoreAttributes( |
| 4125 &it, name, it.property_attributes())); |
4103 } | 4126 } |
4104 function->set_name(*name); | |
4105 return *function; | 4127 return *function; |
4106 } | 4128 } |
4107 | 4129 |
4108 | 4130 |
4109 // ES6 section 19.2.3.5 Function.prototype.toString ( ) | 4131 // ES6 section 19.2.3.5 Function.prototype.toString ( ) |
4110 BUILTIN(FunctionPrototypeToString) { | 4132 BUILTIN(FunctionPrototypeToString) { |
4111 HandleScope scope(isolate); | 4133 HandleScope scope(isolate); |
4112 Handle<Object> receiver = args.receiver(); | 4134 Handle<Object> receiver = args.receiver(); |
4113 if (receiver->IsJSBoundFunction()) { | 4135 if (receiver->IsJSBoundFunction()) { |
4114 return *JSBoundFunction::ToString(Handle<JSBoundFunction>::cast(receiver)); | 4136 return *JSBoundFunction::ToString(Handle<JSBoundFunction>::cast(receiver)); |
(...skipping 836 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4951 BUILTIN_LIST_T(DEFINE_BUILTIN_ACCESSOR_T) | 4973 BUILTIN_LIST_T(DEFINE_BUILTIN_ACCESSOR_T) |
4952 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) | 4974 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) |
4953 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) | 4975 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) |
4954 #undef DEFINE_BUILTIN_ACCESSOR_C | 4976 #undef DEFINE_BUILTIN_ACCESSOR_C |
4955 #undef DEFINE_BUILTIN_ACCESSOR_A | 4977 #undef DEFINE_BUILTIN_ACCESSOR_A |
4956 #undef DEFINE_BUILTIN_ACCESSOR_T | 4978 #undef DEFINE_BUILTIN_ACCESSOR_T |
4957 #undef DEFINE_BUILTIN_ACCESSOR_H | 4979 #undef DEFINE_BUILTIN_ACCESSOR_H |
4958 | 4980 |
4959 } // namespace internal | 4981 } // namespace internal |
4960 } // namespace v8 | 4982 } // namespace v8 |
OLD | NEW |