Convert function.length to API-style accessor.
TEST=mjsunit/function-length-accessor R=yangguo@chromium.org Review URL: https://codereview.chromium.org/257423009 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20937 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
3654b3b2c0
commit
72358c7fed
@ -889,31 +889,57 @@ Handle<AccessorInfo> Accessors::FunctionPrototypeInfo(
|
||||
//
|
||||
|
||||
|
||||
Object* Accessors::FunctionGetLength(Isolate* isolate,
|
||||
Object* object,
|
||||
void*) {
|
||||
JSFunction* function = FindInstanceOf<JSFunction>(isolate, object);
|
||||
if (function == NULL) return Smi::FromInt(0);
|
||||
// Check if already compiled.
|
||||
if (function->shared()->is_compiled()) {
|
||||
return Smi::FromInt(function->shared()->length());
|
||||
}
|
||||
// If the function isn't compiled yet, the length is not computed correctly
|
||||
// yet. Compile it now and return the right length.
|
||||
void Accessors::FunctionLengthGetter(
|
||||
v8::Local<v8::String> name,
|
||||
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
||||
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
||||
HandleScope scope(isolate);
|
||||
Handle<JSFunction> function_handle(function);
|
||||
if (Compiler::EnsureCompiled(function_handle, KEEP_EXCEPTION)) {
|
||||
return Smi::FromInt(function_handle->shared()->length());
|
||||
Handle<Object> object = Utils::OpenHandle(*info.This());
|
||||
MaybeHandle<JSFunction> maybe_function;
|
||||
|
||||
{
|
||||
DisallowHeapAllocation no_allocation;
|
||||
JSFunction* function = FindInstanceOf<JSFunction>(isolate, *object);
|
||||
if (function != NULL) maybe_function = Handle<JSFunction>(function);
|
||||
}
|
||||
return isolate->heap()->exception();
|
||||
|
||||
int length = 0;
|
||||
Handle<JSFunction> function;
|
||||
if (maybe_function.ToHandle(&function)) {
|
||||
if (function->shared()->is_compiled()) {
|
||||
length = function->shared()->length();
|
||||
} else {
|
||||
// If the function isn't compiled yet, the length is not computed
|
||||
// correctly yet. Compile it now and return the right length.
|
||||
if (Compiler::EnsureCompiled(function, KEEP_EXCEPTION)) {
|
||||
length = function->shared()->length();
|
||||
}
|
||||
if (isolate->has_pending_exception()) {
|
||||
isolate->OptionalRescheduleException(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
Handle<Object> result(Smi::FromInt(length), isolate);
|
||||
info.GetReturnValue().Set(Utils::ToLocal(result));
|
||||
}
|
||||
|
||||
|
||||
const AccessorDescriptor Accessors::FunctionLength = {
|
||||
FunctionGetLength,
|
||||
ReadOnlySetAccessor,
|
||||
0
|
||||
};
|
||||
void Accessors::FunctionLengthSetter(
|
||||
v8::Local<v8::String> name,
|
||||
v8::Local<v8::Value> val,
|
||||
const v8::PropertyCallbackInfo<void>& info) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
|
||||
Handle<AccessorInfo> Accessors::FunctionLengthInfo(
|
||||
Isolate* isolate, PropertyAttributes attributes) {
|
||||
return MakeAccessor(isolate,
|
||||
isolate->factory()->length_string(),
|
||||
&FunctionLengthGetter,
|
||||
&FunctionLengthSetter,
|
||||
attributes);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
|
@ -37,13 +37,13 @@ namespace internal {
|
||||
// The list of accessor descriptors. This is a second-order macro
|
||||
// taking a macro to be applied to all accessor descriptor names.
|
||||
#define ACCESSOR_DESCRIPTOR_LIST(V) \
|
||||
V(FunctionLength) \
|
||||
V(FunctionName) \
|
||||
V(FunctionArguments) \
|
||||
V(FunctionCaller) \
|
||||
V(ArrayLength)
|
||||
|
||||
#define ACCESSOR_INFO_LIST(V) \
|
||||
V(FunctionLength) \
|
||||
V(FunctionPrototype) \
|
||||
V(ScriptColumnOffset) \
|
||||
V(ScriptCompilationType) \
|
||||
|
@ -388,15 +388,17 @@ void Genesis::SetFunctionInstanceDescriptor(
|
||||
int size = (prototypeMode == DONT_ADD_PROTOTYPE) ? 4 : 5;
|
||||
Map::EnsureDescriptorSlack(map, size);
|
||||
|
||||
Handle<Foreign> length(factory()->NewForeign(&Accessors::FunctionLength));
|
||||
Handle<Foreign> name(factory()->NewForeign(&Accessors::FunctionName));
|
||||
Handle<Foreign> args(factory()->NewForeign(&Accessors::FunctionArguments));
|
||||
Handle<Foreign> caller(factory()->NewForeign(&Accessors::FunctionCaller));
|
||||
PropertyAttributes attribs = static_cast<PropertyAttributes>(
|
||||
DONT_ENUM | DONT_DELETE | READ_ONLY);
|
||||
|
||||
Handle<AccessorInfo> length =
|
||||
Accessors::FunctionLengthInfo(isolate(), attribs);
|
||||
{ // Add length.
|
||||
CallbacksDescriptor d(factory()->length_string(), length, attribs);
|
||||
CallbacksDescriptor d(Handle<Name>(Name::cast(length->name())),
|
||||
length, attribs);
|
||||
map->AppendDescriptor(&d);
|
||||
}
|
||||
{ // Add name.
|
||||
@ -517,7 +519,6 @@ void Genesis::SetStrictFunctionInstanceDescriptor(
|
||||
int size = (prototypeMode == DONT_ADD_PROTOTYPE) ? 4 : 5;
|
||||
Map::EnsureDescriptorSlack(map, size);
|
||||
|
||||
Handle<Foreign> length(factory()->NewForeign(&Accessors::FunctionLength));
|
||||
Handle<Foreign> name(factory()->NewForeign(&Accessors::FunctionName));
|
||||
Handle<AccessorPair> arguments(factory()->NewAccessorPair());
|
||||
Handle<AccessorPair> caller(factory()->NewAccessorPair());
|
||||
@ -526,8 +527,11 @@ void Genesis::SetStrictFunctionInstanceDescriptor(
|
||||
PropertyAttributes ro_attribs =
|
||||
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
|
||||
|
||||
Handle<AccessorInfo> length =
|
||||
Accessors::FunctionLengthInfo(isolate(), ro_attribs);
|
||||
{ // Add length.
|
||||
CallbacksDescriptor d(factory()->length_string(), length, ro_attribs);
|
||||
CallbacksDescriptor d(Handle<Name>(Name::cast(length->name())),
|
||||
length, ro_attribs);
|
||||
map->AppendDescriptor(&d);
|
||||
}
|
||||
{ // Add name.
|
||||
|
35
test/mjsunit/function-length-accessor.js
Normal file
35
test/mjsunit/function-length-accessor.js
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --harmony-scoping
|
||||
|
||||
function foo(a, b, c, d) {
|
||||
"use strict"
|
||||
const x = 10;
|
||||
// long comment to trigger lazy compilation.
|
||||
// long comment to trigger lazy compilation.
|
||||
// long comment to trigger lazy compilation.
|
||||
// long comment to trigger lazy compilation.
|
||||
// long comment to trigger lazy compilation.
|
||||
// long comment to trigger lazy compilation.
|
||||
// long comment to trigger lazy compilation.
|
||||
// long comment to trigger lazy compilation.
|
||||
// long comment to trigger lazy compilation.
|
||||
// long comment to trigger lazy compilation.
|
||||
// long comment to trigger lazy compilation.
|
||||
// long comment to trigger lazy compilation.
|
||||
// long comment to trigger lazy compilation.
|
||||
// long comment to trigger lazy compilation.
|
||||
// long comment to trigger lazy compilation.
|
||||
// long comment to trigger lazy compilation.
|
||||
// long comment to trigger lazy compilation.
|
||||
// long comment to trigger lazy compilation.
|
||||
// long comment to trigger lazy compilation.
|
||||
// long comment to trigger lazy compilation.
|
||||
// long comment to trigger lazy compilation.
|
||||
// long comment to trigger lazy compilation.
|
||||
x = 20; // This will trigger compile error with harmony scoping.
|
||||
}
|
||||
|
||||
assertThrows("foo.length()");
|
Loading…
Reference in New Issue
Block a user