Add RemovePrototype to FunctionTemplate

This allows functions created from a FunctionTemplate to not have a
prototype property, which is required by DOM methods.

R=mstarzinger@chromium.org
BUG=chromium:272440

Review URL: https://codereview.chromium.org/22990003

Patch from Erik Arvidsson <arv@chromium.org>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16341 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent fcdf3bdb
......@@ -3430,6 +3430,12 @@ class V8_EXPORT FunctionTemplate : public Template {
*/
void ReadOnlyPrototype();
/**
* Removes the prototype property from functions created from this
* FunctionTemplate.
*/
void RemovePrototype();
/**
* Returns true if the given object is an instance of this function
* template.
......
......@@ -1451,6 +1451,17 @@ void FunctionTemplate::ReadOnlyPrototype() {
Utils::OpenHandle(this)->set_read_only_prototype(true);
}
void FunctionTemplate::RemovePrototype() {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
if (IsDeadCheck(isolate, "v8::FunctionTemplate::RemovePrototype()")) {
return;
}
ENTER_V8(isolate);
Utils::OpenHandle(this)->set_remove_prototype(true);
}
template<
typename Getter,
typename Setter,
......
......@@ -75,22 +75,26 @@ function InstantiateFunction(data, name) {
var fun = %CreateApiFunction(data);
if (name) %FunctionSetName(fun, name);
cache[serialNumber] = fun;
var prototype = %GetTemplateField(data, kApiPrototypeTemplateOffset);
var flags = %GetTemplateField(data, kApiFlagOffset);
// 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 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')) {
var parent_fun = Instantiate(parent);
%SetPrototype(fun.prototype, parent_fun.prototype);
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 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')) {
var parent_fun = Instantiate(parent);
%SetPrototype(fun.prototype, parent_fun.prototype);
}
}
ConfigureTemplateInstance(fun, data);
} catch (e) {
......
......@@ -67,7 +67,8 @@ const msPerMonth = 2592000000;
# For apinatives.js
const kUninitialized = -1;
const kReadOnlyPrototypeBit = 3; # For FunctionTemplateInfo, matches objects.h
const kReadOnlyPrototypeBit = 3;
const kRemovePrototypeBit = 4; # For FunctionTemplateInfo, matches objects.h
# Note: kDayZeroInJulianDay = ToJulianDay(1970, 0, 1).
const kInvalidDate = 'Invalid Date';
......
......@@ -4576,6 +4576,8 @@ BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
kNeedsAccessCheckBit)
BOOL_ACCESSORS(FunctionTemplateInfo, flag, read_only_prototype,
kReadOnlyPrototypeBit)
BOOL_ACCESSORS(FunctionTemplateInfo, flag, remove_prototype,
kRemovePrototypeBit)
BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
kIsExpressionBit)
BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
......
......@@ -9874,6 +9874,7 @@ class FunctionTemplateInfo: public TemplateInfo {
// requires access check.
DECL_BOOLEAN_ACCESSORS(needs_access_check)
DECL_BOOLEAN_ACCESSORS(read_only_prototype)
DECL_BOOLEAN_ACCESSORS(remove_prototype)
static inline FunctionTemplateInfo* cast(Object* obj);
......@@ -9909,6 +9910,7 @@ class FunctionTemplateInfo: public TemplateInfo {
static const int kUndetectableBit = 1;
static const int kNeedsAccessCheckBit = 2;
static const int kReadOnlyPrototypeBit = 3;
static const int kRemovePrototypeBit = 4;
DISALLOW_IMPLICIT_CONSTRUCTORS(FunctionTemplateInfo);
};
......
......@@ -9608,6 +9608,26 @@ THREADED_TEST(SetPrototypeThrows) {
}
THREADED_TEST(FunctionRemovePrototype) {
LocalContext context;
v8::HandleScope handle_scope(context->GetIsolate());
Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
t1->RemovePrototype();
Local<v8::Function> fun = t1->GetFunction();
context->Global()->Set(v8_str("fun"), fun);
CHECK(!CompileRun("'prototype' in fun")->BooleanValue());
v8::TryCatch try_catch;
CompileRun("new fun()");
CHECK(try_catch.HasCaught());
try_catch.Reset();
fun->NewInstance();
CHECK(try_catch.HasCaught());
}
THREADED_TEST(GetterSetterExceptions) {
LocalContext context;
v8::HandleScope handle_scope(context->GetIsolate());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment