Added ability to remove prototype from function. In this case, [[Construct]] from function will not be allowed.
Added runtime function %FunctionRemovePrototype for this. Removed prototypes from all builtin functions. Some sputnik tests marked as fixed. Added test to check builtins behavior. Review URL: http://codereview.chromium.org/1722003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4536 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
ffedb9ea3f
commit
8fee5e810a
@ -248,9 +248,13 @@ class Genesis BASE_EMBEDDED {
|
||||
void TransferNamedProperties(Handle<JSObject> from, Handle<JSObject> to);
|
||||
void TransferIndexedProperties(Handle<JSObject> from, Handle<JSObject> to);
|
||||
|
||||
enum PrototypePropertyMode {
|
||||
DONT_ADD_PROTOTYPE,
|
||||
ADD_READONLY_PROTOTYPE,
|
||||
ADD_WRITEABLE_PROTOTYPE
|
||||
};
|
||||
Handle<DescriptorArray> ComputeFunctionInstanceDescriptor(
|
||||
bool make_prototype_read_only,
|
||||
bool make_prototype_enumerable = false);
|
||||
PrototypePropertyMode prototypeMode);
|
||||
void MakeFunctionInstancePrototypeWritable();
|
||||
|
||||
static bool CompileBuiltin(int index);
|
||||
@ -330,7 +334,8 @@ static Handle<JSFunction> InstallFunction(Handle<JSObject> target,
|
||||
bool is_ecma_native) {
|
||||
Handle<String> symbol = Factory::LookupAsciiSymbol(name);
|
||||
Handle<Code> call_code = Handle<Code>(Builtins::builtin(call));
|
||||
Handle<JSFunction> function =
|
||||
Handle<JSFunction> function = prototype.is_null() ?
|
||||
Factory::NewFunctionWithoutPrototype(symbol, call_code) :
|
||||
Factory::NewFunctionWithPrototype(symbol,
|
||||
type,
|
||||
instance_size,
|
||||
@ -346,23 +351,23 @@ static Handle<JSFunction> InstallFunction(Handle<JSObject> target,
|
||||
|
||||
|
||||
Handle<DescriptorArray> Genesis::ComputeFunctionInstanceDescriptor(
|
||||
bool make_prototype_read_only,
|
||||
bool make_prototype_enumerable) {
|
||||
PrototypePropertyMode prototypeMode) {
|
||||
Handle<DescriptorArray> result = Factory::empty_descriptor_array();
|
||||
|
||||
// Add prototype.
|
||||
if (prototypeMode != DONT_ADD_PROTOTYPE) {
|
||||
PropertyAttributes attributes = static_cast<PropertyAttributes>(
|
||||
(make_prototype_enumerable ? 0 : DONT_ENUM)
|
||||
| DONT_DELETE
|
||||
| (make_prototype_read_only ? READ_ONLY : 0));
|
||||
DONT_ENUM |
|
||||
DONT_DELETE |
|
||||
(prototypeMode == ADD_READONLY_PROTOTYPE ? READ_ONLY : 0));
|
||||
result =
|
||||
Factory::CopyAppendProxyDescriptor(
|
||||
result,
|
||||
Factory::prototype_symbol(),
|
||||
Factory::NewProxy(&Accessors::FunctionPrototype),
|
||||
attributes);
|
||||
}
|
||||
|
||||
attributes =
|
||||
PropertyAttributes attributes =
|
||||
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
|
||||
// Add length.
|
||||
result =
|
||||
@ -407,14 +412,26 @@ Handle<JSFunction> Genesis::CreateEmptyFunction() {
|
||||
// Please note that the prototype property for function instances must be
|
||||
// writable.
|
||||
Handle<DescriptorArray> function_map_descriptors =
|
||||
ComputeFunctionInstanceDescriptor(false, false);
|
||||
ComputeFunctionInstanceDescriptor(ADD_WRITEABLE_PROTOTYPE);
|
||||
fm->set_instance_descriptors(*function_map_descriptors);
|
||||
fm->set_function_with_prototype(true);
|
||||
|
||||
// Functions with this map will not have a 'prototype' property, and
|
||||
// can not be used as constructors.
|
||||
fm = Factory::NewMap(JS_FUNCTION_TYPE, JSFunction::kSize);
|
||||
global_context()->set_function_without_prototype_map(*fm);
|
||||
function_map_descriptors =
|
||||
ComputeFunctionInstanceDescriptor(DONT_ADD_PROTOTYPE);
|
||||
fm->set_instance_descriptors(*function_map_descriptors);
|
||||
fm->set_function_with_prototype(false);
|
||||
|
||||
// Allocate the function map first and then patch the prototype later
|
||||
fm = Factory::NewMap(JS_FUNCTION_TYPE, JSFunction::kSize);
|
||||
global_context()->set_function_map(*fm);
|
||||
function_map_descriptors = ComputeFunctionInstanceDescriptor(true);
|
||||
function_map_descriptors =
|
||||
ComputeFunctionInstanceDescriptor(ADD_READONLY_PROTOTYPE);
|
||||
fm->set_instance_descriptors(*function_map_descriptors);
|
||||
fm->set_function_with_prototype(true);
|
||||
|
||||
Handle<String> object_name = Handle<String>(Heap::Object_symbol());
|
||||
|
||||
@ -458,6 +475,11 @@ Handle<JSFunction> Genesis::CreateEmptyFunction() {
|
||||
global_context()->function_map()->set_prototype(*empty_function);
|
||||
global_context()->function_instance_map()->set_prototype(*empty_function);
|
||||
|
||||
// Allocate a distinct prototype for the function map for functions without
|
||||
// prototype, so it will not add 'prototype' property in the proto chain.
|
||||
global_context()->function_without_prototype_map()->set_prototype(
|
||||
*Factory::NewJSObject(Top::object_function(), TENURED));
|
||||
|
||||
// Allocate the function map first and then patch the prototype later
|
||||
Handle<Map> empty_fm = Factory::CopyMapDropDescriptors(fm);
|
||||
empty_fm->set_instance_descriptors(*function_map_descriptors);
|
||||
@ -1215,12 +1237,12 @@ bool Genesis::InstallNatives() {
|
||||
// Install the call and the apply functions.
|
||||
Handle<JSFunction> call =
|
||||
InstallFunction(proto, "call", JS_OBJECT_TYPE, JSObject::kHeaderSize,
|
||||
Factory::NewJSObject(Top::object_function(), TENURED),
|
||||
Handle<JSObject>::null(),
|
||||
Builtins::FunctionCall,
|
||||
false);
|
||||
Handle<JSFunction> apply =
|
||||
InstallFunction(proto, "apply", JS_OBJECT_TYPE, JSObject::kHeaderSize,
|
||||
Factory::NewJSObject(Top::object_function(), TENURED),
|
||||
Handle<JSObject>::null(),
|
||||
Builtins::FunctionApply,
|
||||
false);
|
||||
|
||||
@ -1236,6 +1258,23 @@ bool Genesis::InstallNatives() {
|
||||
// Set the lengths for the functions to satisfy ECMA-262.
|
||||
call->shared()->set_length(1);
|
||||
apply->shared()->set_length(2);
|
||||
|
||||
// Install the call, apply, toString and constructor properties
|
||||
// for the functions without prototype.
|
||||
Handle<JSObject> wp_proto = Handle<JSObject>(
|
||||
JSObject::cast(Top::function_without_prototype_map()->prototype()));
|
||||
|
||||
Handle<String> call_symbol = Factory::LookupAsciiSymbol("call");
|
||||
SetProperty(wp_proto, call_symbol, call, DONT_ENUM);
|
||||
|
||||
Handle<String> apply_symbol = Factory::LookupAsciiSymbol("apply");
|
||||
SetProperty(wp_proto, apply_symbol, apply, DONT_ENUM);
|
||||
|
||||
Handle<Object> to_string = GetProperty(proto, "toString");
|
||||
Handle<String> to_string_symbol = Factory::LookupAsciiSymbol("toString");
|
||||
SetProperty(wp_proto, to_string_symbol, to_string, DONT_ENUM);
|
||||
|
||||
SetProperty(wp_proto, Factory::constructor_symbol(), function, DONT_ENUM);
|
||||
}
|
||||
|
||||
// Create a constructor for RegExp results (a variant of Array that
|
||||
@ -1655,9 +1694,10 @@ void Genesis::MakeFunctionInstancePrototypeWritable() {
|
||||
HandleScope scope;
|
||||
|
||||
Handle<DescriptorArray> function_map_descriptors =
|
||||
ComputeFunctionInstanceDescriptor(false);
|
||||
ComputeFunctionInstanceDescriptor(ADD_WRITEABLE_PROTOTYPE);
|
||||
Handle<Map> fm = Factory::CopyMapDropDescriptors(Top::function_map());
|
||||
fm->set_instance_descriptors(*function_map_descriptors);
|
||||
fm->set_function_with_prototype(true);
|
||||
Top::context()->global_context()->set_function_map(*fm);
|
||||
}
|
||||
|
||||
|
@ -74,6 +74,7 @@ enum ContextLookupFlags {
|
||||
V(INSTANTIATE_FUN_INDEX, JSFunction, instantiate_fun) \
|
||||
V(CONFIGURE_INSTANCE_FUN_INDEX, JSFunction, configure_instance_fun) \
|
||||
V(FUNCTION_MAP_INDEX, Map, function_map) \
|
||||
V(FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map, function_without_prototype_map) \
|
||||
V(FUNCTION_INSTANCE_MAP_INDEX, Map, function_instance_map) \
|
||||
V(JS_ARRAY_MAP_INDEX, Map, js_array_map)\
|
||||
V(REGEXP_RESULT_MAP_INDEX, Map, regexp_result_map)\
|
||||
@ -179,6 +180,7 @@ class Context: public FixedArray {
|
||||
JS_ARRAY_MAP_INDEX,
|
||||
REGEXP_RESULT_MAP_INDEX,
|
||||
FUNCTION_MAP_INDEX,
|
||||
FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX,
|
||||
FUNCTION_INSTANCE_MAP_INDEX,
|
||||
INITIAL_OBJECT_PROTOTYPE_INDEX,
|
||||
BOOLEAN_FUNCTION_INDEX,
|
||||
|
@ -513,6 +513,16 @@ Handle<JSFunction> Factory::NewFunctionWithPrototype(Handle<String> name,
|
||||
}
|
||||
|
||||
|
||||
Handle<JSFunction> Factory::NewFunctionWithoutPrototype(Handle<String> name,
|
||||
Handle<Code> code) {
|
||||
Handle<JSFunction> function = NewFunctionWithoutPrototype(name);
|
||||
function->set_code(*code);
|
||||
ASSERT(!function->has_initial_map());
|
||||
ASSERT(!function->has_prototype());
|
||||
return function;
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> Factory::NewCode(const CodeDesc& desc,
|
||||
ZoneScopeInfo* sinfo,
|
||||
Code::Flags flags,
|
||||
@ -705,6 +715,24 @@ Handle<JSFunction> Factory::NewFunction(Handle<String> name,
|
||||
}
|
||||
|
||||
|
||||
Handle<JSFunction> Factory::NewFunctionWithoutPrototypeHelper(
|
||||
Handle<String> name) {
|
||||
Handle<SharedFunctionInfo> function_share = NewSharedFunctionInfo(name);
|
||||
CALL_HEAP_FUNCTION(Heap::AllocateFunction(
|
||||
*Top::function_without_prototype_map(),
|
||||
*function_share,
|
||||
*the_hole_value()),
|
||||
JSFunction);
|
||||
}
|
||||
|
||||
|
||||
Handle<JSFunction> Factory::NewFunctionWithoutPrototype(Handle<String> name) {
|
||||
Handle<JSFunction> fun = NewFunctionWithoutPrototypeHelper(name);
|
||||
fun->set_context(Top::context()->global_context());
|
||||
return fun;
|
||||
}
|
||||
|
||||
|
||||
Handle<Object> Factory::ToObject(Handle<Object> object) {
|
||||
CALL_HEAP_FUNCTION(object->ToObject(), Object);
|
||||
}
|
||||
|
@ -218,6 +218,8 @@ class Factory : public AllStatic {
|
||||
static Handle<JSFunction> NewFunction(Handle<String> name,
|
||||
Handle<Object> prototype);
|
||||
|
||||
static Handle<JSFunction> NewFunctionWithoutPrototype(Handle<String> name);
|
||||
|
||||
static Handle<JSFunction> NewFunction(Handle<Object> super, bool is_global);
|
||||
|
||||
static Handle<JSFunction> BaseNewFunctionFromSharedFunctionInfo(
|
||||
@ -291,6 +293,9 @@ class Factory : public AllStatic {
|
||||
Handle<Code> code,
|
||||
bool force_initial_map);
|
||||
|
||||
static Handle<JSFunction> NewFunctionWithoutPrototype(Handle<String> name,
|
||||
Handle<Code> code);
|
||||
|
||||
static Handle<DescriptorArray> CopyAppendProxyDescriptor(
|
||||
Handle<DescriptorArray> array,
|
||||
Handle<String> key,
|
||||
@ -376,6 +381,9 @@ class Factory : public AllStatic {
|
||||
static Handle<JSFunction> NewFunctionHelper(Handle<String> name,
|
||||
Handle<Object> prototype);
|
||||
|
||||
static Handle<JSFunction> NewFunctionWithoutPrototypeHelper(
|
||||
Handle<String> name);
|
||||
|
||||
static Handle<DescriptorArray> CopyAppendCallbackDescriptors(
|
||||
Handle<DescriptorArray> array,
|
||||
Handle<Object> descriptors);
|
||||
|
@ -203,6 +203,7 @@ void FlattenString(Handle<String> string) {
|
||||
|
||||
Handle<Object> SetPrototype(Handle<JSFunction> function,
|
||||
Handle<Object> prototype) {
|
||||
ASSERT(function->should_have_prototype());
|
||||
CALL_HEAP_FUNCTION(Accessors::FunctionSetPrototype(*function,
|
||||
*prototype,
|
||||
NULL),
|
||||
|
@ -615,7 +615,8 @@ Object* LoadIC::Load(State state, Handle<Object> object, Handle<String> name) {
|
||||
}
|
||||
|
||||
// Use specialized code for getting prototype of functions.
|
||||
if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol())) {
|
||||
if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol()) &&
|
||||
JSFunction::cast(*object)->should_have_prototype()) {
|
||||
#ifdef DEBUG
|
||||
if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n");
|
||||
#endif
|
||||
@ -824,7 +825,8 @@ Object* KeyedLoadIC::Load(State state,
|
||||
}
|
||||
|
||||
// Use specialized code for getting prototype of functions.
|
||||
if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol())) {
|
||||
if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol()) &&
|
||||
JSFunction::cast(*object)->should_have_prototype()) {
|
||||
Handle<JSFunction> function = Handle<JSFunction>::cast(object);
|
||||
Object* code =
|
||||
StubCache::ComputeKeyedLoadFunctionPrototype(*name, *function);
|
||||
|
@ -2113,6 +2113,20 @@ bool Map::has_non_instance_prototype() {
|
||||
}
|
||||
|
||||
|
||||
void Map::set_function_with_prototype(bool value) {
|
||||
if (value) {
|
||||
set_bit_field2(bit_field2() | (1 << kFunctionWithPrototype));
|
||||
} else {
|
||||
set_bit_field2(bit_field2() & ~(1 << kFunctionWithPrototype));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Map::function_with_prototype() {
|
||||
return ((1 << kFunctionWithPrototype) & bit_field2()) != 0;
|
||||
}
|
||||
|
||||
|
||||
void Map::set_is_access_check_needed(bool access_check_needed) {
|
||||
if (access_check_needed) {
|
||||
set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
|
||||
@ -2568,6 +2582,10 @@ Object* JSFunction::prototype() {
|
||||
return instance_prototype();
|
||||
}
|
||||
|
||||
bool JSFunction::should_have_prototype() {
|
||||
return map()->function_with_prototype();
|
||||
}
|
||||
|
||||
|
||||
bool JSFunction::is_compiled() {
|
||||
return shared()->is_compiled();
|
||||
|
@ -4906,6 +4906,7 @@ Object* JSFunction::SetInstancePrototype(Object* value) {
|
||||
|
||||
|
||||
Object* JSFunction::SetPrototype(Object* value) {
|
||||
ASSERT(should_have_prototype());
|
||||
Object* construct_prototype = value;
|
||||
|
||||
// If the value is not a JSObject, store the value in the map's
|
||||
@ -4931,6 +4932,14 @@ Object* JSFunction::SetPrototype(Object* value) {
|
||||
}
|
||||
|
||||
|
||||
Object* JSFunction::RemovePrototype() {
|
||||
ASSERT(map() == context()->global_context()->function_map());
|
||||
set_map(context()->global_context()->function_without_prototype_map());
|
||||
set_prototype_or_initial_map(Heap::the_hole_value());
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
Object* JSFunction::SetInstanceClassName(String* name) {
|
||||
shared()->set_instance_class_name(name);
|
||||
return this;
|
||||
|
@ -2854,6 +2854,12 @@ class Map: public HeapObject {
|
||||
inline void set_non_instance_prototype(bool value);
|
||||
inline bool has_non_instance_prototype();
|
||||
|
||||
// Tells whether function has special prototype property. If not, prototype
|
||||
// property will not be created when accessed (will return undefined),
|
||||
// and construction from this function will not be allowed.
|
||||
inline void set_function_with_prototype(bool value);
|
||||
inline bool function_with_prototype();
|
||||
|
||||
// Tells whether the instance with this map should be ignored by the
|
||||
// __proto__ accessor.
|
||||
inline void set_is_hidden_prototype() {
|
||||
@ -3030,6 +3036,7 @@ class Map: public HeapObject {
|
||||
|
||||
// Bit positions for bit field 2
|
||||
static const int kIsExtensible = 0;
|
||||
static const int kFunctionWithPrototype = 1;
|
||||
|
||||
// Layout of the default cache. It holds alternating name and code objects.
|
||||
static const int kCodeCacheEntrySize = 2;
|
||||
@ -3396,6 +3403,11 @@ class JSFunction: public JSObject {
|
||||
Object* SetInstancePrototype(Object* value);
|
||||
Object* SetPrototype(Object* value);
|
||||
|
||||
// After prototype is removed, it will not be created when accessed, and
|
||||
// [[Construct]] from this function will not be allowed.
|
||||
Object* RemovePrototype();
|
||||
inline bool should_have_prototype();
|
||||
|
||||
// Accessor for this function's initial map's [[class]]
|
||||
// property. This is primarily used by ECMA native functions. This
|
||||
// method sets the class_name field of this function's initial map
|
||||
|
@ -1450,6 +1450,18 @@ static Object* Runtime_FunctionSetName(Arguments args) {
|
||||
}
|
||||
|
||||
|
||||
static Object* Runtime_FunctionRemovePrototype(Arguments args) {
|
||||
NoHandleAllocation ha;
|
||||
ASSERT(args.length() == 1);
|
||||
|
||||
CONVERT_CHECKED(JSFunction, f, args[0]);
|
||||
Object* obj = f->RemovePrototype();
|
||||
if (obj->IsFailure()) return obj;
|
||||
|
||||
return Heap::undefined_value();
|
||||
}
|
||||
|
||||
|
||||
static Object* Runtime_FunctionGetScript(Arguments args) {
|
||||
HandleScope scope;
|
||||
ASSERT(args.length() == 1);
|
||||
@ -1523,6 +1535,7 @@ static Object* Runtime_FunctionSetPrototype(Arguments args) {
|
||||
ASSERT(args.length() == 2);
|
||||
|
||||
CONVERT_CHECKED(JSFunction, fun, args[0]);
|
||||
ASSERT(fun->should_have_prototype());
|
||||
Object* obj = Accessors::FunctionSetPrototype(fun, args[1], NULL);
|
||||
if (obj->IsFailure()) return obj;
|
||||
return args[0]; // return TOS
|
||||
@ -6541,6 +6554,16 @@ static Object* Runtime_NewObject(Arguments args) {
|
||||
}
|
||||
|
||||
Handle<JSFunction> function = Handle<JSFunction>::cast(constructor);
|
||||
|
||||
// If function should not have prototype, construction is not allowed. In this
|
||||
// case generated code bailouts here, since function has no initial_map.
|
||||
if (!function->should_have_prototype()) {
|
||||
Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
|
||||
Handle<Object> type_error =
|
||||
Factory::NewTypeError("not_constructor", arguments);
|
||||
return Top::Throw(*type_error);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_DEBUGGER_SUPPORT
|
||||
// Handle stepping into constructors if step into is active.
|
||||
if (Debug::StepInActive()) {
|
||||
|
@ -184,6 +184,7 @@ namespace internal {
|
||||
F(FunctionSetPrototype, 2, 1) \
|
||||
F(FunctionGetName, 1, 1) \
|
||||
F(FunctionSetName, 2, 1) \
|
||||
F(FunctionRemovePrototype, 1, 1) \
|
||||
F(FunctionGetSourceCode, 1, 1) \
|
||||
F(FunctionGetScript, 1, 1) \
|
||||
F(FunctionGetScriptSourcePosition, 1, 1) \
|
||||
|
@ -54,6 +54,7 @@ function InstallFunctions(object, attributes, functions) {
|
||||
var key = functions[i];
|
||||
var f = functions[i + 1];
|
||||
%FunctionSetName(f, key);
|
||||
%FunctionRemovePrototype(f);
|
||||
%SetProperty(object, key, f, attributes);
|
||||
}
|
||||
%ToFastProperties(object);
|
||||
|
54
test/mjsunit/function-without-prototype.js
Normal file
54
test/mjsunit/function-without-prototype.js
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Tests that function does not have prototype.
|
||||
function testPrototype(f) {
|
||||
assertFalse('prototype' in f);
|
||||
assertEquals(undefined, f.prototype);
|
||||
f.prototype = 42;
|
||||
assertEquals(42, f.prototype);
|
||||
assertTrue('prototype' in f);
|
||||
}
|
||||
|
||||
// Tests that construction from function throws.
|
||||
function testConstruction(name) {
|
||||
assertThrows("new " + name + "()");
|
||||
eval(name + ".prototype = 42;");
|
||||
assertThrows("new " + name + "()");
|
||||
}
|
||||
|
||||
testPrototype(eval);
|
||||
testPrototype(Array.prototype.push);
|
||||
testPrototype(Function.prototype.call);
|
||||
testPrototype(String.fromCharCode);
|
||||
var date = new Date();
|
||||
testPrototype(date.toString);
|
||||
|
||||
testConstruction("parseInt");
|
||||
testConstruction("Function.prototype.apply");
|
||||
var regexp = /abc/g;
|
||||
testConstruction("regexp.test");
|
@ -54,79 +54,6 @@ S15.10.6.3_A1_T16: FAIL_OK
|
||||
S15.10.7_A1_T1: FAIL_OK
|
||||
S15.10.7_A1_T2: FAIL_OK
|
||||
|
||||
# We allow construct calls to built-in functions, and we allow built-in
|
||||
# functions to have prototypes.
|
||||
S15.1.2.1_A4.6: FAIL_OK
|
||||
S15.1.2.1_A4.7: FAIL_OK
|
||||
S15.1.2.2_A9.6: FAIL_OK
|
||||
S15.1.2.2_A9.7: FAIL_OK
|
||||
S15.1.2.3_A7.6: FAIL_OK
|
||||
S15.1.2.3_A7.7: FAIL_OK
|
||||
S15.1.2.4_A2.6: FAIL_OK
|
||||
S15.1.2.4_A2.7: FAIL_OK
|
||||
S15.1.2.5_A2.6: FAIL_OK
|
||||
S15.1.2.5_A2.7: FAIL_OK
|
||||
S15.1.3.1_A5.6: FAIL_OK
|
||||
S15.1.3.1_A5.7: FAIL_OK
|
||||
S15.1.3.2_A5.6: FAIL_OK
|
||||
S15.1.3.2_A5.7: FAIL_OK
|
||||
S15.1.3.3_A5.6: FAIL_OK
|
||||
S15.1.3.3_A5.7: FAIL_OK
|
||||
S15.1.3.4_A5.6: FAIL_OK
|
||||
S15.1.3.4_A5.7: FAIL_OK
|
||||
S15.10.6.2_A6: FAIL_OK
|
||||
S15.10.6.3_A6: FAIL_OK
|
||||
S15.10.6.4_A6: FAIL_OK
|
||||
S15.10.6.4_A7: FAIL_OK
|
||||
S15.2.4.2_A6: FAIL_OK
|
||||
S15.2.4.3_A6: FAIL_OK
|
||||
S15.2.4.4_A6: FAIL_OK
|
||||
S15.2.4.5_A6: FAIL_OK
|
||||
S15.2.4.6_A6: FAIL_OK
|
||||
S15.2.4.7_A6: FAIL_OK
|
||||
S15.3.4.2_A6: FAIL_OK
|
||||
S15.4.4.10_A5.6: FAIL_OK
|
||||
S15.4.4.10_A5.7: FAIL_OK
|
||||
S15.4.4.11_A7.6: FAIL_OK
|
||||
S15.4.4.11_A7.7: FAIL_OK
|
||||
S15.4.4.12_A5.6: FAIL_OK
|
||||
S15.4.4.12_A5.7: FAIL_OK
|
||||
S15.4.4.13_A5.6: FAIL_OK
|
||||
S15.4.4.13_A5.7: FAIL_OK
|
||||
S15.4.4.2_A4.6: FAIL_OK
|
||||
S15.4.4.3_A4.6: FAIL_OK
|
||||
S15.4.4.3_A4.6: FAIL_OK
|
||||
S15.4.4.4_A4.6: FAIL_OK
|
||||
S15.4.4.4_A4.7: FAIL_OK
|
||||
S15.4.4.5_A6.6: FAIL_OK
|
||||
S15.4.4.5_A6.7: FAIL_OK
|
||||
S15.4.4.6_A5.6: FAIL_OK
|
||||
S15.4.4.6_A5.7: FAIL_OK
|
||||
S15.4.4.7_A6.6: FAIL_OK
|
||||
S15.4.4.7_A6.7: FAIL_OK
|
||||
S15.4.4.8_A5.6: FAIL_OK
|
||||
S15.4.4.8_A5.7: FAIL_OK
|
||||
S15.4.4.9_A5.6: FAIL_OK
|
||||
S15.4.4.9_A5.7: FAIL_OK
|
||||
S15.5.4.10_A6: FAIL_OK
|
||||
S15.5.4.11_A6: FAIL_OK
|
||||
S15.5.4.12_A6: FAIL_OK
|
||||
S15.5.4.13_A6: FAIL_OK
|
||||
S15.5.4.14_A6: FAIL_OK
|
||||
S15.5.4.15_A6: FAIL_OK
|
||||
S15.5.4.16_A6: FAIL_OK
|
||||
S15.5.4.17_A6: FAIL_OK
|
||||
S15.5.4.18_A6: FAIL_OK
|
||||
S15.5.4.19_A6: FAIL_OK
|
||||
S15.5.4.4_A6: FAIL_OK
|
||||
S15.5.4.5_A6: FAIL_OK
|
||||
S15.5.4.6_A6: FAIL_OK
|
||||
S15.5.4.7_A6: FAIL_OK
|
||||
S15.5.4.9_A6: FAIL_OK
|
||||
S15.3.4.3_A12: FAIL_OK
|
||||
S15.3.4.4_A12: FAIL_OK
|
||||
S15.5.4.8_A6: FAIL_OK
|
||||
|
||||
# We are silent in some regexp cases where the spec wants us to give
|
||||
# errors, for compatibility.
|
||||
S15.10.2.11_A1_T2: FAIL
|
||||
|
Loading…
Reference in New Issue
Block a user