From fc68cb74e52c1044b0ba1caf97072a4959c3ed52 Mon Sep 17 00:00:00 2001 From: "mstarzinger@chromium.org" Date: Mon, 26 Aug 2013 17:40:03 +0000 Subject: [PATCH] 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 . git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16341 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- include/v8.h | 6 ++++++ src/api.cc | 11 +++++++++++ src/apinatives.js | 34 +++++++++++++++++++--------------- src/macros.py | 3 ++- src/objects-inl.h | 2 ++ src/objects.h | 2 ++ test/cctest/test-api.cc | 20 ++++++++++++++++++++ 7 files changed, 62 insertions(+), 16 deletions(-) diff --git a/include/v8.h b/include/v8.h index dbf2b08..31fa38a 100644 --- a/include/v8.h +++ b/include/v8.h @@ -3431,6 +3431,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. */ diff --git a/src/api.cc b/src/api.cc index 61cc520..de9d075 100644 --- a/src/api.cc +++ b/src/api.cc @@ -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, diff --git a/src/apinatives.js b/src/apinatives.js index ace882b..7adeb7e 100644 --- a/src/apinatives.js +++ b/src/apinatives.js @@ -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) { diff --git a/src/macros.py b/src/macros.py index d50231d..f1a2130 100644 --- a/src/macros.py +++ b/src/macros.py @@ -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'; diff --git a/src/objects-inl.h b/src/objects-inl.h index 22d1ac3..13ae603 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -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, diff --git a/src/objects.h b/src/objects.h index 411908c..4685dc7 100644 --- a/src/objects.h +++ b/src/objects.h @@ -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); }; diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index 192f114..c9043cf 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -9608,6 +9608,26 @@ THREADED_TEST(SetPrototypeThrows) { } +THREADED_TEST(FunctionRemovePrototype) { + LocalContext context; + v8::HandleScope handle_scope(context->GetIsolate()); + + Local t1 = v8::FunctionTemplate::New(); + t1->RemovePrototype(); + Local 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()); -- 2.7.4