From 1e1387f12c8822a2df0d024e938f1b6874c50f25 Mon Sep 17 00:00:00 2001 From: "jkummerow@chromium.org" Date: Wed, 22 Jun 2011 12:39:45 +0000 Subject: [PATCH] Add possibility to configure 'prototype' property via FunctionTemplate BUG=v8:1479 TEST=test-api/SetPrototypeProperties Review URL: http://codereview.chromium.org/7229007 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8366 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- include/v8.h | 7 +++++++ src/api.cc | 12 ++++++++++++ src/apinatives.js | 10 +++++++++- src/macros.py | 13 +++++++------ src/objects-inl.h | 2 ++ src/objects.h | 4 +++- test/cctest/test-api.cc | 50 +++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 90 insertions(+), 8 deletions(-) diff --git a/include/v8.h b/include/v8.h index c3bccdc..7862869 100644 --- a/include/v8.h +++ b/include/v8.h @@ -2144,6 +2144,13 @@ class V8EXPORT FunctionTemplate : public Template { void SetHiddenPrototype(bool value); /** + * Sets the property attributes of the 'prototype' property of functions + * created from this FunctionTemplate. Can be any combination of ReadOnly, + * DontEnum and DontDelete. + */ + void SetPrototypeAttributes(int attributes); + + /** * Returns true if the given object is an instance of this function * template. */ diff --git a/src/api.cc b/src/api.cc index 3fe5621..f8a7dfa 100644 --- a/src/api.cc +++ b/src/api.cc @@ -884,6 +884,7 @@ static void InitializeFunctionTemplate( i::Handle info) { info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE)); info->set_flag(0); + info->set_prototype_attributes(i::Smi::FromInt(v8::None)); } @@ -1106,6 +1107,17 @@ void FunctionTemplate::SetHiddenPrototype(bool value) { } +void FunctionTemplate::SetPrototypeAttributes(int attributes) { + i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); + if (IsDeadCheck(isolate, "v8::FunctionTemplate::SetPrototypeAttributes()")) { + return; + } + ENTER_V8(isolate); + Utils::OpenHandle(this)->set_prototype_attributes( + i::Smi::FromInt(attributes)); +} + + void FunctionTemplate::SetNamedInstancePropertyHandler( NamedPropertyGetter getter, NamedPropertySetter setter, diff --git a/src/apinatives.js b/src/apinatives.js index ca2bbf5..193863f 100644 --- a/src/apinatives.js +++ b/src/apinatives.js @@ -73,7 +73,15 @@ function InstantiateFunction(data, name) { if (name) %FunctionSetName(fun, name); cache[serialNumber] = fun; var prototype = %GetTemplateField(data, kApiPrototypeTemplateOffset); - fun.prototype = prototype ? Instantiate(prototype) : {}; + var attributes = %GetTemplateField(data, kApiPrototypeAttributesOffset); + if (attributes != NONE) { + %IgnoreAttributesAndSetProperty( + fun, "prototype", + prototype ? Instantiate(prototype) : {}, + attributes); + } else { + fun.prototype = prototype ? Instantiate(prototype) : {}; + } %SetProperty(fun.prototype, "constructor", fun, DONT_ENUM); var parent = %GetTemplateField(data, kApiParentTemplateOffset); if (parent) { diff --git a/src/macros.py b/src/macros.py index 3905659..fc08cb1 100644 --- a/src/macros.py +++ b/src/macros.py @@ -38,12 +38,13 @@ const GETTER = 0; const SETTER = 1; # These definitions must match the index of the properties in objects.h. -const kApiTagOffset = 0; -const kApiPropertyListOffset = 1; -const kApiSerialNumberOffset = 2; -const kApiConstructorOffset = 2; -const kApiPrototypeTemplateOffset = 5; -const kApiParentTemplateOffset = 6; +const kApiTagOffset = 0; +const kApiPropertyListOffset = 1; +const kApiSerialNumberOffset = 2; +const kApiConstructorOffset = 2; +const kApiPrototypeTemplateOffset = 5; +const kApiParentTemplateOffset = 6; +const kApiPrototypeAttributesOffset = 15; const NO_HINT = 0; const NUMBER_HINT = 1; diff --git a/src/objects-inl.h b/src/objects-inl.h index 5ebf8f8..0198dc1 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -3232,6 +3232,8 @@ ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object, ACCESSORS(FunctionTemplateInfo, access_check_info, Object, kAccessCheckInfoOffset) ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset) +ACCESSORS(FunctionTemplateInfo, prototype_attributes, Smi, + kPrototypeAttributesOffset) ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset) ACCESSORS(ObjectTemplateInfo, internal_field_count, Object, diff --git a/src/objects.h b/src/objects.h index 4d1f68d..d1df8ba 100644 --- a/src/objects.h +++ b/src/objects.h @@ -6786,6 +6786,7 @@ class FunctionTemplateInfo: public TemplateInfo { DECL_ACCESSORS(instance_call_handler, Object) DECL_ACCESSORS(access_check_info, Object) DECL_ACCESSORS(flag, Smi) + DECL_ACCESSORS(prototype_attributes, Smi) // Following properties use flag bits. DECL_BOOLEAN_ACCESSORS(hidden_prototype) @@ -6825,7 +6826,8 @@ class FunctionTemplateInfo: public TemplateInfo { static const int kAccessCheckInfoOffset = kInstanceCallHandlerOffset + kPointerSize; static const int kFlagOffset = kAccessCheckInfoOffset + kPointerSize; - static const int kSize = kFlagOffset + kPointerSize; + static const int kPrototypeAttributesOffset = kFlagOffset + kPointerSize; + static const int kSize = kPrototypeAttributesOffset + kPointerSize; private: // Bit position in the flag, from least significant bit position. diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index e0bcbc9..de2c203 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -6842,6 +6842,56 @@ THREADED_TEST(SetPrototype) { } +THREADED_TEST(SetPrototypeProperties) { + v8::HandleScope handle_scope; + LocalContext context; + + Local t1 = v8::FunctionTemplate::New(); + t1->SetPrototypeAttributes(v8::DontDelete); + context->Global()->Set(v8_str("func1"), t1->GetFunction()); + CHECK(CompileRun( + "(function() {" + " descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');" + " return (descriptor['writable'] == true) &&" + " (descriptor['enumerable'] == true) &&" + " (descriptor['configurable'] == false);" + "})()")->BooleanValue()); + + Local t2 = v8::FunctionTemplate::New(); + t2->SetPrototypeAttributes(v8::DontEnum); + context->Global()->Set(v8_str("func2"), t2->GetFunction()); + CHECK(CompileRun( + "(function() {" + " descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');" + " return (descriptor['writable'] == true) &&" + " (descriptor['enumerable'] == false) &&" + " (descriptor['configurable'] == true);" + "})()")->BooleanValue()); + + Local t3 = v8::FunctionTemplate::New(); + t3->SetPrototypeAttributes(v8::ReadOnly); + context->Global()->Set(v8_str("func3"), t3->GetFunction()); + CHECK(CompileRun( + "(function() {" + " descriptor = Object.getOwnPropertyDescriptor(func3, 'prototype');" + " return (descriptor['writable'] == false) &&" + " (descriptor['enumerable'] == true) &&" + " (descriptor['configurable'] == true);" + "})()")->BooleanValue()); + + Local t4 = v8::FunctionTemplate::New(); + t4->SetPrototypeAttributes(v8::ReadOnly | v8::DontEnum | v8::DontDelete); + context->Global()->Set(v8_str("func4"), t4->GetFunction()); + CHECK(CompileRun( + "(function() {" + " descriptor = Object.getOwnPropertyDescriptor(func4, 'prototype');" + " return (descriptor['writable'] == false) &&" + " (descriptor['enumerable'] == false) &&" + " (descriptor['configurable'] == false);" + "})()")->BooleanValue()); +} + + THREADED_TEST(SetPrototypeThrows) { v8::HandleScope handle_scope; LocalContext context; -- 2.7.4