Pass in the prototype to CreateApiFunction rather than setting it on the result.
BUG= R=ishell@chromium.org Review URL: https://codereview.chromium.org/253603003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@21066 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
8452271f1b
commit
22cdf0c0fd
@ -48,31 +48,29 @@ function InstantiateFunction(data, name) {
|
||||
(serialNumber in cache) && (cache[serialNumber] != kUninitialized);
|
||||
if (!isFunctionCached) {
|
||||
try {
|
||||
var fun = %CreateApiFunction(data);
|
||||
if (name) %FunctionSetName(fun, name);
|
||||
var flags = %GetTemplateField(data, kApiFlagOffset);
|
||||
var doNotCache = flags & (1 << kDoNotCacheBit);
|
||||
if (!doNotCache) cache[serialNumber] = fun;
|
||||
if (flags & (1 << kRemovePrototypeBit)) {
|
||||
%FunctionRemovePrototype(fun);
|
||||
} else {
|
||||
var prototype = %GetTemplateField(data, kApiPrototypeTemplateOffset);
|
||||
// Note: Do not directly use an object template as a condition, our
|
||||
// internal ToBoolean doesn't handle that!
|
||||
fun.prototype = typeof prototype === 'undefined' ?
|
||||
{} : Instantiate(prototype);
|
||||
if (flags & (1 << kReadOnlyPrototypeBit)) {
|
||||
%FunctionSetReadOnlyPrototype(fun);
|
||||
}
|
||||
%SetProperty(fun.prototype, "constructor", fun, DONT_ENUM);
|
||||
var has_proto = !(flags & (1 << kRemovePrototypeBit));
|
||||
var prototype;
|
||||
if (has_proto) {
|
||||
var template = %GetTemplateField(data, kApiPrototypeTemplateOffset);
|
||||
prototype = typeof template === 'undefined'
|
||||
? {} : Instantiate(template);
|
||||
|
||||
var parent = %GetTemplateField(data, kApiParentTemplateOffset);
|
||||
// Note: Do not directly use a function template as a condition, our
|
||||
// internal ToBoolean doesn't handle that!
|
||||
if (!(typeof parent === 'undefined')) {
|
||||
if (typeof parent !== 'undefined') {
|
||||
var parent_fun = Instantiate(parent);
|
||||
%SetPrototype(fun.prototype, parent_fun.prototype);
|
||||
%SetPrototype(prototype, parent_fun.prototype);
|
||||
}
|
||||
}
|
||||
var fun = %CreateApiFunction(data, prototype);
|
||||
if (name) %FunctionSetName(fun, name);
|
||||
var doNotCache = flags & (1 << kDoNotCacheBit);
|
||||
if (!doNotCache) cache[serialNumber] = fun;
|
||||
if (has_proto && flags & (1 << kReadOnlyPrototypeBit)) {
|
||||
%FunctionSetReadOnlyPrototype(fun);
|
||||
}
|
||||
ConfigureTemplateInstance(fun, data);
|
||||
if (doNotCache) return fun;
|
||||
} catch (e) {
|
||||
|
@ -729,6 +729,7 @@ Handle<JSGlobalProxy> Genesis::CreateNewGlobals(
|
||||
FunctionTemplateInfo::cast(js_global_template->constructor()));
|
||||
js_global_function =
|
||||
factory()->CreateApiFunction(js_global_constructor,
|
||||
factory()->the_hole_value(),
|
||||
factory()->InnerGlobalObject);
|
||||
}
|
||||
|
||||
@ -756,6 +757,7 @@ Handle<JSGlobalProxy> Genesis::CreateNewGlobals(
|
||||
FunctionTemplateInfo::cast(data->constructor()));
|
||||
global_proxy_function =
|
||||
factory()->CreateApiFunction(global_constructor,
|
||||
factory()->the_hole_value(),
|
||||
factory()->OuterGlobalObject);
|
||||
}
|
||||
|
||||
|
@ -1255,19 +1255,30 @@ Handle<Object> Factory::NewError(const char* constructor,
|
||||
}
|
||||
|
||||
|
||||
Handle<JSFunction> Factory::NewFunction(Handle<String> name,
|
||||
Handle<JSFunction> Factory::NewFunction(MaybeHandle<Object> maybe_prototype,
|
||||
Handle<String> name,
|
||||
InstanceType type,
|
||||
int instance_size,
|
||||
Handle<Code> code,
|
||||
bool force_initial_map) {
|
||||
// Allocate the function
|
||||
Handle<JSFunction> function = NewFunction(name, code, the_hole_value());
|
||||
Handle<JSFunction> function = NewFunction(name, code, maybe_prototype);
|
||||
|
||||
if (force_initial_map ||
|
||||
Handle<Object> prototype;
|
||||
if (maybe_prototype.ToHandle(&prototype) &&
|
||||
(force_initial_map ||
|
||||
type != JS_OBJECT_TYPE ||
|
||||
instance_size != JSObject::kHeaderSize) {
|
||||
instance_size != JSObject::kHeaderSize)) {
|
||||
Handle<Map> initial_map = NewMap(type, instance_size);
|
||||
Handle<JSObject> prototype = NewFunctionPrototype(function);
|
||||
if (prototype->IsJSObject()) {
|
||||
JSObject::SetLocalPropertyIgnoreAttributes(
|
||||
Handle<JSObject>::cast(prototype),
|
||||
constructor_string(),
|
||||
function,
|
||||
DONT_ENUM).Assert();
|
||||
} else if (!function->shared()->is_generator()) {
|
||||
prototype = NewFunctionPrototype(function);
|
||||
}
|
||||
initial_map->set_prototype(*prototype);
|
||||
function->set_initial_map(*initial_map);
|
||||
initial_map->set_constructor(*function);
|
||||
@ -1280,6 +1291,16 @@ Handle<JSFunction> Factory::NewFunction(Handle<String> name,
|
||||
}
|
||||
|
||||
|
||||
Handle<JSFunction> Factory::NewFunction(Handle<String> name,
|
||||
InstanceType type,
|
||||
int instance_size,
|
||||
Handle<Code> code,
|
||||
bool force_initial_map) {
|
||||
return NewFunction(
|
||||
the_hole_value(), name, type, instance_size, code, force_initial_map);
|
||||
}
|
||||
|
||||
|
||||
Handle<JSFunction> Factory::NewFunctionWithPrototype(Handle<String> name,
|
||||
InstanceType type,
|
||||
int instance_size,
|
||||
@ -2057,7 +2078,9 @@ Handle<JSObject> Factory::NewArgumentsObject(Handle<Object> callee,
|
||||
|
||||
|
||||
Handle<JSFunction> Factory::CreateApiFunction(
|
||||
Handle<FunctionTemplateInfo> obj, ApiInstanceType instance_type) {
|
||||
Handle<FunctionTemplateInfo> obj,
|
||||
Handle<Object> prototype,
|
||||
ApiInstanceType instance_type) {
|
||||
Handle<Code> code = isolate()->builtins()->HandleApiCall();
|
||||
Handle<Code> construct_stub = isolate()->builtins()->JSConstructStubApi();
|
||||
|
||||
@ -2093,20 +2116,31 @@ Handle<JSFunction> Factory::CreateApiFunction(
|
||||
break;
|
||||
}
|
||||
|
||||
MaybeHandle<Object> maybe_prototype = prototype;
|
||||
if (obj->remove_prototype()) maybe_prototype = MaybeHandle<Object>();
|
||||
|
||||
Handle<JSFunction> result = NewFunction(
|
||||
Factory::empty_string(), type, instance_size, code, true);
|
||||
maybe_prototype, Factory::empty_string(), type,
|
||||
instance_size, code, true);
|
||||
|
||||
// Set length.
|
||||
result->shared()->set_length(obj->length());
|
||||
|
||||
// Set class name.
|
||||
Handle<Object> class_name = Handle<Object>(obj->class_name(), isolate());
|
||||
Handle<Object> class_name(obj->class_name(), isolate());
|
||||
if (class_name->IsString()) {
|
||||
result->shared()->set_instance_class_name(*class_name);
|
||||
result->shared()->set_name(*class_name);
|
||||
}
|
||||
result->shared()->set_function_data(*obj);
|
||||
result->shared()->set_construct_stub(*construct_stub);
|
||||
result->shared()->DontAdaptArguments();
|
||||
|
||||
Handle<Map> map = Handle<Map>(result->initial_map());
|
||||
if (obj->remove_prototype()) {
|
||||
ASSERT(result->shared()->IsApiFunction());
|
||||
return result;
|
||||
}
|
||||
// Down from here is only valid for API functions that can be used as a
|
||||
// constructor (don't set the "remove prototype" flag).
|
||||
|
||||
Handle<Map> map(result->initial_map());
|
||||
|
||||
// Mark as undetectable if needed.
|
||||
if (obj->undetectable()) {
|
||||
@ -2136,10 +2170,6 @@ Handle<JSFunction> Factory::CreateApiFunction(
|
||||
map->set_has_instance_call_handler();
|
||||
}
|
||||
|
||||
result->shared()->set_function_data(*obj);
|
||||
result->shared()->set_construct_stub(*construct_stub);
|
||||
result->shared()->DontAdaptArguments();
|
||||
|
||||
// Recursively copy parent instance templates' accessors,
|
||||
// 'data' may be modified.
|
||||
int max_number_of_additional_properties = 0;
|
||||
|
@ -464,6 +464,12 @@ class Factory V8_FINAL {
|
||||
Handle<Context> context,
|
||||
PretenureFlag pretenure = TENURED);
|
||||
|
||||
Handle<JSFunction> NewFunction(MaybeHandle<Object> maybe_prototype,
|
||||
Handle<String> name,
|
||||
InstanceType type,
|
||||
int instance_size,
|
||||
Handle<Code> code,
|
||||
bool force_initial_map);
|
||||
Handle<JSFunction> NewFunction(Handle<String> name,
|
||||
InstanceType type,
|
||||
int instance_size,
|
||||
@ -551,6 +557,7 @@ class Factory V8_FINAL {
|
||||
|
||||
Handle<JSFunction> CreateApiFunction(
|
||||
Handle<FunctionTemplateInfo> data,
|
||||
Handle<Object> prototype,
|
||||
ApiInstanceType type = JavaScriptObject);
|
||||
|
||||
Handle<JSFunction> InstallMembers(Handle<JSFunction> function);
|
||||
|
@ -2112,9 +2112,10 @@ RUNTIME_FUNCTION(Runtime_RegExpCompile) {
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_CreateApiFunction) {
|
||||
HandleScope scope(isolate);
|
||||
ASSERT(args.length() == 1);
|
||||
ASSERT(args.length() == 2);
|
||||
CONVERT_ARG_HANDLE_CHECKED(FunctionTemplateInfo, data, 0);
|
||||
return *isolate->factory()->CreateApiFunction(data);
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
|
||||
return *isolate->factory()->CreateApiFunction(data, prototype);
|
||||
}
|
||||
|
||||
|
||||
@ -2786,7 +2787,8 @@ static Handle<JSFunction> InstallBuiltin(Isolate* isolate,
|
||||
Handle<String> key = isolate->factory()->InternalizeUtf8String(name);
|
||||
Handle<Code> code(isolate->builtins()->builtin(builtin_name));
|
||||
Handle<JSFunction> optimized =
|
||||
isolate->factory()->NewFunction(key,
|
||||
isolate->factory()->NewFunction(MaybeHandle<Object>(),
|
||||
key,
|
||||
JS_OBJECT_TYPE,
|
||||
JSObject::kHeaderSize,
|
||||
code,
|
||||
|
@ -202,7 +202,7 @@ namespace internal {
|
||||
F(SetCode, 2, 1) \
|
||||
F(SetExpectedNumberOfProperties, 2, 1) \
|
||||
\
|
||||
F(CreateApiFunction, 1, 1) \
|
||||
F(CreateApiFunction, 2, 1) \
|
||||
F(IsTemplate, 1, 1) \
|
||||
F(GetTemplateField, 2, 1) \
|
||||
F(DisableAccessChecks, 1, 1) \
|
||||
|
Loading…
Reference in New Issue
Block a user