diff options
| author | Ben Murdoch <benm@google.com> | 2012-03-05 11:04:45 +0000 |
|---|---|---|
| committer | Ben Murdoch <benm@google.com> | 2012-04-11 15:39:56 +0100 |
| commit | 592a9fc1d8ea420377a2e7efd0600e20b058be2b (patch) | |
| tree | 23fe22995f4f9056a96266d169d49426a5e745d7 /test | |
| parent | e25ed7434cc3a061dd965ad25b923bca153aed94 (diff) | |
| download | android_external_v8-592a9fc1d8ea420377a2e7efd0600e20b058be2b.tar.gz android_external_v8-592a9fc1d8ea420377a2e7efd0600e20b058be2b.tar.bz2 android_external_v8-592a9fc1d8ea420377a2e7efd0600e20b058be2b.zip | |
Merge V8 at 3.7.12.28
Bug: 5688872
Change-Id: Iddb40cae44d51a2b449f2858951e0472771f5981
Diffstat (limited to 'test')
123 files changed, 8776 insertions, 2950 deletions
diff --git a/test/cctest/SConscript b/test/cctest/SConscript index 5c926718..621d8ecf 100644 --- a/test/cctest/SConscript +++ b/test/cctest/SConscript @@ -73,7 +73,6 @@ SOURCES = { 'test-fixed-dtoa.cc', 'test-flags.cc', 'test-func-name-inference.cc', - 'test-hashing.cc', 'test-hashmap.cc', 'test-heap-profiler.cc', 'test-heap.cc', diff --git a/test/cctest/cctest.gyp b/test/cctest/cctest.gyp index 5d0cab3e..3b8f4f65 100644 --- a/test/cctest/cctest.gyp +++ b/test/cctest/cctest.gyp @@ -68,6 +68,7 @@ 'test-fixed-dtoa.cc', 'test-flags.cc', 'test-func-name-inference.cc', + 'test-hashing.cc', 'test-hashmap.cc', 'test-heap.cc', 'test-heap-profiler.cc', @@ -91,7 +92,8 @@ 'test-threads.cc', 'test-unbound-queue.cc', 'test-utils.cc', - 'test-version.cc' + 'test-version.cc', + 'test-weakmaps.cc' ], 'conditions': [ ['v8_target_arch=="ia32"', { @@ -134,6 +136,12 @@ 'sources': [ 'test-platform-win32.cc', ], + 'msvs_settings': { + 'VCCLCompilerTool': { + # MSVS wants this for gay-{precision,shortest}.cc. + 'AdditionalOptions': ['/bigobj'], + }, + }, }], ['component=="shared_library"', { # cctest can't be built against a shared library, so we need to diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status index 5122da5a..7161345e 100644 --- a/test/cctest/cctest.status +++ b/test/cctest/cctest.status @@ -33,11 +33,22 @@ test-api/Bug*: FAIL # BUG(382): Weird test. Can't guarantee that it never times out. test-api/ApplyInterruption: PASS || TIMEOUT +# BUG(484): This test which we thought was originally corrected in r5236 +# is re-appearing. Disabled until bug in test is fixed. This only fails +# when snapshot is on, so I am marking it PASS || FAIL +test-heap-profiler/HeapSnapshotsDiff: PASS || FAIL + # These tests always fail. They are here to test test.py. If # they don't fail then test.py has failed. test-serialize/TestThatAlwaysFails: FAIL test-serialize/DependentTestThatAlwaysFails: FAIL +# TODO(gc): Temporarily disabled in the GC branch. +test-log/EquivalenceOfLoggingAndTraversal: PASS || FAIL + +# BUG(1261): Flakey test. +test-profile-generator/RecordStackTraceAtStartProfiling: PASS || FAIL + # We do not yet shrink weak maps after they have been emptied by the GC test-weakmaps/Shrinking: FAIL diff --git a/test/cctest/test-accessors.cc b/test/cctest/test-accessors.cc index d95536d2..b1900f9e 100644 --- a/test/cctest/test-accessors.cc +++ b/test/cctest/test-accessors.cc @@ -241,7 +241,7 @@ static v8::Handle<Value> CheckAccessorArgsCorrect(Local<String> name, ApiTestFuzzer::Fuzz(); CHECK(info.This() == info.Holder()); CHECK(info.Data()->Equals(v8::String::New("data"))); - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK(info.This() == info.Holder()); CHECK(info.Data()->Equals(v8::String::New("data"))); return v8::Integer::New(17); diff --git a/test/cctest/test-alloc.cc b/test/cctest/test-alloc.cc index 97671923..cf9d488a 100644 --- a/test/cctest/test-alloc.cc +++ b/test/cctest/test-alloc.cc @@ -1,4 +1,4 @@ -// Copyright 2007-2008 the V8 project authors. All rights reserved. +// Copyright 2011 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: @@ -72,11 +72,29 @@ static MaybeObject* AllocateAfterFailures() { } CHECK(!heap->AllocateRawAsciiString(100, TENURED)->IsFailure()); + // Old pointer space. + OldSpace* old_pointer_space = heap->old_pointer_space(); + static const int kOldPointerSpaceFillerLength = 10000; + static const int kOldPointerSpaceFillerSize = FixedArray::SizeFor( + kOldPointerSpaceFillerLength); + while (old_pointer_space->Available() > kOldPointerSpaceFillerSize) { + CHECK(!heap->AllocateFixedArray(kOldPointerSpaceFillerLength, TENURED)-> + IsFailure()); + } + CHECK(!heap->AllocateFixedArray(kOldPointerSpaceFillerLength, TENURED)-> + IsFailure()); + // Large object space. - while (!heap->OldGenerationAllocationLimitReached()) { - CHECK(!heap->AllocateFixedArray(10000, TENURED)->IsFailure()); + static const int kLargeObjectSpaceFillerLength = 300000; + static const int kLargeObjectSpaceFillerSize = FixedArray::SizeFor( + kLargeObjectSpaceFillerLength); + ASSERT(kLargeObjectSpaceFillerSize > heap->old_pointer_space()->AreaSize()); + while (heap->OldGenerationSpaceAvailable() > kLargeObjectSpaceFillerSize) { + CHECK(!heap->AllocateFixedArray(kLargeObjectSpaceFillerLength, TENURED)-> + IsFailure()); } - CHECK(!heap->AllocateFixedArray(10000, TENURED)->IsFailure()); + CHECK(!heap->AllocateFixedArray(kLargeObjectSpaceFillerLength, TENURED)-> + IsFailure()); // Map space. MapSpace* map_space = heap->map_space(); @@ -175,16 +193,16 @@ unsigned int Pseudorandom() { // Plain old data class. Represents a block of allocated memory. class Block { public: - Block(void* base_arg, int size_arg) + Block(Address base_arg, int size_arg) : base(base_arg), size(size_arg) {} - void *base; + Address base; int size; }; TEST(CodeRange) { - const int code_range_size = 16*MB; + const int code_range_size = 32*MB; OS::Setup(); Isolate::Current()->InitializeLoggingAndCounters(); CodeRange* code_range = new CodeRange(Isolate::Current()); @@ -196,11 +214,15 @@ TEST(CodeRange) { while (total_allocated < 5 * code_range_size) { if (current_allocated < code_range_size / 10) { // Allocate a block. - // Geometrically distributed sizes, greater than Page::kPageSize. - size_t requested = (Page::kPageSize << (Pseudorandom() % 6)) + - Pseudorandom() % 5000 + 1; + // Geometrically distributed sizes, greater than + // Page::kMaxNonCodeHeapObjectSize (which is greater than code page area). + // TODO(gc): instead of using 3 use some contant based on code_range_size + // kMaxHeapObjectSize. + size_t requested = + (Page::kMaxNonCodeHeapObjectSize << (Pseudorandom() % 3)) + + Pseudorandom() % 5000 + 1; size_t allocated = 0; - void* base = code_range->AllocateRawMemory(requested, &allocated); + Address base = code_range->AllocateRawMemory(requested, &allocated); CHECK(base != NULL); blocks.Add(Block(base, static_cast<int>(allocated))); current_allocated += static_cast<int>(allocated); diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index c1c8aae5..cc20b6f1 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -80,6 +80,11 @@ static void ExpectString(const char* code, const char* expected) { CHECK_EQ(expected, *ascii); } +static void ExpectInt32(const char* code, int expected) { + Local<Value> result = CompileRun(code); + CHECK(result->IsInt32()); + CHECK_EQ(expected, result->Int32Value()); +} static void ExpectBoolean(const char* code, bool expected) { Local<Value> result = CompileRun(code); @@ -393,11 +398,11 @@ THREADED_TEST(ScriptUsingStringResource) { CHECK(source->IsExternal()); CHECK_EQ(resource, static_cast<TestResource*>(source->GetExternalStringResource())); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(0, dispose_count); } v8::internal::Isolate::Current()->compilation_cache()->Clear(); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllAvailableGarbage(); CHECK_EQ(1, dispose_count); } @@ -415,11 +420,11 @@ THREADED_TEST(ScriptUsingAsciiStringResource) { Local<Value> value = script->Run(); CHECK(value->IsNumber()); CHECK_EQ(7, value->Int32Value()); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(0, dispose_count); } i::Isolate::Current()->compilation_cache()->Clear(); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllAvailableGarbage(); CHECK_EQ(1, dispose_count); } @@ -441,11 +446,12 @@ THREADED_TEST(ScriptMakingExternalString) { Local<Value> value = script->Run(); CHECK(value->IsNumber()); CHECK_EQ(7, value->Int32Value()); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(0, dispose_count); } i::Isolate::Current()->compilation_cache()->Clear(); - HEAP->CollectAllGarbage(false); + // TODO(1608): This should use kAbortIncrementalMarking. + HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask); CHECK_EQ(1, dispose_count); } @@ -467,11 +473,12 @@ THREADED_TEST(ScriptMakingExternalAsciiString) { Local<Value> value = script->Run(); CHECK(value->IsNumber()); CHECK_EQ(7, value->Int32Value()); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(0, dispose_count); } i::Isolate::Current()->compilation_cache()->Clear(); - HEAP->CollectAllGarbage(false); + // TODO(1608): This should use kAbortIncrementalMarking. + HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask); CHECK_EQ(1, dispose_count); } @@ -484,7 +491,7 @@ TEST(MakingExternalStringConditions) { HEAP->CollectGarbage(i::NEW_SPACE); HEAP->CollectGarbage(i::NEW_SPACE); - uint16_t* two_byte_string = AsciiToTwoByteString("small"); + uint16_t* two_byte_string = AsciiToTwoByteString("s1"); Local<String> small_string = String::New(two_byte_string); i::DeleteArray(two_byte_string); @@ -496,7 +503,7 @@ TEST(MakingExternalStringConditions) { // Old space strings should be accepted. CHECK(small_string->CanMakeExternal()); - two_byte_string = AsciiToTwoByteString("small 2"); + two_byte_string = AsciiToTwoByteString("small string 2"); small_string = String::New(two_byte_string); i::DeleteArray(two_byte_string); @@ -530,7 +537,7 @@ TEST(MakingExternalAsciiStringConditions) { HEAP->CollectGarbage(i::NEW_SPACE); HEAP->CollectGarbage(i::NEW_SPACE); - Local<String> small_string = String::New("small"); + Local<String> small_string = String::New("s1"); // We should refuse to externalize newly created small string. CHECK(!small_string->CanMakeExternal()); // Trigger GCs so that the newly allocated string moves to old gen. @@ -539,7 +546,7 @@ TEST(MakingExternalAsciiStringConditions) { // Old space strings should be accepted. CHECK(small_string->CanMakeExternal()); - small_string = String::New("small 2"); + small_string = String::New("small string 2"); // We should refuse externalizing newly created small string. CHECK(!small_string->CanMakeExternal()); for (int i = 0; i < 100; i++) { @@ -572,8 +579,8 @@ THREADED_TEST(UsingExternalString) { i::Handle<i::String> isymbol = FACTORY->SymbolFromString(istring); CHECK(isymbol->IsSymbol()); } - HEAP->CollectAllGarbage(false); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); } @@ -590,8 +597,8 @@ THREADED_TEST(UsingExternalAsciiString) { i::Handle<i::String> isymbol = FACTORY->SymbolFromString(istring); CHECK(isymbol->IsSymbol()); } - HEAP->CollectAllGarbage(false); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); } @@ -672,11 +679,11 @@ TEST(ExternalStringWithDisposeHandling) { Local<Value> value = script->Run(); CHECK(value->IsNumber()); CHECK_EQ(7, value->Int32Value()); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllAvailableGarbage(); CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count); } i::Isolate::Current()->compilation_cache()->Clear(); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllAvailableGarbage(); CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls); CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count); @@ -693,11 +700,11 @@ TEST(ExternalStringWithDisposeHandling) { Local<Value> value = script->Run(); CHECK(value->IsNumber()); CHECK_EQ(7, value->Int32Value()); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllAvailableGarbage(); CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count); } i::Isolate::Current()->compilation_cache()->Clear(); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllAvailableGarbage(); CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls); CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_count); } @@ -744,8 +751,8 @@ THREADED_TEST(StringConcat) { CHECK_EQ(68, value->Int32Value()); } i::Isolate::Current()->compilation_cache()->Clear(); - HEAP->CollectAllGarbage(false); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); } @@ -1182,9 +1189,9 @@ THREADED_TEST(GlobalPrototype) { templ->Set("x", v8_num(200)); templ->SetAccessor(v8_str("m"), GetM); LocalContext env(0, templ); - v8::Handle<v8::Object> obj = env->Global(); - v8::Handle<Script> script = v8_compile("dummy()"); - v8::Handle<Value> result = script->Run(); + v8::Handle<v8::Object> obj(env->Global()); + v8::Handle<Script> script(v8_compile("dummy()")); + v8::Handle<Value> result(script->Run()); CHECK_EQ(13.4, result->NumberValue()); CHECK_EQ(200, v8_compile("x")->Run()->Int32Value()); CHECK_EQ(876, v8_compile("m")->Run()->Int32Value()); @@ -1294,6 +1301,197 @@ static v8::Handle<Value> EchoNamedProperty(Local<String> name, return name; } +// Helper functions for Interceptor/Accessor interaction tests + +Handle<Value> SimpleAccessorGetter(Local<String> name, + const AccessorInfo& info) { + Handle<Object> self = info.This(); + return self->Get(String::Concat(v8_str("accessor_"), name)); +} + +void SimpleAccessorSetter(Local<String> name, Local<Value> value, + const AccessorInfo& info) { + Handle<Object> self = info.This(); + self->Set(String::Concat(v8_str("accessor_"), name), value); +} + +Handle<Value> EmptyInterceptorGetter(Local<String> name, + const AccessorInfo& info) { + return Handle<Value>(); +} + +Handle<Value> EmptyInterceptorSetter(Local<String> name, + Local<Value> value, + const AccessorInfo& info) { + return Handle<Value>(); +} + +Handle<Value> InterceptorGetter(Local<String> name, + const AccessorInfo& info) { + // Intercept names that start with 'interceptor_'. + String::AsciiValue ascii(name); + char* name_str = *ascii; + char prefix[] = "interceptor_"; + int i; + for (i = 0; name_str[i] && prefix[i]; ++i) { + if (name_str[i] != prefix[i]) return Handle<Value>(); + } + Handle<Object> self = info.This(); + return self->GetHiddenValue(v8_str(name_str + i)); +} + +Handle<Value> InterceptorSetter(Local<String> name, + Local<Value> value, + const AccessorInfo& info) { + // Intercept accesses that set certain integer values. + if (value->IsInt32() && value->Int32Value() < 10000) { + Handle<Object> self = info.This(); + self->SetHiddenValue(name, value); + return value; + } + return Handle<Value>(); +} + +void AddAccessor(Handle<FunctionTemplate> templ, + Handle<String> name, + v8::AccessorGetter getter, + v8::AccessorSetter setter) { + templ->PrototypeTemplate()->SetAccessor(name, getter, setter); +} + +void AddInterceptor(Handle<FunctionTemplate> templ, + v8::NamedPropertyGetter getter, + v8::NamedPropertySetter setter) { + templ->InstanceTemplate()->SetNamedPropertyHandler(getter, setter); +} + +THREADED_TEST(EmptyInterceptorDoesNotShadowAccessors) { + v8::HandleScope scope; + Handle<FunctionTemplate> parent = FunctionTemplate::New(); + Handle<FunctionTemplate> child = FunctionTemplate::New(); + child->Inherit(parent); + AddAccessor(parent, v8_str("age"), + SimpleAccessorGetter, SimpleAccessorSetter); + AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter); + LocalContext env; + env->Global()->Set(v8_str("Child"), child->GetFunction()); + CompileRun("var child = new Child;" + "child.age = 10;"); + ExpectBoolean("child.hasOwnProperty('age')", false); + ExpectInt32("child.age", 10); + ExpectInt32("child.accessor_age", 10); +} + +THREADED_TEST(EmptyInterceptorDoesNotShadowJSAccessors) { + v8::HandleScope scope; + Handle<FunctionTemplate> parent = FunctionTemplate::New(); + Handle<FunctionTemplate> child = FunctionTemplate::New(); + child->Inherit(parent); + AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter); + LocalContext env; + env->Global()->Set(v8_str("Child"), child->GetFunction()); + CompileRun("var child = new Child;" + "var parent = child.__proto__;" + "Object.defineProperty(parent, 'age', " + " {get: function(){ return this.accessor_age; }, " + " set: function(v){ this.accessor_age = v; }, " + " enumerable: true, configurable: true});" + "child.age = 10;"); + ExpectBoolean("child.hasOwnProperty('age')", false); + ExpectInt32("child.age", 10); + ExpectInt32("child.accessor_age", 10); +} + +THREADED_TEST(EmptyInterceptorDoesNotAffectJSProperties) { + v8::HandleScope scope; + Handle<FunctionTemplate> parent = FunctionTemplate::New(); + Handle<FunctionTemplate> child = FunctionTemplate::New(); + child->Inherit(parent); + AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter); + LocalContext env; + env->Global()->Set(v8_str("Child"), child->GetFunction()); + CompileRun("var child = new Child;" + "var parent = child.__proto__;" + "parent.name = 'Alice';"); + ExpectBoolean("child.hasOwnProperty('name')", false); + ExpectString("child.name", "Alice"); + CompileRun("child.name = 'Bob';"); + ExpectString("child.name", "Bob"); + ExpectBoolean("child.hasOwnProperty('name')", true); + ExpectString("parent.name", "Alice"); +} + +THREADED_TEST(SwitchFromInterceptorToAccessor) { + v8::HandleScope scope; + Handle<FunctionTemplate> parent = FunctionTemplate::New(); + Handle<FunctionTemplate> child = FunctionTemplate::New(); + child->Inherit(parent); + AddAccessor(parent, v8_str("age"), + SimpleAccessorGetter, SimpleAccessorSetter); + AddInterceptor(child, InterceptorGetter, InterceptorSetter); + LocalContext env; + env->Global()->Set(v8_str("Child"), child->GetFunction()); + CompileRun("var child = new Child;" + "function setAge(i){ child.age = i; };" + "for(var i = 0; i <= 10000; i++) setAge(i);"); + // All i < 10000 go to the interceptor. + ExpectInt32("child.interceptor_age", 9999); + // The last i goes to the accessor. + ExpectInt32("child.accessor_age", 10000); +} + +THREADED_TEST(SwitchFromAccessorToInterceptor) { + v8::HandleScope scope; + Handle<FunctionTemplate> parent = FunctionTemplate::New(); + Handle<FunctionTemplate> child = FunctionTemplate::New(); + child->Inherit(parent); + AddAccessor(parent, v8_str("age"), + SimpleAccessorGetter, SimpleAccessorSetter); + AddInterceptor(child, InterceptorGetter, InterceptorSetter); + LocalContext env; + env->Global()->Set(v8_str("Child"), child->GetFunction()); + CompileRun("var child = new Child;" + "function setAge(i){ child.age = i; };" + "for(var i = 20000; i >= 9999; i--) setAge(i);"); + // All i >= 10000 go to the accessor. + ExpectInt32("child.accessor_age", 10000); + // The last i goes to the interceptor. + ExpectInt32("child.interceptor_age", 9999); +} + +THREADED_TEST(SwitchFromInterceptorToProperty) { + v8::HandleScope scope; + Handle<FunctionTemplate> parent = FunctionTemplate::New(); + Handle<FunctionTemplate> child = FunctionTemplate::New(); + child->Inherit(parent); + AddInterceptor(child, InterceptorGetter, InterceptorSetter); + LocalContext env; + env->Global()->Set(v8_str("Child"), child->GetFunction()); + CompileRun("var child = new Child;" + "function setAge(i){ child.age = i; };" + "for(var i = 0; i <= 10000; i++) setAge(i);"); + // All i < 10000 go to the interceptor. + ExpectInt32("child.interceptor_age", 9999); + // The last i goes to child's own property. + ExpectInt32("child.age", 10000); +} + +THREADED_TEST(SwitchFromPropertyToInterceptor) { + v8::HandleScope scope; + Handle<FunctionTemplate> parent = FunctionTemplate::New(); + Handle<FunctionTemplate> child = FunctionTemplate::New(); + child->Inherit(parent); + AddInterceptor(child, InterceptorGetter, InterceptorSetter); + LocalContext env; + env->Global()->Set(v8_str("Child"), child->GetFunction()); + CompileRun("var child = new Child;" + "function setAge(i){ child.age = i; };" + "for(var i = 20000; i >= 9999; i--) setAge(i);"); + // All i >= 10000 go to child's own property. + ExpectInt32("child.age", 10000); + // The last i goes to the interceptor. + ExpectInt32("child.interceptor_age", 9999); +} THREADED_TEST(NamedPropertyHandlerGetter) { echo_named_call_count = 0; @@ -1567,7 +1765,7 @@ THREADED_TEST(DeepCrossLanguageRecursion) { env->Global()->Set(v8_str("depth"), v8::Integer::New(0)); call_recursively_script = v8_compile("callScriptRecursively()"); - v8::Handle<Value> result = call_recursively_script->Run(); + v8::Handle<Value> result(call_recursively_script->Run()); call_recursively_script = v8::Handle<Script>(); env->Global()->Set(v8_str("depth"), v8::Integer::New(0)); @@ -1666,12 +1864,12 @@ THREADED_TEST(InternalFieldsNativePointers) { // Check reading and writing aligned pointers. obj->SetPointerInInternalField(0, aligned); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(aligned, obj->GetPointerFromInternalField(0)); // Check reading and writing unaligned pointers. obj->SetPointerInInternalField(0, unaligned); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(unaligned, obj->GetPointerFromInternalField(0)); delete[] data; @@ -1697,19 +1895,19 @@ THREADED_TEST(InternalFieldsNativePointersAndExternal) { CHECK_EQ(1, static_cast<int>(reinterpret_cast<uintptr_t>(unaligned) & 0x1)); obj->SetPointerInInternalField(0, aligned); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(aligned, v8::External::Unwrap(obj->GetInternalField(0))); obj->SetPointerInInternalField(0, unaligned); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(unaligned, v8::External::Unwrap(obj->GetInternalField(0))); obj->SetInternalField(0, v8::External::Wrap(aligned)); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(aligned, obj->GetPointerFromInternalField(0)); obj->SetInternalField(0, v8::External::Wrap(unaligned)); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(unaligned, obj->GetPointerFromInternalField(0)); delete[] data; @@ -1722,7 +1920,7 @@ THREADED_TEST(IdentityHash) { // Ensure that the test starts with an fresh heap to test whether the hash // code is based on the address. - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); Local<v8::Object> obj = v8::Object::New(); int hash = obj->GetIdentityHash(); int hash1 = obj->GetIdentityHash(); @@ -1732,7 +1930,7 @@ THREADED_TEST(IdentityHash) { // objects should not be assigned the same hash code. If the test below fails // the random number generator should be evaluated. CHECK_NE(hash, hash2); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); int hash3 = v8::Object::New()->GetIdentityHash(); // Make sure that the identity hash is not based on the initial address of // the object alone. If the test below fails the random number generator @@ -1769,7 +1967,7 @@ THREADED_TEST(HiddenProperties) { v8::Local<v8::String> empty = v8_str(""); v8::Local<v8::String> prop_name = v8_str("prop_name"); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); // Make sure delete of a non-existent hidden value works CHECK(obj->DeleteHiddenValue(key)); @@ -1779,7 +1977,7 @@ THREADED_TEST(HiddenProperties) { CHECK(obj->SetHiddenValue(key, v8::Integer::New(2002))); CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value()); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); // Make sure we do not find the hidden property. CHECK(!obj->Has(empty)); @@ -1790,7 +1988,7 @@ THREADED_TEST(HiddenProperties) { CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value()); CHECK_EQ(2003, obj->Get(empty)->Int32Value()); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); // Add another property and delete it afterwards to force the object in // slow case. @@ -1801,7 +1999,7 @@ THREADED_TEST(HiddenProperties) { CHECK(obj->Delete(prop_name)); CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value()); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK(obj->DeleteHiddenValue(key)); CHECK(obj->GetHiddenValue(key).IsEmpty()); @@ -1908,19 +2106,30 @@ THREADED_TEST(GlobalHandle) { } -static int NumberOfWeakCalls = 0; +class WeakCallCounter { + public: + explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) { } + int id() { return id_; } + void increment() { number_of_weak_calls_++; } + int NumberOfWeakCalls() { return number_of_weak_calls_; } + private: + int id_; + int number_of_weak_calls_; +}; + + static void WeakPointerCallback(Persistent<Value> handle, void* id) { - CHECK_EQ(reinterpret_cast<void*>(1234), id); - NumberOfWeakCalls++; + WeakCallCounter* counter = reinterpret_cast<WeakCallCounter*>(id); + CHECK_EQ(1234, counter->id()); + counter->increment(); handle.Dispose(); } + THREADED_TEST(ApiObjectGroups) { HandleScope scope; LocalContext env; - NumberOfWeakCalls = 0; - Persistent<Object> g1s1; Persistent<Object> g1s2; Persistent<Object> g1c1; @@ -1928,21 +2137,23 @@ THREADED_TEST(ApiObjectGroups) { Persistent<Object> g2s2; Persistent<Object> g2c1; + WeakCallCounter counter(1234); + { HandleScope scope; g1s1 = Persistent<Object>::New(Object::New()); g1s2 = Persistent<Object>::New(Object::New()); g1c1 = Persistent<Object>::New(Object::New()); - g1s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); - g1s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); - g1c1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); + g1s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); + g1s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); + g1c1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); g2s1 = Persistent<Object>::New(Object::New()); g2s2 = Persistent<Object>::New(Object::New()); g2c1 = Persistent<Object>::New(Object::New()); - g2s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); - g2s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); - g2c1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); + g2s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); + g2s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); + g2c1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); } Persistent<Object> root = Persistent<Object>::New(g1s1); // make a root. @@ -1961,14 +2172,15 @@ THREADED_TEST(ApiObjectGroups) { V8::AddObjectGroup(g2_objects, 2); V8::AddImplicitReferences(g2s2, g2_children, 1); } - // Do a full GC - HEAP->CollectGarbage(i::OLD_POINTER_SPACE); + // Do a single full GC. Use kMakeHeapIterableMask to ensure that + // incremental garbage collection is stopped. + HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask); // All object should be alive. - CHECK_EQ(0, NumberOfWeakCalls); + CHECK_EQ(0, counter.NumberOfWeakCalls()); // Weaken the root. - root.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); + root.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); // But make children strong roots---all the objects (except for children) // should be collectable now. g1c1.ClearWeak(); @@ -1986,17 +2198,17 @@ THREADED_TEST(ApiObjectGroups) { V8::AddImplicitReferences(g2s2, g2_children, 1); } - HEAP->CollectGarbage(i::OLD_POINTER_SPACE); + HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask); // All objects should be gone. 5 global handles in total. - CHECK_EQ(5, NumberOfWeakCalls); + CHECK_EQ(5, counter.NumberOfWeakCalls()); // And now make children weak again and collect them. - g1c1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); - g2c1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); + g1c1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); + g2c1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); - HEAP->CollectGarbage(i::OLD_POINTER_SPACE); - CHECK_EQ(7, NumberOfWeakCalls); + HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask); + CHECK_EQ(7, counter.NumberOfWeakCalls()); } @@ -2004,7 +2216,7 @@ THREADED_TEST(ApiObjectGroupsCycle) { HandleScope scope; LocalContext env; - NumberOfWeakCalls = 0; + WeakCallCounter counter(1234); Persistent<Object> g1s1; Persistent<Object> g1s2; @@ -2017,18 +2229,18 @@ THREADED_TEST(ApiObjectGroupsCycle) { HandleScope scope; g1s1 = Persistent<Object>::New(Object::New()); g1s2 = Persistent<Object>::New(Object::New()); - g1s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); - g1s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); + g1s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); + g1s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); g2s1 = Persistent<Object>::New(Object::New()); g2s2 = Persistent<Object>::New(Object::New()); - g2s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); - g2s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); + g2s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); + g2s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); g3s1 = Persistent<Object>::New(Object::New()); g3s2 = Persistent<Object>::New(Object::New()); - g3s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); - g3s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); + g3s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); + g3s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); } Persistent<Object> root = Persistent<Object>::New(g1s1); // make a root. @@ -2050,14 +2262,14 @@ THREADED_TEST(ApiObjectGroupsCycle) { V8::AddObjectGroup(g3_objects, 2); V8::AddImplicitReferences(g3s1, g3_children, 1); } - // Do a full GC - HEAP->CollectGarbage(i::OLD_POINTER_SPACE); + // Do a single full GC + HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask); // All object should be alive. - CHECK_EQ(0, NumberOfWeakCalls); + CHECK_EQ(0, counter.NumberOfWeakCalls()); // Weaken the root. - root.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); + root.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); // Groups are deleted, rebuild groups. { @@ -2075,10 +2287,10 @@ THREADED_TEST(ApiObjectGroupsCycle) { V8::AddImplicitReferences(g3s1, g3_children, 1); } - HEAP->CollectGarbage(i::OLD_POINTER_SPACE); + HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask); // All objects should be gone. 7 global handles in total. - CHECK_EQ(7, NumberOfWeakCalls); + CHECK_EQ(7, counter.NumberOfWeakCalls()); } @@ -4172,7 +4384,7 @@ THREADED_TEST(ExtensibleOnUndetectable) { source = v8_str("undetectable.y = 2000;"); script = Script::Compile(source); - Local<Value> result = script->Run(); + Local<Value> result(script->Run()); ExpectBoolean("undetectable.y == undefined", true); } @@ -4305,6 +4517,47 @@ THREADED_TEST(SimpleExtensions) { } +static const char* kEmbeddedExtensionSource = + "function Ret54321(){return 54321;}~~@@$" + "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS."; +static const int kEmbeddedExtensionSourceValidLen = 34; + + +THREADED_TEST(ExtensionMissingSourceLength) { + v8::HandleScope handle_scope; + v8::RegisterExtension(new Extension("srclentest_fail", + kEmbeddedExtensionSource)); + const char* extension_names[] = { "srclentest_fail" }; + v8::ExtensionConfiguration extensions(1, extension_names); + v8::Handle<Context> context = Context::New(&extensions); + CHECK_EQ(0, *context); +} + + +THREADED_TEST(ExtensionWithSourceLength) { + for (int source_len = kEmbeddedExtensionSourceValidLen - 1; + source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) { + v8::HandleScope handle_scope; + i::ScopedVector<char> extension_name(32); + i::OS::SNPrintF(extension_name, "ext #%d", source_len); + v8::RegisterExtension(new Extension(extension_name.start(), + kEmbeddedExtensionSource, 0, 0, + source_len)); + const char* extension_names[1] = { extension_name.start() }; + v8::ExtensionConfiguration extensions(1, extension_names); + v8::Handle<Context> context = Context::New(&extensions); + if (source_len == kEmbeddedExtensionSourceValidLen) { + Context::Scope lock(context); + v8::Handle<Value> result = Script::Compile(v8_str("Ret54321()"))->Run(); + CHECK_EQ(v8::Integer::New(54321), result); + } else { + // Anything but exactly the right length should fail to compile. + CHECK_EQ(0, *context); + } + } +} + + static const char* kEvalExtensionSource1 = "function UseEval1() {" " var x = 42;" @@ -4483,7 +4736,7 @@ THREADED_TEST(NativeFunctionDeclarationError) { "native\nfunction foo();")); const char* extension_names[] = { name }; v8::ExtensionConfiguration extensions(1, extension_names); - v8::Handle<Context> context = Context::New(&extensions); + v8::Handle<Context> context(Context::New(&extensions)); ASSERT(context.IsEmpty()); } @@ -4497,7 +4750,7 @@ THREADED_TEST(NativeFunctionDeclarationErrorEscape) { "nativ\\u0065 function foo();")); const char* extension_names[] = { name }; v8::ExtensionConfiguration extensions(1, extension_names); - v8::Handle<Context> context = Context::New(&extensions); + v8::Handle<Context> context(Context::New(&extensions)); ASSERT(context.IsEmpty()); } @@ -4664,7 +4917,7 @@ TEST(RegexpOutOfMemory) { Local<Script> script = Script::Compile(String::New(js_code_causing_huge_string_flattening)); last_location = NULL; - Local<Value> result = script->Run(); + Local<Value> result(script->Run()); CHECK(false); // Should not return. } @@ -4805,7 +5058,7 @@ static void InvokeScavenge() { static void InvokeMarkSweep() { - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); } @@ -4898,7 +5151,7 @@ static v8::Handle<Value> ArgumentsTestCallback(const v8::Arguments& args) { CHECK_EQ(v8::Integer::New(3), args[2]); CHECK_EQ(v8::Undefined(), args[3]); v8::HandleScope scope; - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); return v8::Undefined(); } @@ -5185,67 +5438,109 @@ static int StrNCmp16(uint16_t* a, uint16_t* b, int n) { THREADED_TEST(StringWrite) { + LocalContext context; v8::HandleScope scope; v8::Handle<String> str = v8_str("abcde"); // abc<Icelandic eth><Unicode snowman>. v8::Handle<String> str2 = v8_str("abc\303\260\342\230\203"); + const int kStride = 4; // Must match stride in for loops in JS below. + CompileRun( + "var left = '';" + "for (var i = 0; i < 0xd800; i += 4) {" + " left = left + String.fromCharCode(i);" + "}"); + CompileRun( + "var right = '';" + "for (var i = 0; i < 0xd800; i += 4) {" + " right = String.fromCharCode(i) + right;" + "}"); + v8::Handle<v8::Object> global = Context::GetCurrent()->Global(); + Handle<String> left_tree = global->Get(v8_str("left")).As<String>(); + Handle<String> right_tree = global->Get(v8_str("right")).As<String>(); CHECK_EQ(5, str2->Length()); + CHECK_EQ(0xd800 / kStride, left_tree->Length()); + CHECK_EQ(0xd800 / kStride, right_tree->Length()); char buf[100]; - char utf8buf[100]; + char utf8buf[0xd800 * 3]; uint16_t wbuf[100]; int len; int charlen; - memset(utf8buf, 0x1, sizeof(utf8buf)); + memset(utf8buf, 0x1, 1000); len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen); CHECK_EQ(9, len); CHECK_EQ(5, charlen); CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203")); - memset(utf8buf, 0x1, sizeof(utf8buf)); + memset(utf8buf, 0x1, 1000); len = str2->WriteUtf8(utf8buf, 8, &charlen); CHECK_EQ(8, len); CHECK_EQ(5, charlen); CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9)); - memset(utf8buf, 0x1, sizeof(utf8buf)); + memset(utf8buf, 0x1, 1000); len = str2->WriteUtf8(utf8buf, 7, &charlen); CHECK_EQ(5, len); CHECK_EQ(4, charlen); CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5)); - memset(utf8buf, 0x1, sizeof(utf8buf)); + memset(utf8buf, 0x1, 1000); len = str2->WriteUtf8(utf8buf, 6, &charlen); CHECK_EQ(5, len); CHECK_EQ(4, charlen); CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5)); - memset(utf8buf, 0x1, sizeof(utf8buf)); + memset(utf8buf, 0x1, 1000); len = str2->WriteUtf8(utf8buf, 5, &charlen); CHECK_EQ(5, len); CHECK_EQ(4, charlen); CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5)); - memset(utf8buf, 0x1, sizeof(utf8buf)); + memset(utf8buf, 0x1, 1000); len = str2->WriteUtf8(utf8buf, 4, &charlen); CHECK_EQ(3, len); CHECK_EQ(3, charlen); CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4)); - memset(utf8buf, 0x1, sizeof(utf8buf)); + memset(utf8buf, 0x1, 1000); len = str2->WriteUtf8(utf8buf, 3, &charlen); CHECK_EQ(3, len); CHECK_EQ(3, charlen); CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4)); - memset(utf8buf, 0x1, sizeof(utf8buf)); + memset(utf8buf, 0x1, 1000); len = str2->WriteUtf8(utf8buf, 2, &charlen); CHECK_EQ(2, len); CHECK_EQ(2, charlen); CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3)); + memset(utf8buf, 0x1, sizeof(utf8buf)); + len = left_tree->Utf8Length(); + int utf8_expected = + (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride; + CHECK_EQ(utf8_expected, len); + len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen); + CHECK_EQ(utf8_expected, len); + CHECK_EQ(0xd800 / kStride, charlen); + CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3])); + CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2])); + CHECK_EQ(0xc0 - kStride, + static_cast<unsigned char>(utf8buf[utf8_expected - 1])); + CHECK_EQ(1, utf8buf[utf8_expected]); + + memset(utf8buf, 0x1, sizeof(utf8buf)); + len = right_tree->Utf8Length(); + CHECK_EQ(utf8_expected, len); + len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen); + CHECK_EQ(utf8_expected, len); + CHECK_EQ(0xd800 / kStride, charlen); + CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0])); + CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1])); + CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2])); + CHECK_EQ(1, utf8buf[utf8_expected]); + memset(buf, 0x1, sizeof(buf)); memset(wbuf, 0x1, sizeof(wbuf)); len = str->WriteAscii(buf); @@ -5400,7 +5695,7 @@ THREADED_TEST(ErrorConstruction) { v8::Handle<String> message = v8_str("message"); v8::Handle<Value> range_error = v8::Exception::RangeError(foo); CHECK(range_error->IsObject()); - v8::Handle<v8::Object> range_obj = range_error.As<v8::Object>(); + v8::Handle<v8::Object> range_obj(range_error.As<v8::Object>()); CHECK(range_error.As<v8::Object>()->Get(message)->Equals(foo)); v8::Handle<Value> reference_error = v8::Exception::ReferenceError(foo); CHECK(reference_error->IsObject()); @@ -6970,7 +7265,7 @@ THREADED_TEST(CallKnownGlobalReceiver) { // Create new environment reusing the global object. LocalContext env(NULL, instance_template, global_object); env->Global()->Set(v8_str("foo"), foo); - Local<Value> value = Script::Compile(v8_str("foo()"))->Run(); + Local<Value> value(Script::Compile(v8_str("foo()"))->Run()); } } @@ -7158,6 +7453,60 @@ THREADED_TEST(SetPrototype) { } +// Getting property names of an object with a prototype chain that +// triggers dictionary elements in GetLocalPropertyNames() shouldn't +// crash the runtime. +THREADED_TEST(Regress91517) { + i::FLAG_allow_natives_syntax = true; + v8::HandleScope handle_scope; + LocalContext context; + + Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(); + t1->SetHiddenPrototype(true); + t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1)); + Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(); + t2->SetHiddenPrototype(true); + t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2)); + t2->InstanceTemplate()->Set(v8_str("objects"), v8::Object::New()); + t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2)); + Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(); + t3->SetHiddenPrototype(true); + t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3)); + Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New(); + t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4)); + + // Force dictionary-based properties. + i::ScopedVector<char> name_buf(1024); + for (int i = 1; i <= 1000; i++) { + i::OS::SNPrintF(name_buf, "sdf%d", i); + t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2)); + } + + Local<v8::Object> o1 = t1->GetFunction()->NewInstance(); + Local<v8::Object> o2 = t2->GetFunction()->NewInstance(); + Local<v8::Object> o3 = t3->GetFunction()->NewInstance(); + Local<v8::Object> o4 = t4->GetFunction()->NewInstance(); + + // Create prototype chain of hidden prototypes. + CHECK(o4->SetPrototype(o3)); + CHECK(o3->SetPrototype(o2)); + CHECK(o2->SetPrototype(o1)); + + // Call the runtime version of GetLocalPropertyNames() on the natively + // created object through JavaScript. + context->Global()->Set(v8_str("obj"), o4); + CompileRun("var names = %GetLocalPropertyNames(obj);"); + + ExpectInt32("names.length", 1006); + ExpectTrue("names.indexOf(\"baz\") >= 0"); + ExpectTrue("names.indexOf(\"boo\") >= 0"); + ExpectTrue("names.indexOf(\"foo\") >= 0"); + ExpectTrue("names.indexOf(\"fuz1\") >= 0"); + ExpectTrue("names.indexOf(\"fuz2\") >= 0"); + ExpectFalse("names[1005] == undefined"); +} + + THREADED_TEST(FunctionReadOnlyPrototype) { v8::HandleScope handle_scope; LocalContext context; @@ -7241,7 +7590,7 @@ THREADED_TEST(Constructor) { Local<Function> cons = templ->GetFunction(); context->Global()->Set(v8_str("Fun"), cons); Local<v8::Object> inst = cons->NewInstance(); - i::Handle<i::JSObject> obj = v8::Utils::OpenHandle(*inst); + i::Handle<i::JSObject> obj(v8::Utils::OpenHandle(*inst)); Local<Value> value = CompileRun("(new Fun()).constructor === Fun"); CHECK(value->BooleanValue()); } @@ -7492,9 +7841,11 @@ THREADED_TEST(EvalAliasedDynamic) { " var bar = 2;" " with (x) { return eval('bar'); }" "}" - "f(this)")); + "result4 = f(this)")); script->Run(); - CHECK(try_catch.HasCaught()); + CHECK(!try_catch.HasCaught()); + CHECK_EQ(2, current->Global()->Get(v8_str("result4"))->Int32Value()); + try_catch.Reset(); } @@ -7710,7 +8061,7 @@ THREADED_TEST(CallAsFunction) { } { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(); - Local<ObjectTemplate> instance_template = t->InstanceTemplate(); + Local<ObjectTemplate> instance_template(t->InstanceTemplate()); Local<v8::Object> instance = t->GetFunction()->NewInstance(); context->Global()->Set(v8_str("obj2"), instance); v8::TryCatch try_catch; @@ -7815,7 +8166,7 @@ static int Recurse(int depth, int iterations) { v8::HandleScope scope; if (depth == 0) return CountHandles(); for (int i = 0; i < iterations; i++) { - Local<v8::Number> n = v8::Integer::New(42); + Local<v8::Number> n(v8::Integer::New(42)); } return Recurse(depth - 1, iterations); } @@ -7829,7 +8180,7 @@ THREADED_TEST(HandleIteration) { v8::HandleScope scope1; CHECK_EQ(0, CountHandles()); for (int i = 0; i < kIterations; i++) { - Local<v8::Number> n = v8::Integer::New(42); + Local<v8::Number> n(v8::Integer::New(42)); CHECK_EQ(i + 1, CountHandles()); } @@ -7837,7 +8188,7 @@ THREADED_TEST(HandleIteration) { { v8::HandleScope scope2; for (int j = 0; j < kIterations; j++) { - Local<v8::Number> n = v8::Integer::New(42); + Local<v8::Number> n(v8::Integer::New(42)); CHECK_EQ(j + 1 + kIterations, CountHandles()); } } @@ -7883,7 +8234,7 @@ static v8::Handle<Value> InterceptorHasOwnPropertyGetterGC( Local<String> name, const AccessorInfo& info) { ApiTestFuzzer::Fuzz(); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); return v8::Handle<Value>(); } @@ -8340,10 +8691,10 @@ THREADED_TEST(InterceptorStoreIC) { 0, 0, 0, v8_str("data")); LocalContext context; context->Global()->Set(v8_str("o"), templ->NewInstance()); - v8::Handle<Value> value = CompileRun( + v8::Handle<Value> value(CompileRun( "for (var i = 0; i < 1000; i++) {" " o.x = 42;" - "}"); + "}")); } @@ -8613,7 +8964,7 @@ static v8::Handle<Value> InterceptorCallICFastApi(Local<String> name, int* call_count = reinterpret_cast<int*>(v8::External::Unwrap(info.Data())); ++(*call_count); if ((*call_count) % 20 == 0) { - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); } return v8::Handle<Value>(); } @@ -8769,11 +9120,11 @@ THREADED_TEST(InterceptorCallICFastApi_TrivialSignature) { v8::Handle<v8::Function> fun = fun_templ->GetFunction(); GenerateSomeGarbage(); context->Global()->Set(v8_str("o"), fun->NewInstance()); - v8::Handle<Value> value = CompileRun( + v8::Handle<Value> value(CompileRun( "var result = 0;" "for (var i = 0; i < 100; i++) {" " result = o.method(41);" - "}"); + "}")); CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value()); CHECK_EQ(100, interceptor_call_count); } @@ -8796,14 +9147,14 @@ THREADED_TEST(InterceptorCallICFastApi_SimpleSignature) { v8::Handle<v8::Function> fun = fun_templ->GetFunction(); GenerateSomeGarbage(); context->Global()->Set(v8_str("o"), fun->NewInstance()); - v8::Handle<Value> value = CompileRun( + v8::Handle<Value> value(CompileRun( "o.foo = 17;" "var receiver = {};" "receiver.__proto__ = o;" "var result = 0;" "for (var i = 0; i < 100; i++) {" " result = receiver.method(41);" - "}"); + "}")); CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value()); CHECK_EQ(100, interceptor_call_count); } @@ -8826,7 +9177,7 @@ THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) { v8::Handle<v8::Function> fun = fun_templ->GetFunction(); GenerateSomeGarbage(); context->Global()->Set(v8_str("o"), fun->NewInstance()); - v8::Handle<Value> value = CompileRun( + v8::Handle<Value> value(CompileRun( "o.foo = 17;" "var receiver = {};" "receiver.__proto__ = o;" @@ -8838,7 +9189,7 @@ THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) { " saved_result = result;" " receiver = {method: function(x) { return x - 1 }};" " }" - "}"); + "}")); CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value()); CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value()); CHECK_GE(interceptor_call_count, 50); @@ -8862,7 +9213,7 @@ THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) { v8::Handle<v8::Function> fun = fun_templ->GetFunction(); GenerateSomeGarbage(); context->Global()->Set(v8_str("o"), fun->NewInstance()); - v8::Handle<Value> value = CompileRun( + v8::Handle<Value> value(CompileRun( "o.foo = 17;" "var receiver = {};" "receiver.__proto__ = o;" @@ -8874,7 +9225,7 @@ THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) { " saved_result = result;" " o.method = function(x) { return x - 1 };" " }" - "}"); + "}")); CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value()); CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value()); CHECK_GE(interceptor_call_count, 50); @@ -8899,7 +9250,7 @@ THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) { GenerateSomeGarbage(); context->Global()->Set(v8_str("o"), fun->NewInstance()); v8::TryCatch try_catch; - v8::Handle<Value> value = CompileRun( + v8::Handle<Value> value(CompileRun( "o.foo = 17;" "var receiver = {};" "receiver.__proto__ = o;" @@ -8911,7 +9262,7 @@ THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) { " saved_result = result;" " receiver = 333;" " }" - "}"); + "}")); CHECK(try_catch.HasCaught()); CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"), try_catch.Exception()->ToString()); @@ -8938,7 +9289,7 @@ THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) { GenerateSomeGarbage(); context->Global()->Set(v8_str("o"), fun->NewInstance()); v8::TryCatch try_catch; - v8::Handle<Value> value = CompileRun( + v8::Handle<Value> value(CompileRun( "o.foo = 17;" "var receiver = {};" "receiver.__proto__ = o;" @@ -8950,7 +9301,7 @@ THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) { " saved_result = result;" " receiver = {method: receiver.method};" " }" - "}"); + "}")); CHECK(try_catch.HasCaught()); CHECK_EQ(v8_str("TypeError: Illegal invocation"), try_catch.Exception()->ToString()); @@ -8967,16 +9318,16 @@ THREADED_TEST(CallICFastApi_TrivialSignature) { v8::Handle<v8::Signature>()); v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate(); proto_templ->Set(v8_str("method"), method_templ); - v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate(); + v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate()); LocalContext context; v8::Handle<v8::Function> fun = fun_templ->GetFunction(); GenerateSomeGarbage(); context->Global()->Set(v8_str("o"), fun->NewInstance()); - v8::Handle<Value> value = CompileRun( + v8::Handle<Value> value(CompileRun( "var result = 0;" "for (var i = 0; i < 100; i++) {" " result = o.method(41);" - "}"); + "}")); CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value()); } @@ -8990,19 +9341,19 @@ THREADED_TEST(CallICFastApi_SimpleSignature) { v8::Signature::New(fun_templ)); v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate(); proto_templ->Set(v8_str("method"), method_templ); - v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate(); + v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate()); LocalContext context; v8::Handle<v8::Function> fun = fun_templ->GetFunction(); GenerateSomeGarbage(); context->Global()->Set(v8_str("o"), fun->NewInstance()); - v8::Handle<Value> value = CompileRun( + v8::Handle<Value> value(CompileRun( "o.foo = 17;" "var receiver = {};" "receiver.__proto__ = o;" "var result = 0;" "for (var i = 0; i < 100; i++) {" " result = receiver.method(41);" - "}"); + "}")); CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value()); } @@ -9016,12 +9367,12 @@ THREADED_TEST(CallICFastApi_SimpleSignature_Miss1) { v8::Signature::New(fun_templ)); v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate(); proto_templ->Set(v8_str("method"), method_templ); - v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate(); + v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate()); LocalContext context; v8::Handle<v8::Function> fun = fun_templ->GetFunction(); GenerateSomeGarbage(); context->Global()->Set(v8_str("o"), fun->NewInstance()); - v8::Handle<Value> value = CompileRun( + v8::Handle<Value> value(CompileRun( "o.foo = 17;" "var receiver = {};" "receiver.__proto__ = o;" @@ -9033,7 +9384,7 @@ THREADED_TEST(CallICFastApi_SimpleSignature_Miss1) { " saved_result = result;" " receiver = {method: function(x) { return x - 1 }};" " }" - "}"); + "}")); CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value()); CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value()); } @@ -9047,13 +9398,13 @@ THREADED_TEST(CallICFastApi_SimpleSignature_Miss2) { v8::Signature::New(fun_templ)); v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate(); proto_templ->Set(v8_str("method"), method_templ); - v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate(); + v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate()); LocalContext context; v8::Handle<v8::Function> fun = fun_templ->GetFunction(); GenerateSomeGarbage(); context->Global()->Set(v8_str("o"), fun->NewInstance()); v8::TryCatch try_catch; - v8::Handle<Value> value = CompileRun( + v8::Handle<Value> value(CompileRun( "o.foo = 17;" "var receiver = {};" "receiver.__proto__ = o;" @@ -9065,7 +9416,7 @@ THREADED_TEST(CallICFastApi_SimpleSignature_Miss2) { " saved_result = result;" " receiver = 333;" " }" - "}"); + "}")); CHECK(try_catch.HasCaught()); CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"), try_catch.Exception()->ToString()); @@ -9093,7 +9444,7 @@ THREADED_TEST(InterceptorKeyedCallICKeyChange1) { templ->SetNamedPropertyHandler(NoBlockGetterX); LocalContext context; context->Global()->Set(v8_str("o"), templ->NewInstance()); - v8::Handle<Value> value = CompileRun( + v8::Handle<Value> value(CompileRun( "proto = new Object();" "proto.y = function(x) { return x + 1; };" "proto.z = function(x) { return x - 1; };" @@ -9103,7 +9454,7 @@ THREADED_TEST(InterceptorKeyedCallICKeyChange1) { "for (var i = 0; i < 10; i++) {" " if (i == 5) { method = 'z'; };" " result += o[method](41);" - "}"); + "}")); CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value()); } @@ -9119,7 +9470,7 @@ THREADED_TEST(InterceptorKeyedCallICKeyChange2) { context->Global()->Set(v8_str("proto1"), templ->NewInstance()); keyed_call_ic_function = v8_compile("function f(x) { return x - 1; }; f")->Run(); - v8::Handle<Value> value = CompileRun( + v8::Handle<Value> value(CompileRun( "o = new Object();" "proto2 = new Object();" "o.y = function(x) { return x + 1; };" @@ -9131,7 +9482,7 @@ THREADED_TEST(InterceptorKeyedCallICKeyChange2) { "for (var i = 0; i < 10; i++) {" " if (i == 5) { method = 'y'; };" " result += o[method](41);" - "}"); + "}")); CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value()); } @@ -9144,7 +9495,7 @@ THREADED_TEST(InterceptorKeyedCallICKeyChangeOnGlobal) { templ->SetNamedPropertyHandler(NoBlockGetterX); LocalContext context; context->Global()->Set(v8_str("o"), templ->NewInstance()); - v8::Handle<Value> value = CompileRun( + v8::Handle<Value> value(CompileRun( "function inc(x) { return x + 1; };" "inc(1);" "function dec(x) { return x - 1; };" @@ -9157,7 +9508,7 @@ THREADED_TEST(InterceptorKeyedCallICKeyChangeOnGlobal) { "for (var i = 0; i < 10; i++) {" " if (i == 5) { method = 'y'; };" " result += o[method](41);" - "}"); + "}")); CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value()); } @@ -9170,7 +9521,7 @@ THREADED_TEST(InterceptorKeyedCallICFromGlobal) { LocalContext context; context->Global()->Set(v8_str("o"), templ_o->NewInstance()); - v8::Handle<Value> value = CompileRun( + v8::Handle<Value> value(CompileRun( "function len(x) { return x.length; };" "o.__proto__ = this;" "var m = 'parseFloat';" @@ -9181,7 +9532,7 @@ THREADED_TEST(InterceptorKeyedCallICFromGlobal) { " saved_result = result;" " };" " result = o[m]('239');" - "}"); + "}")); CHECK_EQ(3, context->Global()->Get(v8_str("result"))->Int32Value()); CHECK_EQ(239, context->Global()->Get(v8_str("saved_result"))->Int32Value()); } @@ -9194,7 +9545,7 @@ THREADED_TEST(InterceptorKeyedCallICMapChangeBefore) { LocalContext context; context->Global()->Set(v8_str("proto"), templ_o->NewInstance()); - v8::Handle<Value> value = CompileRun( + v8::Handle<Value> value(CompileRun( "var o = new Object();" "o.__proto__ = proto;" "o.method = function(x) { return x + 1; };" @@ -9203,7 +9554,7 @@ THREADED_TEST(InterceptorKeyedCallICMapChangeBefore) { "for (var i = 0; i < 10; i++) {" " if (i == 5) { o.method = function(x) { return x - 1; }; };" " result += o[m](41);" - "}"); + "}")); CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value()); } @@ -9216,7 +9567,7 @@ THREADED_TEST(InterceptorKeyedCallICMapChangeAfter) { LocalContext context; context->Global()->Set(v8_str("o"), templ_o->NewInstance()); - v8::Handle<Value> value = CompileRun( + v8::Handle<Value> value(CompileRun( "var proto = new Object();" "o.__proto__ = proto;" "proto.method = function(x) { return x + 1; };" @@ -9225,7 +9576,7 @@ THREADED_TEST(InterceptorKeyedCallICMapChangeAfter) { "for (var i = 0; i < 10; i++) {" " if (i == 5) { proto.method = function(x) { return x - 1; }; };" " result += o[m](41);" - "}"); + "}")); CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value()); } @@ -9964,6 +10315,7 @@ THREADED_TEST(LockUnlockLock) { static int GetGlobalObjectsCount() { + i::Isolate::Current()->heap()->EnsureHeapIsIterable(); int count = 0; i::HeapIterator it; for (i::HeapObject* object = it.next(); object != NULL; object = it.next()) @@ -9978,9 +10330,8 @@ static void CheckSurvivingGlobalObjectsCount(int expected) { // the first garbage collection but some of the maps have already // been marked at that point. Therefore some of the maps are not // collected until the second garbage collection. - HEAP->global_context_map(); - HEAP->CollectAllGarbage(false); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); + HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask); int count = GetGlobalObjectsCount(); #ifdef DEBUG if (count != expected) HEAP->TracePathToGlobal(); @@ -10049,7 +10400,7 @@ THREADED_TEST(NewPersistentHandleFromWeakCallback) { // weak callback of the first handle would be able to 'reallocate' it. handle1.MakeWeak(NULL, NewPersistentHandleCallback); handle2.Dispose(); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); } @@ -10057,7 +10408,7 @@ v8::Persistent<v8::Object> to_be_disposed; void DisposeAndForceGcCallback(v8::Persistent<v8::Value> handle, void*) { to_be_disposed.Dispose(); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); handle.Dispose(); } @@ -10073,7 +10424,7 @@ THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) { } handle1.MakeWeak(NULL, DisposeAndForceGcCallback); to_be_disposed = handle2; - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); } void DisposingCallback(v8::Persistent<v8::Value> handle, void*) { @@ -10099,7 +10450,7 @@ THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) { } handle2.MakeWeak(NULL, DisposingCallback); handle3.MakeWeak(NULL, HandleCreatingCallback); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); } @@ -10141,7 +10492,7 @@ THREADED_TEST(NestedHandleScopeAndContexts) { v8::Persistent<Context> env = Context::New(); env->Enter(); v8::Handle<Value> value = NestedScope(env); - v8::Handle<String> str = value->ToString(); + v8::Handle<String> str(value->ToString()); env->Exit(); env.Dispose(); } @@ -10149,7 +10500,7 @@ THREADED_TEST(NestedHandleScopeAndContexts) { THREADED_TEST(ExternalAllocatedMemory) { v8::HandleScope outer; - v8::Persistent<Context> env = Context::New(); + v8::Persistent<Context> env(Context::New()); const int kSize = 1024*1024; CHECK_EQ(v8::V8::AdjustAmountOfExternalAllocatedMemory(kSize), kSize); CHECK_EQ(v8::V8::AdjustAmountOfExternalAllocatedMemory(-kSize), 0); @@ -10487,7 +10838,7 @@ THREADED_TEST(AccessControlRepeatedContextCreation) { i::Handle<i::FunctionTemplateInfo> constructor( i::FunctionTemplateInfo::cast(internal_template->constructor())); CHECK(!constructor->access_check_info()->IsUndefined()); - v8::Persistent<Context> context0 = Context::New(NULL, global_template); + v8::Persistent<Context> context0(Context::New(NULL, global_template)); CHECK(!constructor->access_check_info()->IsUndefined()); } @@ -10915,7 +11266,7 @@ class RegExpInterruptTest { { v8::Locker lock; // TODO(lrn): Perhaps create some garbage before collecting. - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); gc_count_++; } i::OS::Sleep(1); @@ -11037,7 +11388,7 @@ class ApplyInterruptTest { while (gc_during_apply_ < kRequiredGCs) { { v8::Locker lock; - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); gc_count_++; } i::OS::Sleep(1); @@ -11187,6 +11538,7 @@ static void MorphAString(i::String* string, // Test that we can still flatten a string if the components it is built up // from have been turned into 16 bit strings in the mean time. THREADED_TEST(MorphCompositeStringTest) { + char utf_buffer[129]; const char* c_string = "Now is the time for all good men" " to come to the aid of the party"; uint16_t* two_byte_string = AsciiToTwoByteString(c_string); @@ -11215,6 +11567,17 @@ THREADED_TEST(MorphCompositeStringTest) { MorphAString(*v8::Utils::OpenHandle(*lhs), &ascii_resource, &uc16_resource); MorphAString(*v8::Utils::OpenHandle(*rhs), &ascii_resource, &uc16_resource); + // This should UTF-8 without flattening, since everything is ASCII. + Handle<String> cons = v8_compile("cons")->Run().As<String>(); + CHECK_EQ(128, cons->Utf8Length()); + int nchars = -1; + CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars)); + CHECK_EQ(128, nchars); + CHECK_EQ(0, strcmp( + utf_buffer, + "Now is the time for all good men to come to the aid of the party" + "Now is the time for all good men to come to the aid of the party")); + // Now do some stuff to make sure the strings are flattened, etc. CompileRun( "/[^a-z]/.test(cons);" @@ -11753,13 +12116,15 @@ THREADED_TEST(PixelArray) { i::Handle<i::ExternalPixelArray> pixels = i::Handle<i::ExternalPixelArray>::cast( FACTORY->NewExternalArray(kElementCount, - v8::kExternalPixelArray, - pixel_data)); - HEAP->CollectAllGarbage(false); // Force GC to trigger verification. + v8::kExternalPixelArray, + pixel_data)); + // Force GC to trigger verification. + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); for (int i = 0; i < kElementCount; i++) { pixels->set(i, i % 256); } - HEAP->CollectAllGarbage(false); // Force GC to trigger verification. + // Force GC to trigger verification. + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); for (int i = 0; i < kElementCount; i++) { CHECK_EQ(i % 256, pixels->get_scalar(i)); CHECK_EQ(i % 256, pixel_data[i]); @@ -12235,11 +12600,13 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type, i::Handle<ExternalArrayClass> array = i::Handle<ExternalArrayClass>::cast( FACTORY->NewExternalArray(kElementCount, array_type, array_data)); - HEAP->CollectAllGarbage(false); // Force GC to trigger verification. + // Force GC to trigger verification. + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); for (int i = 0; i < kElementCount; i++) { array->set(i, static_cast<ElementType>(i)); } - HEAP->CollectAllGarbage(false); // Force GC to trigger verification. + // Force GC to trigger verification. + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); for (int i = 0; i < kElementCount; i++) { CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array->get_scalar(i))); @@ -12357,7 +12724,8 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type, " }" "}" "sum;"); - HEAP->CollectAllGarbage(false); // Force GC to trigger verification. + // Force GC to trigger verification. + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(28, result->Int32Value()); // Make sure out-of-range loads do not throw. @@ -12546,11 +12914,11 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type, const int kLargeElementCount = kXSize * kYSize * 4; ElementType* large_array_data = static_cast<ElementType*>(malloc(kLargeElementCount * element_size)); - i::Handle<ExternalArrayClass> large_array = + i::Handle<ExternalArrayClass> large_array( i::Handle<ExternalArrayClass>::cast( FACTORY->NewExternalArray(kLargeElementCount, - array_type, - array_data)); + array_type, + array_data))); v8::Handle<v8::Object> large_obj = v8::Object::New(); // Set the elements to be the external array. large_obj->SetIndexedPropertiesToExternalArrayData(large_array_data, @@ -12949,8 +13317,8 @@ TEST(CaptureStackTrace) { "}\n" "var x;eval('new foo();');"; v8::Handle<v8::String> overview_src = v8::String::New(overview_source); - v8::Handle<Value> overview_result = - v8::Script::New(overview_src, origin)->Run(); + v8::Handle<Value> overview_result( + v8::Script::New(overview_src, origin)->Run()); ASSERT(!overview_result.IsEmpty()); ASSERT(overview_result->IsObject()); @@ -12970,7 +13338,7 @@ TEST(CaptureStackTrace) { v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset); v8::Handle<v8::Script> detailed_script( v8::Script::New(detailed_src, &detailed_origin)); - v8::Handle<Value> detailed_result = detailed_script->Run(); + v8::Handle<Value> detailed_result(detailed_script->Run()); ASSERT(!detailed_result.IsEmpty()); ASSERT(detailed_result->IsObject()); } @@ -13250,7 +13618,13 @@ THREADED_TEST(QuietSignalingNaNs) { } else { uint64_t stored_bits = DoubleToBits(stored_number); // Check if quiet nan (bits 51..62 all set). +#if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR) + // Most significant fraction bit for quiet nan is set to 0 + // on MIPS architecture. Allowed by IEEE-754. + CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff)); +#else CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff)); +#endif } // Check that Date::New preserves non-NaNs in the date range and @@ -13263,7 +13637,13 @@ THREADED_TEST(QuietSignalingNaNs) { } else { uint64_t stored_bits = DoubleToBits(stored_date); // Check if quiet nan (bits 51..62 all set). +#if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR) + // Most significant fraction bit for quiet nan is set to 0 + // on MIPS architecture. Allowed by IEEE-754. + CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff)); +#else CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff)); +#endif } } } @@ -13272,7 +13652,7 @@ THREADED_TEST(QuietSignalingNaNs) { static v8::Handle<Value> SpaghettiIncident(const v8::Arguments& args) { v8::HandleScope scope; v8::TryCatch tc; - v8::Handle<v8::String> str = args[0]->ToString(); + v8::Handle<v8::String> str(args[0]->ToString()); if (tc.HasCaught()) return tc.ReThrow(); return v8::Undefined(); @@ -13337,7 +13717,7 @@ TEST(Regress528) { other_context->Enter(); CompileRun(source_simple); other_context->Exit(); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); if (GetGlobalObjectsCount() == 1) break; } CHECK_GE(2, gc_count); @@ -13359,7 +13739,7 @@ TEST(Regress528) { other_context->Enter(); CompileRun(source_eval); other_context->Exit(); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); if (GetGlobalObjectsCount() == 1) break; } CHECK_GE(2, gc_count); @@ -13386,7 +13766,7 @@ TEST(Regress528) { other_context->Enter(); CompileRun(source_exception); other_context->Exit(); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); if (GetGlobalObjectsCount() == 1) break; } CHECK_GE(2, gc_count); @@ -13434,6 +13814,41 @@ THREADED_TEST(ScriptLineNumber) { } +THREADED_TEST(ScriptColumnNumber) { + v8::HandleScope scope; + LocalContext env; + v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"), + v8::Integer::New(3), v8::Integer::New(2)); + v8::Handle<v8::String> script = v8::String::New( + "function foo() {}\n\n function bar() {}"); + v8::Script::Compile(script, &origin)->Run(); + v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast( + env->Global()->Get(v8::String::New("foo"))); + v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast( + env->Global()->Get(v8::String::New("bar"))); + CHECK_EQ(14, foo->GetScriptColumnNumber()); + CHECK_EQ(17, bar->GetScriptColumnNumber()); +} + + +THREADED_TEST(FunctionGetScriptId) { + v8::HandleScope scope; + LocalContext env; + v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"), + v8::Integer::New(3), v8::Integer::New(2)); + v8::Handle<v8::String> scriptSource = v8::String::New( + "function foo() {}\n\n function bar() {}"); + v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin)); + script->Run(); + v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast( + env->Global()->Get(v8::String::New("foo"))); + v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast( + env->Global()->Get(v8::String::New("bar"))); + CHECK_EQ(script->Id(), foo->GetScriptId()); + CHECK_EQ(script->Id(), bar->GetScriptId()); +} + + static v8::Handle<Value> GetterWhichReturns42(Local<String> name, const AccessorInfo& info) { return v8_num(42); @@ -13604,26 +14019,26 @@ TEST(GCCallbacks) { v8::V8::AddGCEpilogueCallback(EpilogueCallback); CHECK_EQ(0, prologue_call_count); CHECK_EQ(0, epilogue_call_count); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(1, prologue_call_count); CHECK_EQ(1, epilogue_call_count); v8::V8::AddGCPrologueCallback(PrologueCallbackSecond); v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(2, prologue_call_count); CHECK_EQ(2, epilogue_call_count); CHECK_EQ(1, prologue_call_count_second); CHECK_EQ(1, epilogue_call_count_second); v8::V8::RemoveGCPrologueCallback(PrologueCallback); v8::V8::RemoveGCEpilogueCallback(EpilogueCallback); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(2, prologue_call_count); CHECK_EQ(2, epilogue_call_count); CHECK_EQ(2, prologue_call_count_second); CHECK_EQ(2, epilogue_call_count_second); v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond); v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(2, prologue_call_count); CHECK_EQ(2, epilogue_call_count); CHECK_EQ(2, prologue_call_count_second); @@ -13840,7 +14255,7 @@ THREADED_TEST(TwoByteStringInAsciiCons) { void FailedAccessCheckCallbackGC(Local<v8::Object> target, v8::AccessType type, Local<v8::Value> data) { - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); } @@ -14414,7 +14829,7 @@ TEST(DontDeleteCellLoadIC) { "})()", "ReferenceError: cell is not defined"); CompileRun("cell = \"new_second\";"); - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); ExpectString("readCell()", "new_second"); ExpectString("readCell()", "new_second"); } @@ -14535,7 +14950,7 @@ TEST(RegExp) { // RegExps are objects on which you can set properties. re->Set(v8_str("property"), v8::Integer::New(32)); - v8::Handle<v8::Value> value = CompileRun("re.property"); + v8::Handle<v8::Value> value(CompileRun("re.property")); ASSERT_EQ(32, value->Int32Value()); v8::TryCatch try_catch; diff --git a/test/cctest/test-assembler-ia32.cc b/test/cctest/test-assembler-ia32.cc index 839b7f56..cdab8f7c 100644 --- a/test/cctest/test-assembler-ia32.cc +++ b/test/cctest/test-assembler-ia32.cc @@ -1,4 +1,4 @@ -// Copyright 2006-2008 the V8 project authors. All rights reserved. +// Copyright 2011 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: @@ -93,15 +93,15 @@ TEST(AssemblerIa321) { Label L, C; __ mov(edx, Operand(esp, 4)); - __ xor_(eax, Operand(eax)); // clear eax + __ xor_(eax, eax); // clear eax __ jmp(&C); __ bind(&L); - __ add(eax, Operand(edx)); - __ sub(Operand(edx), Immediate(1)); + __ add(eax, edx); + __ sub(edx, Immediate(1)); __ bind(&C); - __ test(edx, Operand(edx)); + __ test(edx, edx); __ j(not_zero, &L); __ ret(0); @@ -135,11 +135,11 @@ TEST(AssemblerIa322) { __ jmp(&C); __ bind(&L); - __ imul(eax, Operand(edx)); - __ sub(Operand(edx), Immediate(1)); + __ imul(eax, edx); + __ sub(edx, Immediate(1)); __ bind(&C); - __ test(edx, Operand(edx)); + __ test(edx, edx); __ j(not_zero, &L); __ ret(0); @@ -275,10 +275,10 @@ TEST(AssemblerIa326) { __ subsd(xmm0, xmm1); __ divsd(xmm0, xmm1); // Copy xmm0 to st(0) using eight bytes of stack. - __ sub(Operand(esp), Immediate(8)); + __ sub(esp, Immediate(8)); __ movdbl(Operand(esp, 0), xmm0); __ fld_d(Operand(esp, 0)); - __ add(Operand(esp), Immediate(8)); + __ add(esp, Immediate(8)); __ ret(0); CodeDesc desc; @@ -314,12 +314,12 @@ TEST(AssemblerIa328) { v8::internal::byte buffer[256]; Assembler assm(Isolate::Current(), buffer, sizeof buffer); __ mov(eax, Operand(esp, 4)); - __ cvtsi2sd(xmm0, Operand(eax)); + __ cvtsi2sd(xmm0, eax); // Copy xmm0 to st(0) using eight bytes of stack. - __ sub(Operand(esp), Immediate(8)); + __ sub(esp, Immediate(8)); __ movdbl(Operand(esp, 0), xmm0); __ fld_d(Operand(esp, 0)); - __ add(Operand(esp), Immediate(8)); + __ add(esp, Immediate(8)); __ ret(0); CodeDesc desc; assm.GetCode(&desc); diff --git a/test/cctest/test-compiler.cc b/test/cctest/test-compiler.cc index 2d9b0120..7f63ebca 100644 --- a/test/cctest/test-compiler.cc +++ b/test/cctest/test-compiler.cc @@ -1,4 +1,4 @@ -// Copyright 2006-2008 the V8 project authors. All rights reserved. +// Copyright 2011 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: @@ -270,8 +270,8 @@ TEST(UncaughtThrow) { CHECK(!fun.is_null()); bool has_pending_exception; Handle<JSObject> global(Isolate::Current()->context()->global()); - Handle<Object> result = - Execution::Call(fun, global, 0, NULL, &has_pending_exception); + Handle<Object> result( + Execution::Call(fun, global, 0, NULL, &has_pending_exception)); CHECK(has_pending_exception); CHECK_EQ(42.0, Isolate::Current()->pending_exception()-> ToObjectChecked()->Number()); @@ -305,10 +305,11 @@ TEST(C2JSFrames) { Handle<Object> fun1(fun1_object->ToObjectChecked()); CHECK(fun1->IsJSFunction()); - Object** argv[1] = { - Handle<Object>::cast(FACTORY->LookupAsciiSymbol("hello")).location() - }; - Execution::Call(Handle<JSFunction>::cast(fun1), global, 1, argv, + Handle<Object> argv[] = { FACTORY->LookupAsciiSymbol("hello") }; + Execution::Call(Handle<JSFunction>::cast(fun1), + global, + ARRAY_SIZE(argv), + argv, &has_pending_exception); CHECK(!has_pending_exception); } diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc index 45da6dc0..a9e28362 100644 --- a/test/cctest/test-debug.cc +++ b/test/cctest/test-debug.cc @@ -409,11 +409,8 @@ Handle<FixedArray> GetDebuggedFunctions() { static Handle<Code> ComputeCallDebugBreak(int argc) { - CALL_HEAP_FUNCTION( - v8::internal::Isolate::Current(), - v8::internal::Isolate::Current()->stub_cache()->ComputeCallDebugBreak( - argc, Code::CALL_IC), - Code); + return Isolate::Current()->stub_cache()->ComputeCallDebugBreak(argc, + Code::CALL_IC); } @@ -425,8 +422,8 @@ void CheckDebuggerUnloaded(bool check_functions) { CHECK_EQ(NULL, Isolate::Current()->debug()->debug_info_list_); // Collect garbage to ensure weak handles are cleared. - HEAP->CollectAllGarbage(false); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); + HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask); // Iterate the head and check that there are no debugger related objects left. HeapIterator iterator; @@ -859,7 +856,7 @@ static void DebugEventRemoveBreakPoint(v8::DebugEvent event, if (event == v8::Break) { break_point_hit_count++; - v8::Handle<v8::Function> fun = v8::Handle<v8::Function>::Cast(data); + v8::Handle<v8::Function> fun(v8::Handle<v8::Function>::Cast(data)); ClearBreakPoint(debug_event_remove_break_point); } } @@ -944,7 +941,7 @@ static void DebugEventBreakPointCollectGarbage( HEAP->CollectGarbage(v8::internal::NEW_SPACE); } else { // Mark sweep compact. - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); } } } @@ -1417,8 +1414,7 @@ TEST(GCDuringBreakPointProcessing) { // Call the function three times with different garbage collections in between // and make sure that the break point survives. static void CallAndGC(v8::Local<v8::Object> recv, - v8::Local<v8::Function> f, - bool force_compaction) { + v8::Local<v8::Function> f) { break_point_hit_count = 0; for (int i = 0; i < 3; i++) { @@ -1432,14 +1428,15 @@ static void CallAndGC(v8::Local<v8::Object> recv, CHECK_EQ(2 + i * 3, break_point_hit_count); // Mark sweep (and perhaps compact) and call function. - HEAP->CollectAllGarbage(force_compaction); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); f->Call(recv, 0, NULL); CHECK_EQ(3 + i * 3, break_point_hit_count); } } -static void TestBreakPointSurviveGC(bool force_compaction) { +// Test that a break point can be set at a return store location. +TEST(BreakPointSurviveGC) { break_point_hit_count = 0; v8::HandleScope scope; DebugLocalContext env; @@ -1450,50 +1447,50 @@ static void TestBreakPointSurviveGC(bool force_compaction) { // Test IC store break point with garbage collection. { - v8::Local<v8::Function> bar = - CompileFunction(&env, "function foo(){}", "foo"); + v8::Local<v8::Function> bar( + CompileFunction(&env, "function foo(){}", "foo")); foo = CompileFunction(&env, "function foo(){bar=0;}", "foo"); SetBreakPoint(foo, 0); } - CallAndGC(env->Global(), foo, force_compaction); + CallAndGC(env->Global(), foo); // Test IC load break point with garbage collection. { - v8::Local<v8::Function> bar = - CompileFunction(&env, "function foo(){}", "foo"); + v8::Local<v8::Function> bar( + CompileFunction(&env, "function foo(){}", "foo")); foo = CompileFunction(&env, "bar=1;function foo(){var x=bar;}", "foo"); SetBreakPoint(foo, 0); } - CallAndGC(env->Global(), foo, force_compaction); + CallAndGC(env->Global(), foo); // Test IC call break point with garbage collection. { - v8::Local<v8::Function> bar = - CompileFunction(&env, "function foo(){}", "foo"); + v8::Local<v8::Function> bar( + CompileFunction(&env, "function foo(){}", "foo")); foo = CompileFunction(&env, "function bar(){};function foo(){bar();}", "foo"); SetBreakPoint(foo, 0); } - CallAndGC(env->Global(), foo, force_compaction); + CallAndGC(env->Global(), foo); // Test return break point with garbage collection. { - v8::Local<v8::Function> bar = - CompileFunction(&env, "function foo(){}", "foo"); + v8::Local<v8::Function> bar( + CompileFunction(&env, "function foo(){}", "foo")); foo = CompileFunction(&env, "function foo(){}", "foo"); SetBreakPoint(foo, 0); } - CallAndGC(env->Global(), foo, force_compaction); + CallAndGC(env->Global(), foo); // Test non IC break point with garbage collection. { - v8::Local<v8::Function> bar = - CompileFunction(&env, "function foo(){}", "foo"); + v8::Local<v8::Function> bar( + CompileFunction(&env, "function foo(){}", "foo")); foo = CompileFunction(&env, "function foo(){var bar=0;}", "foo"); SetBreakPoint(foo, 0); } - CallAndGC(env->Global(), foo, force_compaction); + CallAndGC(env->Global(), foo); v8::Debug::SetDebugEventListener(NULL); @@ -1501,13 +1498,6 @@ static void TestBreakPointSurviveGC(bool force_compaction) { } -// Test that a break point can be set at a return store location. -TEST(BreakPointSurviveGC) { - TestBreakPointSurviveGC(false); - TestBreakPointSurviveGC(true); -} - - // Test that break points can be set using the global Debug object. TEST(BreakPointThroughJavaScript) { break_point_hit_count = 0; @@ -2259,7 +2249,7 @@ TEST(ScriptBreakPointLineTopLevel) { } f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f"))); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); SetScriptBreakPointByNameFromJS("test.html", 3, -1); @@ -3761,8 +3751,8 @@ TEST(BreakOnException) { v8::internal::Isolate::Current()->TraceException(false); // Create functions for testing break on exception. - v8::Local<v8::Function> throws = - CompileFunction(&env, "function throws(){throw 1;}", "throws"); + v8::Local<v8::Function> throws( + CompileFunction(&env, "function throws(){throw 1;}", "throws")); v8::Local<v8::Function> caught = CompileFunction(&env, "function caught(){try {throws();} catch(e) {};}", @@ -5557,10 +5547,10 @@ TEST(DebuggerUnload) { v8::HandleScope scope; // Get the test functions again. - v8::Local<v8::Function> foo = - v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("foo"))); - v8::Local<v8::Function> bar = - v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("foo"))); + v8::Local<v8::Function> foo(v8::Local<v8::Function>::Cast( + env->Global()->Get(v8::String::New("foo")))); + v8::Local<v8::Function> bar(v8::Local<v8::Function>::Cast( + env->Global()->Get(v8::String::New("foo")))); foo->Call(env->Global(), 0, NULL); CHECK_EQ(0, break_point_hit_count); @@ -6037,7 +6027,7 @@ TEST(DebugGetLoadedScripts) { EmptyExternalStringResource source_ext_str; v8::Local<v8::String> source = v8::String::NewExternal(&source_ext_str); - v8::Handle<v8::Script> evil_script = v8::Script::Compile(source); + v8::Handle<v8::Script> evil_script(v8::Script::Compile(source)); Handle<i::ExternalTwoByteString> i_source( i::ExternalTwoByteString::cast(*v8::Utils::OpenHandle(*source))); // This situation can happen if source was an external string disposed @@ -6472,7 +6462,7 @@ TEST(ScriptCollectedEvent) { // Do garbage collection to ensure that only the script in this test will be // collected afterwards. - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); script_collected_count = 0; v8::Debug::SetDebugEventListener(DebugEventScriptCollectedEvent, @@ -6484,7 +6474,7 @@ TEST(ScriptCollectedEvent) { // Do garbage collection to collect the script above which is no longer // referenced. - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); CHECK_EQ(2, script_collected_count); @@ -6520,7 +6510,7 @@ TEST(ScriptCollectedEventContext) { // Do garbage collection to ensure that only the script in this test will be // collected afterwards. - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); v8::Debug::SetMessageHandler2(ScriptCollectedMessageHandler); { @@ -6531,7 +6521,7 @@ TEST(ScriptCollectedEventContext) { // Do garbage collection to collect the script above which is no longer // referenced. - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); CHECK_EQ(2, script_collected_message_count); @@ -6685,7 +6675,7 @@ static void BreakMessageHandler(const v8::Debug::Message& message) { break_point_hit_count++; v8::HandleScope scope; - v8::Handle<v8::String> json = message.GetJSON(); + v8::Handle<v8::String> json(message.GetJSON()); SendContinueCommand(); } else if (message.IsEvent() && message.GetEvent() == v8::AfterCompile) { @@ -6696,7 +6686,7 @@ static void BreakMessageHandler(const v8::Debug::Message& message) { isolate->stack_guard()->DebugBreak(); // Force serialization to trigger some internal JS execution. - v8::Handle<v8::String> json = message.GetJSON(); + v8::Handle<v8::String> json(message.GetJSON()); // Restore previous state. if (is_debug_break) { diff --git a/test/cctest/test-decls.cc b/test/cctest/test-decls.cc index 61983918..aa733c70 100644 --- a/test/cctest/test-decls.cc +++ b/test/cctest/test-decls.cc @@ -232,7 +232,7 @@ TEST(Unknown) { context.Check("const x; x", 1, // access 2, // declaration + initialization - 2, // declaration + initialization + 1, // declaration EXPECT_RESULT, Undefined()); } @@ -240,7 +240,7 @@ TEST(Unknown) { context.Check("const x = 0; x", 1, // access 2, // declaration + initialization - 2, // declaration + initialization + 1, // declaration EXPECT_RESULT, Undefined()); // SB 0 - BUG 1213579 } } @@ -285,18 +285,18 @@ TEST(Present) { { PresentPropertyContext context; context.Check("const x; x", - 0, - 0, + 1, // access + 1, // initialization 1, // (re-)declaration - EXPECT_EXCEPTION); // x has already been declared! + EXPECT_RESULT, Undefined()); } { PresentPropertyContext context; context.Check("const x = 0; x", - 0, - 0, + 1, // access + 1, // initialization 1, // (re-)declaration - EXPECT_EXCEPTION); // x has already been declared! + EXPECT_RESULT, Number::New(0)); } } @@ -341,7 +341,7 @@ TEST(Absent) { context.Check("const x; x", 1, // access 2, // declaration + initialization - 2, // declaration + initializetion + 1, // declaration EXPECT_RESULT, Undefined()); } @@ -349,7 +349,7 @@ TEST(Absent) { context.Check("const x = 0; x", 1, // access 2, // declaration + initialization - 2, // declaration + initialization + 1, // declaration EXPECT_RESULT, Undefined()); // SB 0 - BUG 1213579 } @@ -429,18 +429,20 @@ TEST(Appearing) { { AppearingPropertyContext context; context.Check("const x; x", - 0, - 1, // declaration + 1, // access 2, // declaration + initialization - EXPECT_EXCEPTION); // x has already been declared! + 1, // declaration + EXPECT_RESULT, Undefined()); } { AppearingPropertyContext context; context.Check("const x = 0; x", - 0, - 1, // declaration + 1, // access 2, // declaration + initialization - EXPECT_EXCEPTION); // x has already been declared! + 1, // declaration + EXPECT_RESULT, Undefined()); + // Result is undefined because declaration succeeded but + // initialization to 0 failed (due to context behavior). } } @@ -496,9 +498,9 @@ TEST(Reappearing) { { ReappearingPropertyContext context; context.Check("const x; var x = 0", 0, - 2, // var declaration + const initialization - 4, // 2 x declaration + 2 x initialization - EXPECT_EXCEPTION); // x has already been declared! + 3, // const declaration+initialization, var initialization + 3, // 2 x declaration + var initialization + EXPECT_RESULT, Undefined()); } } diff --git a/test/cctest/test-deoptimization.cc b/test/cctest/test-deoptimization.cc index 056c9818..c713b021 100644 --- a/test/cctest/test-deoptimization.cc +++ b/test/cctest/test-deoptimization.cc @@ -237,7 +237,7 @@ TEST(DeoptimizeRecursive) { v8::Local<v8::Function> fun = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f"))); - Handle<v8::internal::JSFunction> f = v8::Utils::OpenHandle(*fun); + Handle<v8::internal::JSFunction> f(v8::Utils::OpenHandle(*fun)); } diff --git a/test/cctest/test-dictionary.cc b/test/cctest/test-dictionary.cc index 15a854b3..793e228a 100644 --- a/test/cctest/test-dictionary.cc +++ b/test/cctest/test-dictionary.cc @@ -38,6 +38,7 @@ using namespace v8::internal; + TEST(ObjectHashTable) { v8::HandleScope scope; LocalContext context; @@ -66,7 +67,8 @@ TEST(ObjectHashTable) { CHECK_EQ(table->NumberOfDeletedElements(), 1); CHECK_EQ(table->Lookup(*a), HEAP->undefined_value()); - // Keys should map back to their respective values. + // Keys should map back to their respective values and also should get + // an identity hash code generated. for (int i = 0; i < 100; i++) { Handle<JSObject> key = FACTORY->NewJSArray(7); Handle<JSObject> value = FACTORY->NewJSArray(11); @@ -74,12 +76,67 @@ TEST(ObjectHashTable) { CHECK_EQ(table->NumberOfElements(), i + 1); CHECK_NE(table->FindEntry(*key), ObjectHashTable::kNotFound); CHECK_EQ(table->Lookup(*key), *value); + CHECK(key->GetIdentityHash(OMIT_CREATION)->ToObjectChecked()->IsSmi()); + } + + // Keys never added to the map which already have an identity hash + // code should not be found. + for (int i = 0; i < 100; i++) { + Handle<JSObject> key = FACTORY->NewJSArray(7); + CHECK(key->GetIdentityHash(ALLOW_CREATION)->ToObjectChecked()->IsSmi()); + CHECK_EQ(table->FindEntry(*key), ObjectHashTable::kNotFound); + CHECK_EQ(table->Lookup(*key), HEAP->undefined_value()); + CHECK(key->GetIdentityHash(OMIT_CREATION)->ToObjectChecked()->IsSmi()); } - // Keys never added to the map should not be found. - for (int i = 0; i < 1000; i++) { - Handle<JSObject> o = FACTORY->NewJSArray(100); - CHECK_EQ(table->FindEntry(*o), ObjectHashTable::kNotFound); - CHECK_EQ(table->Lookup(*o), HEAP->undefined_value()); + // Keys that don't have an identity hash should not be found and also + // should not get an identity hash code generated. + for (int i = 0; i < 100; i++) { + Handle<JSObject> key = FACTORY->NewJSArray(7); + CHECK_EQ(table->Lookup(*key), HEAP->undefined_value()); + CHECK_EQ(key->GetIdentityHash(OMIT_CREATION), HEAP->undefined_value()); } } + + +#ifdef DEBUG +TEST(ObjectHashSetCausesGC) { + v8::HandleScope scope; + LocalContext context; + Handle<ObjectHashSet> table = FACTORY->NewObjectHashSet(1); + Handle<JSObject> key = FACTORY->NewJSArray(0); + + // Simulate a full heap so that generating an identity hash code + // in subsequent calls will request GC. + FLAG_gc_interval = 0; + + // Calling Contains() should not cause GC ever. + CHECK(!table->Contains(*key)); + + // Calling Remove() should not cause GC ever. + CHECK(!table->Remove(*key)->IsFailure()); + + // Calling Add() should request GC by returning a failure. + CHECK(table->Add(*key)->IsRetryAfterGC()); +} +#endif + + +#ifdef DEBUG +TEST(ObjectHashTableCausesGC) { + v8::HandleScope scope; + LocalContext context; + Handle<ObjectHashTable> table = FACTORY->NewObjectHashTable(1); + Handle<JSObject> key = FACTORY->NewJSArray(0); + + // Simulate a full heap so that generating an identity hash code + // in subsequent calls will request GC. + FLAG_gc_interval = 0; + + // Calling Lookup() should not cause GC ever. + CHECK(table->Lookup(*key)->IsUndefined()); + + // Calling Put() should request GC by returning a failure. + CHECK(table->Put(*key, *key)->IsRetryAfterGC()); +} +#endif diff --git a/test/cctest/test-disasm-ia32.cc b/test/cctest/test-disasm-ia32.cc index 9f7d0bb6..1e38e4ea 100644 --- a/test/cctest/test-disasm-ia32.cc +++ b/test/cctest/test-disasm-ia32.cc @@ -1,4 +1,4 @@ -// Copyright 2007-2008 the V8 project authors. All rights reserved. +// Copyright 2011 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: @@ -63,9 +63,9 @@ TEST(DisasmIa320) { // Short immediate instructions __ adc(eax, 12345678); - __ add(Operand(eax), Immediate(12345678)); + __ add(eax, Immediate(12345678)); __ or_(eax, 12345678); - __ sub(Operand(eax), Immediate(12345678)); + __ sub(eax, Immediate(12345678)); __ xor_(eax, 12345678); __ and_(eax, 12345678); Handle<FixedArray> foo = FACTORY->NewFixedArray(10, TENURED); @@ -75,7 +75,7 @@ TEST(DisasmIa320) { __ mov(ebx, Operand(esp, ecx, times_2, 0)); // [esp+ecx*4] // ---- All instructions that I can think of - __ add(edx, Operand(ebx)); + __ add(edx, ebx); __ add(edx, Operand(12, RelocInfo::NONE)); __ add(edx, Operand(ebx, 0)); __ add(edx, Operand(ebx, 16)); @@ -89,7 +89,7 @@ TEST(DisasmIa320) { __ add(Operand(ebp, ecx, times_4, 12), Immediate(12)); __ nop(); - __ add(Operand(ebx), Immediate(12)); + __ add(ebx, Immediate(12)); __ nop(); __ adc(ecx, 12); __ adc(ecx, 1000); @@ -116,16 +116,16 @@ TEST(DisasmIa320) { CpuFeatures::Scope fscope(RDTSC); __ rdtsc(); } - __ movsx_b(edx, Operand(ecx)); - __ movsx_w(edx, Operand(ecx)); - __ movzx_b(edx, Operand(ecx)); - __ movzx_w(edx, Operand(ecx)); + __ movsx_b(edx, ecx); + __ movsx_w(edx, ecx); + __ movzx_b(edx, ecx); + __ movzx_w(edx, ecx); __ nop(); - __ imul(edx, Operand(ecx)); - __ shld(edx, Operand(ecx)); - __ shrd(edx, Operand(ecx)); - __ bts(Operand(edx), ecx); + __ imul(edx, ecx); + __ shld(edx, ecx); + __ shrd(edx, ecx); + __ bts(edx, ecx); __ bts(Operand(ebx, ecx, times_4, 0), ecx); __ nop(); __ pushad(); @@ -146,9 +146,9 @@ TEST(DisasmIa320) { __ nop(); __ add(edx, Operand(esp, 16)); - __ add(edx, Operand(ecx)); - __ mov_b(edx, Operand(ecx)); - __ mov_b(Operand(ecx), 6); + __ add(edx, ecx); + __ mov_b(edx, ecx); + __ mov_b(ecx, 6); __ mov_b(Operand(ebx, ecx, times_4, 10000), 6); __ mov_b(Operand(esp, 16), edx); __ mov_w(edx, Operand(esp, 16)); @@ -216,22 +216,20 @@ TEST(DisasmIa320) { __ adc(edx, 12345); - __ add(Operand(ebx), Immediate(12)); + __ add(ebx, Immediate(12)); __ add(Operand(edx, ecx, times_4, 10000), Immediate(12)); __ and_(ebx, 12345); __ cmp(ebx, 12345); - __ cmp(Operand(ebx), Immediate(12)); + __ cmp(ebx, Immediate(12)); __ cmp(Operand(edx, ecx, times_4, 10000), Immediate(12)); + __ cmpb(eax, 100); __ or_(ebx, 12345); - __ sub(Operand(ebx), Immediate(12)); + __ sub(ebx, Immediate(12)); __ sub(Operand(edx, ecx, times_4, 10000), Immediate(12)); - __ subb(Operand(edx, ecx, times_4, 10000), 100); - __ subb(Operand(eax), 100); - __ subb(eax, Operand(edx, ecx, times_4, 10000)); __ xor_(ebx, 12345); @@ -244,7 +242,7 @@ TEST(DisasmIa320) { __ stos(); __ sub(edx, Operand(ebx, ecx, times_4, 10000)); - __ sub(edx, Operand(ebx)); + __ sub(edx, ebx); __ test(edx, Immediate(12345)); __ test(edx, Operand(ebx, ecx, times_8, 10000)); @@ -446,8 +444,8 @@ TEST(DisasmIa320) { { if (CpuFeatures::IsSupported(SSE4_1)) { CpuFeatures::Scope scope(SSE4_1); - __ pextrd(Operand(eax), xmm0, 1); - __ pinsrd(xmm1, Operand(eax), 0); + __ pextrd(eax, xmm0, 1); + __ pinsrd(xmm1, eax, 0); } } diff --git a/test/cctest/test-hashing.cc b/test/cctest/test-hashing.cc index a6265105..9c342a9e 100644 --- a/test/cctest/test-hashing.cc +++ b/test/cctest/test-hashing.cc @@ -46,108 +46,66 @@ typedef uint32_t (*HASH_FUNCTION)(); static v8::Persistent<v8::Context> env; -#define __ masm-> +#define __ assm-> -void generate(MacroAssembler* masm, i::Vector<const char> string) { - // GenerateHashInit takes the first character as an argument so it can't - // handle the zero length string. - ASSERT(string.length() > 0); +void generate(MacroAssembler* assm, i::Vector<const char> string) { #ifdef V8_TARGET_ARCH_IA32 __ push(ebx); __ push(ecx); __ mov(eax, Immediate(0)); - __ mov(ebx, Immediate(string.at(0))); - StringHelper::GenerateHashInit(masm, eax, ebx, ecx); + if (string.length() > 0) { + __ mov(ebx, Immediate(string.at(0))); + StringHelper::GenerateHashInit(assm, eax, ebx, ecx); + } for (int i = 1; i < string.length(); i++) { __ mov(ebx, Immediate(string.at(i))); - StringHelper::GenerateHashAddCharacter(masm, eax, ebx, ecx); + StringHelper::GenerateHashAddCharacter(assm, eax, ebx, ecx); } - StringHelper::GenerateHashGetHash(masm, eax, ecx); + StringHelper::GenerateHashGetHash(assm, eax, ecx); __ pop(ecx); __ pop(ebx); __ Ret(); #elif V8_TARGET_ARCH_X64 - __ push(kRootRegister); - __ InitializeRootRegister(); __ push(rbx); __ push(rcx); __ movq(rax, Immediate(0)); - __ movq(rbx, Immediate(string.at(0))); - StringHelper::GenerateHashInit(masm, rax, rbx, rcx); + if (string.length() > 0) { + __ movq(rbx, Immediate(string.at(0))); + StringHelper::GenerateHashInit(assm, rax, rbx, rcx); + } for (int i = 1; i < string.length(); i++) { __ movq(rbx, Immediate(string.at(i))); - StringHelper::GenerateHashAddCharacter(masm, rax, rbx, rcx); + StringHelper::GenerateHashAddCharacter(assm, rax, rbx, rcx); } - StringHelper::GenerateHashGetHash(masm, rax, rcx); + StringHelper::GenerateHashGetHash(assm, rax, rcx); __ pop(rcx); __ pop(rbx); - __ pop(kRootRegister); __ Ret(); #elif V8_TARGET_ARCH_ARM - __ push(kRootRegister); - __ InitializeRootRegister(); - __ mov(r0, Operand(0)); - __ mov(ip, Operand(string.at(0))); - StringHelper::GenerateHashInit(masm, r0, ip); + if (string.length() > 0) { + __ mov(ip, Operand(string.at(0))); + StringHelper::GenerateHashInit(assm, r0, ip); + } for (int i = 1; i < string.length(); i++) { __ mov(ip, Operand(string.at(i))); - StringHelper::GenerateHashAddCharacter(masm, r0, ip); + StringHelper::GenerateHashAddCharacter(assm, r0, ip); } - StringHelper::GenerateHashGetHash(masm, r0); - __ pop(kRootRegister); + StringHelper::GenerateHashGetHash(assm, r0); __ mov(pc, Operand(lr)); #elif V8_TARGET_ARCH_MIPS - __ push(kRootRegister); - __ InitializeRootRegister(); - __ li(v0, Operand(0)); - __ li(t1, Operand(string.at(0))); - StringHelper::GenerateHashInit(masm, v0, t1); + if (string.length() > 0) { + __ li(t1, Operand(string.at(0))); + StringHelper::GenerateHashInit(assm, v0, t1); + } for (int i = 1; i < string.length(); i++) { __ li(t1, Operand(string.at(i))); - StringHelper::GenerateHashAddCharacter(masm, v0, t1); + StringHelper::GenerateHashAddCharacter(assm, v0, t1); } - StringHelper::GenerateHashGetHash(masm, v0); - __ pop(kRootRegister); - __ jr(ra); - __ nop(); -#endif -} - - -void generate(MacroAssembler* masm, uint32_t key) { -#ifdef V8_TARGET_ARCH_IA32 - __ push(ebx); - __ mov(eax, Immediate(key)); - __ GetNumberHash(eax, ebx); - __ pop(ebx); - __ Ret(); -#elif V8_TARGET_ARCH_X64 - __ push(kRootRegister); - __ InitializeRootRegister(); - __ push(rbx); - __ movq(rax, Immediate(key)); - __ GetNumberHash(rax, rbx); - __ pop(rbx); - __ pop(kRootRegister); - __ Ret(); -#elif V8_TARGET_ARCH_ARM - __ push(kRootRegister); - __ InitializeRootRegister(); - __ mov(r0, Operand(key)); - __ GetNumberHash(r0, ip); - __ pop(kRootRegister); - __ mov(pc, Operand(lr)); -#elif V8_TARGET_ARCH_MIPS - __ push(kRootRegister); - __ InitializeRootRegister(); - __ li(v0, Operand(key)); - __ GetNumberHash(v0, t1); - __ pop(kRootRegister); + StringHelper::GenerateHashGetHash(assm, v0); __ jr(ra); - __ nop(); #endif } @@ -155,19 +113,19 @@ void generate(MacroAssembler* masm, uint32_t key) { void check(i::Vector<const char> string) { v8::HandleScope scope; v8::internal::byte buffer[2048]; - MacroAssembler masm(Isolate::Current(), buffer, sizeof buffer); + MacroAssembler assm(Isolate::Current(), buffer, sizeof buffer); - generate(&masm, string); + generate(&assm, string); CodeDesc desc; - masm.GetCode(&desc); + assm.GetCode(&desc); Code* code = Code::cast(HEAP->CreateCode( desc, Code::ComputeFlags(Code::STUB), Handle<Object>(HEAP->undefined_value()))->ToObjectChecked()); CHECK(code->IsCode()); - HASH_FUNCTION hash = FUNCTION_CAST<HASH_FUNCTION>(code->entry()); + HASH_FUNCTION hash = FUNCTION_CAST<HASH_FUNCTION>(Code::cast(code)->entry()); Handle<String> v8_string = FACTORY->NewStringFromAscii(string); v8_string->set_hash_field(String::kEmptyHashField); #ifdef USE_SIMULATOR @@ -181,47 +139,12 @@ void check(i::Vector<const char> string) { } -void check(uint32_t key) { - v8::HandleScope scope; - v8::internal::byte buffer[2048]; - MacroAssembler masm(Isolate::Current(), buffer, sizeof buffer); - - generate(&masm, key); - - CodeDesc desc; - masm.GetCode(&desc); - Code* code = Code::cast(HEAP->CreateCode( - desc, - Code::ComputeFlags(Code::STUB), - Handle<Object>(HEAP->undefined_value()))->ToObjectChecked()); - CHECK(code->IsCode()); - - HASH_FUNCTION hash = FUNCTION_CAST<HASH_FUNCTION>(code->entry()); -#ifdef USE_SIMULATOR - uint32_t codegen_hash = - reinterpret_cast<uint32_t>(CALL_GENERATED_CODE(hash, 0, 0, 0, 0, 0)); -#else - uint32_t codegen_hash = hash(); -#endif - - uint32_t runtime_hash = ComputeIntegerHash( - key, - Isolate::Current()->heap()->HashSeed()); - CHECK(runtime_hash == codegen_hash); -} - - void check_twochars(char a, char b) { char ab[2] = {a, b}; check(i::Vector<const char>(ab, 2)); } -static uint32_t PseudoRandom(uint32_t i, uint32_t j) { - return ~(~((i * 781) ^ (j * 329))); -} - - TEST(StringHash) { if (env.IsEmpty()) env = v8::Context::New(); for (int a = 0; a < String::kMaxAsciiCharCode; a++) { @@ -232,6 +155,7 @@ TEST(StringHash) { check_twochars(static_cast<char>(a), static_cast<char>(b)); } } + check(i::Vector<const char>("", 0)); check(i::Vector<const char>("*", 1)); check(i::Vector<const char>(".zZ", 3)); check(i::Vector<const char>("muc", 3)); @@ -239,22 +163,4 @@ TEST(StringHash) { check(i::Vector<const char>("-=[ vee eight ftw ]=-", 21)); } - -TEST(NumberHash) { - if (env.IsEmpty()) env = v8::Context::New(); - - // Some specific numbers - for (uint32_t key = 0; key < 42; key += 7) { - check(key); - } - - // Some pseudo-random numbers - static const uint32_t kLimit = 1000; - for (uint32_t i = 0; i < 5; i++) { - for (uint32_t j = 0; j < 5; j++) { - check(PseudoRandom(i, j) % kLimit); - } - } -} - #undef __ diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc index 6c2afd47..81b68a71 100644 --- a/test/cctest/test-heap-profiler.cc +++ b/test/cctest/test-heap-profiler.cc @@ -252,6 +252,28 @@ TEST(HeapSnapshotHeapNumbers) { CHECK_EQ(v8::HeapGraphNode::kHeapNumber, b->GetType()); } +TEST(HeapSnapshotSlicedString) { + v8::HandleScope scope; + LocalContext env; + CompileRun( + "parent_string = \"123456789.123456789.123456789.123456789.123456789." + "123456789.123456789.123456789.123456789.123456789." + "123456789.123456789.123456789.123456789.123456789." + "123456789.123456789.123456789.123456789.123456789.\";" + "child_string = parent_string.slice(100);"); + const v8::HeapSnapshot* snapshot = + v8::HeapProfiler::TakeSnapshot(v8_str("strings")); + const v8::HeapGraphNode* global = GetGlobalObject(snapshot); + const v8::HeapGraphNode* parent_string = + GetProperty(global, v8::HeapGraphEdge::kShortcut, "parent_string"); + CHECK_NE(NULL, parent_string); + const v8::HeapGraphNode* child_string = + GetProperty(global, v8::HeapGraphEdge::kShortcut, "child_string"); + CHECK_NE(NULL, child_string); + const v8::HeapGraphNode* parent = + GetProperty(child_string, v8::HeapGraphEdge::kInternal, "parent"); + CHECK_EQ(parent_string, parent); +} TEST(HeapSnapshotInternalReferences) { v8::HandleScope scope; @@ -294,7 +316,7 @@ TEST(HeapEntryIdsAndGC) { const v8::HeapSnapshot* snapshot1 = v8::HeapProfiler::TakeSnapshot(v8_str("s1")); - HEAP->CollectAllGarbage(true); // Enforce compaction. + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); const v8::HeapSnapshot* snapshot2 = v8::HeapProfiler::TakeSnapshot(v8_str("s2")); @@ -873,6 +895,20 @@ TEST(DocumentURLWithException) { } +TEST(NoHandleLeaks) { + v8::HandleScope scope; + LocalContext env; + + CompileRun("document = { URL:\"abcdefgh\" };"); + + v8::Handle<v8::String> name(v8_str("leakz")); + int count_before = i::HandleScope::NumberOfHandles(); + v8::HeapProfiler::TakeSnapshot(name); + int count_after = i::HandleScope::NumberOfHandles(); + CHECK_EQ(count_before, count_after); +} + + TEST(NodesIteration) { v8::HandleScope scope; LocalContext env; @@ -1001,3 +1037,31 @@ TEST(GetConstructorName) { CHECK_EQ(0, StringCmp( "Object", i::V8HeapExplorer::GetConstructorName(*js_obj6))); } + + +TEST(FastCaseGetter) { + v8::HandleScope scope; + LocalContext env; + + CompileRun("var obj1 = {};\n" + "obj1.__defineGetter__('propWithGetter', function Y() {\n" + " return 42;\n" + "});\n" + "obj1.__defineSetter__('propWithSetter', function Z(value) {\n" + " return this.value_ = value;\n" + "});\n"); + const v8::HeapSnapshot* snapshot = + v8::HeapProfiler::TakeSnapshot(v8_str("fastCaseGetter")); + + const v8::HeapGraphNode* global = GetGlobalObject(snapshot); + CHECK_NE(NULL, global); + const v8::HeapGraphNode* obj1 = + GetProperty(global, v8::HeapGraphEdge::kShortcut, "obj1"); + CHECK_NE(NULL, obj1); + const v8::HeapGraphNode* getterFunction = + GetProperty(obj1, v8::HeapGraphEdge::kProperty, "get-propWithGetter"); + CHECK_NE(NULL, getterFunction); + const v8::HeapGraphNode* setterFunction = + GetProperty(obj1, v8::HeapGraphEdge::kProperty, "set-propWithSetter"); + CHECK_NE(NULL, setterFunction); +} diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc index 11b88130..2ea359d1 100644 --- a/test/cctest/test-heap.cc +++ b/test/cctest/test-heap.cc @@ -1,4 +1,4 @@ -// Copyright 2006-2008 the V8 project authors. All rights reserved. +// Copyright 2011 the V8 project authors. All rights reserved. #include <stdlib.h> @@ -667,22 +667,23 @@ TEST(JSArray) { Handle<JSObject> object = FACTORY->NewJSObject(function); Handle<JSArray> array = Handle<JSArray>::cast(object); // We just initialized the VM, no heap allocation failure yet. - Object* ok = array->Initialize(0)->ToObjectChecked(); + array->Initialize(0)->ToObjectChecked(); // Set array length to 0. - ok = array->SetElementsLength(Smi::FromInt(0))->ToObjectChecked(); + array->SetElementsLength(Smi::FromInt(0))->ToObjectChecked(); CHECK_EQ(Smi::FromInt(0), array->length()); - CHECK(array->HasFastElements()); // Must be in fast mode. + // Must be in fast mode. + CHECK(array->HasFastTypeElements()); // array[length] = name. - ok = array->SetElement(0, *name, kNonStrictMode, true)->ToObjectChecked(); + array->SetElement(0, *name, kNonStrictMode, true)->ToObjectChecked(); CHECK_EQ(Smi::FromInt(1), array->length()); CHECK_EQ(array->GetElement(0), *name); // Set array length with larger than smi value. Handle<Object> length = FACTORY->NewNumberFromUint(static_cast<uint32_t>(Smi::kMaxValue) + 1); - ok = array->SetElementsLength(*length)->ToObjectChecked(); + array->SetElementsLength(*length)->ToObjectChecked(); uint32_t int_length = 0; CHECK(length->ToArrayIndex(&int_length)); @@ -690,8 +691,7 @@ TEST(JSArray) { CHECK(array->HasDictionaryElements()); // Must be in slow mode. // array[length] = name. - ok = array->SetElement( - int_length, *name, kNonStrictMode, true)->ToObjectChecked(); + array->SetElement(int_length, *name, kNonStrictMode, true)->ToObjectChecked(); uint32_t new_int_length = 0; CHECK(array->length()->ToArrayIndex(&new_int_length)); CHECK_EQ(static_cast<double>(int_length), new_int_length - 1); @@ -718,10 +718,8 @@ TEST(JSObjectCopy) { obj->SetProperty( *second, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked(); - Object* ok = - obj->SetElement(0, *first, kNonStrictMode, true)->ToObjectChecked(); - - ok = obj->SetElement(1, *second, kNonStrictMode, true)->ToObjectChecked(); + obj->SetElement(0, *first, kNonStrictMode, true)->ToObjectChecked(); + obj->SetElement(1, *second, kNonStrictMode, true)->ToObjectChecked(); // Make the clone. Handle<JSObject> clone = Copy(obj); @@ -739,8 +737,8 @@ TEST(JSObjectCopy) { clone->SetProperty( *second, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked(); - ok = clone->SetElement(0, *second, kNonStrictMode, true)->ToObjectChecked(); - ok = clone->SetElement(1, *first, kNonStrictMode, true)->ToObjectChecked(); + clone->SetElement(0, *second, kNonStrictMode, true)->ToObjectChecked(); + clone->SetElement(1, *first, kNonStrictMode, true)->ToObjectChecked(); CHECK_EQ(obj->GetElement(1), clone->GetElement(0)); CHECK_EQ(obj->GetElement(0), clone->GetElement(1)); @@ -822,7 +820,7 @@ TEST(Iteration) { FACTORY->NewStringFromAscii(CStrVector("abcdefghij"), TENURED); // Allocate a large string (for large object space). - int large_size = HEAP->MaxObjectSizeInPagedSpace() + 1; + int large_size = Page::kMaxNonCodeHeapObjectSize + 1; char* str = new char[large_size]; for (int i = 0; i < large_size - 1; ++i) str[i] = 'a'; str[large_size - 1] = '\0'; @@ -838,49 +836,6 @@ TEST(Iteration) { } -TEST(LargeObjectSpaceContains) { - InitializeVM(); - - HEAP->CollectGarbage(NEW_SPACE); - - Address current_top = HEAP->new_space()->top(); - Page* page = Page::FromAddress(current_top); - Address current_page = page->address(); - Address next_page = current_page + Page::kPageSize; - int bytes_to_page = static_cast<int>(next_page - current_top); - if (bytes_to_page <= FixedArray::kHeaderSize) { - // Alas, need to cross another page to be able to - // put desired value. - next_page += Page::kPageSize; - bytes_to_page = static_cast<int>(next_page - current_top); - } - CHECK(bytes_to_page > FixedArray::kHeaderSize); - - intptr_t* flags_ptr = &Page::FromAddress(next_page)->flags_; - Address flags_addr = reinterpret_cast<Address>(flags_ptr); - - int bytes_to_allocate = - static_cast<int>(flags_addr - current_top) + kPointerSize; - - int n_elements = (bytes_to_allocate - FixedArray::kHeaderSize) / - kPointerSize; - CHECK_EQ(bytes_to_allocate, FixedArray::SizeFor(n_elements)); - FixedArray* array = FixedArray::cast( - HEAP->AllocateFixedArray(n_elements)->ToObjectChecked()); - - int index = n_elements - 1; - CHECK_EQ(flags_ptr, - HeapObject::RawField(array, FixedArray::OffsetOfElementAt(index))); - array->set(index, Smi::FromInt(0)); - // This chould have turned next page into LargeObjectPage: - // CHECK(Page::FromAddress(next_page)->IsLargeObjectPage()); - - HeapObject* addr = HeapObject::FromAddress(next_page + 2 * kPointerSize); - CHECK(HEAP->new_space()->Contains(addr)); - CHECK(!HEAP->lo_space()->Contains(addr)); -} - - TEST(EmptyHandleEscapeFrom) { InitializeVM(); @@ -907,8 +862,7 @@ TEST(Regression39128) { InitializeVM(); // Increase the chance of 'bump-the-pointer' allocation in old space. - bool force_compaction = true; - HEAP->CollectAllGarbage(force_compaction); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); v8::HandleScope scope; @@ -975,12 +929,6 @@ TEST(Regression39128) { return; } CHECK(HEAP->old_pointer_space()->Contains(clone->address())); - - // Step 5: verify validity of region dirty marks. - Address clone_addr = clone->address(); - Page* page = Page::FromAddress(clone_addr); - // Check that region covering inobject property 1 is marked dirty. - CHECK(page->IsRegionDirty(clone_addr + (object_size - kPointerSize))); } @@ -1010,17 +958,18 @@ TEST(TestCodeFlushing) { Handle<JSFunction> function(JSFunction::cast(func_value)); CHECK(function->shared()->is_compiled()); - HEAP->CollectAllGarbage(true); - HEAP->CollectAllGarbage(true); + // TODO(1609) Currently incremental marker does not support code flushing. + HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask); + HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask); CHECK(function->shared()->is_compiled()); - HEAP->CollectAllGarbage(true); - HEAP->CollectAllGarbage(true); - HEAP->CollectAllGarbage(true); - HEAP->CollectAllGarbage(true); - HEAP->CollectAllGarbage(true); - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask); + HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask); + HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask); + HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask); + HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask); + HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask); // foo should no longer be in the compilation cache CHECK(!function->shared()->is_compiled() || function->IsOptimized()); @@ -1109,7 +1058,7 @@ TEST(TestInternalWeakLists) { } // Mark compact handles the weak references. - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i])); // Get rid of f3 and f5 in the same way. @@ -1118,21 +1067,21 @@ TEST(TestInternalWeakLists) { HEAP->PerformScavenge(); CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i])); } - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i])); CompileRun("f5=null"); for (int j = 0; j < 10; j++) { HEAP->PerformScavenge(); CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i])); } - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[i])); ctx[i]->Exit(); } // Force compilation cache cleanup. - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); // Dispose the global contexts one by one. for (int i = 0; i < kNumTestContexts; i++) { @@ -1146,7 +1095,7 @@ TEST(TestInternalWeakLists) { } // Mark compact handles the weak references. - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); CHECK_EQ(kNumTestContexts - i - 1, CountGlobalContexts()); } @@ -1161,7 +1110,7 @@ static int CountGlobalContextsWithGC(int n) { Handle<Object> object(HEAP->global_contexts_list()); while (!object->IsUndefined()) { count++; - if (count == n) HEAP->CollectAllGarbage(true); + if (count == n) HEAP->CollectAllGarbage(Heap::kNoGCFlags); object = Handle<Object>(Context::cast(*object)->get(Context::NEXT_CONTEXT_LINK)); } @@ -1180,7 +1129,7 @@ static int CountOptimizedUserFunctionsWithGC(v8::Handle<v8::Context> context, while (object->IsJSFunction() && !Handle<JSFunction>::cast(object)->IsBuiltin()) { count++; - if (count == n) HEAP->CollectAllGarbage(true); + if (count == n) HEAP->CollectAllGarbage(Heap::kNoGCFlags); object = Handle<Object>( Object::cast(JSFunction::cast(*object)->next_function_link())); } @@ -1240,90 +1189,319 @@ TEST(TestInternalWeakListsTraverseWithGC) { TEST(TestSizeOfObjectsVsHeapIteratorPrecision) { InitializeVM(); + HEAP->EnsureHeapIsIterable(); intptr_t size_of_objects_1 = HEAP->SizeOfObjects(); - HeapIterator iterator(HeapIterator::kFilterFreeListNodes); + HeapIterator iterator; intptr_t size_of_objects_2 = 0; for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { size_of_objects_2 += obj->Size(); } - // Delta must be within 1% of the larger result. + // Delta must be within 5% of the larger result. + // TODO(gc): Tighten this up by distinguishing between byte + // arrays that are real and those that merely mark free space + // on the heap. if (size_of_objects_1 > size_of_objects_2) { intptr_t delta = size_of_objects_1 - size_of_objects_2; PrintF("Heap::SizeOfObjects: %" V8_PTR_PREFIX "d, " "Iterator: %" V8_PTR_PREFIX "d, " "delta: %" V8_PTR_PREFIX "d\n", size_of_objects_1, size_of_objects_2, delta); - CHECK_GT(size_of_objects_1 / 100, delta); + CHECK_GT(size_of_objects_1 / 20, delta); } else { intptr_t delta = size_of_objects_2 - size_of_objects_1; PrintF("Heap::SizeOfObjects: %" V8_PTR_PREFIX "d, " "Iterator: %" V8_PTR_PREFIX "d, " "delta: %" V8_PTR_PREFIX "d\n", size_of_objects_1, size_of_objects_2, delta); - CHECK_GT(size_of_objects_2 / 100, delta); + CHECK_GT(size_of_objects_2 / 20, delta); } } -class HeapIteratorTestHelper { - public: - HeapIteratorTestHelper(Object* a, Object* b) - : a_(a), b_(b), a_found_(false), b_found_(false) {} - bool a_found() { return a_found_; } - bool b_found() { return b_found_; } - void IterateHeap(HeapIterator::HeapObjectsFiltering mode) { - HeapIterator iterator(mode); - for (HeapObject* obj = iterator.next(); - obj != NULL; - obj = iterator.next()) { - if (obj == a_) - a_found_ = true; - else if (obj == b_) - b_found_ = true; - } +static void FillUpNewSpace(NewSpace* new_space) { + // Fill up new space to the point that it is completely full. Make sure + // that the scavenger does not undo the filling. + v8::HandleScope scope; + AlwaysAllocateScope always_allocate; + intptr_t available = new_space->EffectiveCapacity() - new_space->Size(); + intptr_t number_of_fillers = (available / FixedArray::SizeFor(1000)) - 10; + for (intptr_t i = 0; i < number_of_fillers; i++) { + CHECK(HEAP->InNewSpace(*FACTORY->NewFixedArray(1000, NOT_TENURED))); } - private: - Object* a_; - Object* b_; - bool a_found_; - bool b_found_; -}; +} + + +TEST(GrowAndShrinkNewSpace) { + InitializeVM(); + NewSpace* new_space = HEAP->new_space(); + + // Explicitly growing should double the space capacity. + intptr_t old_capacity, new_capacity; + old_capacity = new_space->Capacity(); + new_space->Grow(); + new_capacity = new_space->Capacity(); + CHECK(2 * old_capacity == new_capacity); + + old_capacity = new_space->Capacity(); + FillUpNewSpace(new_space); + new_capacity = new_space->Capacity(); + CHECK(old_capacity == new_capacity); + + // Explicitly shrinking should not affect space capacity. + old_capacity = new_space->Capacity(); + new_space->Shrink(); + new_capacity = new_space->Capacity(); + CHECK(old_capacity == new_capacity); + + // Let the scavenger empty the new space. + HEAP->CollectGarbage(NEW_SPACE); + CHECK_LE(new_space->Size(), old_capacity); + + // Explicitly shrinking should halve the space capacity. + old_capacity = new_space->Capacity(); + new_space->Shrink(); + new_capacity = new_space->Capacity(); + CHECK(old_capacity == 2 * new_capacity); + + // Consecutive shrinking should not affect space capacity. + old_capacity = new_space->Capacity(); + new_space->Shrink(); + new_space->Shrink(); + new_space->Shrink(); + new_capacity = new_space->Capacity(); + CHECK(old_capacity == new_capacity); +} -TEST(HeapIteratorFilterUnreachable) { + +TEST(CollectingAllAvailableGarbageShrinksNewSpace) { InitializeVM(); v8::HandleScope scope; - CompileRun("a = {}; b = {};"); - v8::Handle<Object> a(ISOLATE->context()->global()->GetProperty( - *FACTORY->LookupAsciiSymbol("a"))->ToObjectChecked()); - v8::Handle<Object> b(ISOLATE->context()->global()->GetProperty( - *FACTORY->LookupAsciiSymbol("b"))->ToObjectChecked()); - CHECK_NE(*a, *b); + NewSpace* new_space = HEAP->new_space(); + intptr_t old_capacity, new_capacity; + old_capacity = new_space->Capacity(); + new_space->Grow(); + new_capacity = new_space->Capacity(); + CHECK(2 * old_capacity == new_capacity); + FillUpNewSpace(new_space); + HEAP->CollectAllAvailableGarbage(); + new_capacity = new_space->Capacity(); + CHECK(old_capacity == new_capacity); +} + + +static int NumberOfGlobalObjects() { + int count = 0; + HeapIterator iterator; + for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { + if (obj->IsGlobalObject()) count++; + } + return count; +} + + +// Test that we don't embed maps from foreign contexts into +// optimized code. +TEST(LeakGlobalContextViaMap) { + i::FLAG_allow_natives_syntax = true; + v8::HandleScope outer_scope; + v8::Persistent<v8::Context> ctx1 = v8::Context::New(); + v8::Persistent<v8::Context> ctx2 = v8::Context::New(); + ctx1->Enter(); + + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(4, NumberOfGlobalObjects()); + { - HeapIteratorTestHelper helper(*a, *b); - helper.IterateHeap(HeapIterator::kFilterUnreachable); - CHECK(helper.a_found()); - CHECK(helper.b_found()); + v8::HandleScope inner_scope; + CompileRun("var v = {x: 42}"); + v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v")); + ctx2->Enter(); + ctx2->Global()->Set(v8_str("o"), v); + v8::Local<v8::Value> res = CompileRun( + "function f() { return o.x; }" + "for (var i = 0; i < 10; ++i) f();" + "%OptimizeFunctionOnNextCall(f);" + "f();"); + CHECK_EQ(42, res->Int32Value()); + ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); + ctx2->Exit(); + ctx1->Exit(); + ctx1.Dispose(); } - CHECK(ISOLATE->context()->global()->DeleteProperty( - *FACTORY->LookupAsciiSymbol("a"), JSObject::FORCE_DELETION)); - // We ensure that GC will not happen, so our raw pointer stays valid. - AssertNoAllocation no_alloc; - Object* a_saved = *a; - a.Clear(); - // Verify that "a" object still resides in the heap... + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(2, NumberOfGlobalObjects()); + ctx2.Dispose(); + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(0, NumberOfGlobalObjects()); +} + + +// Test that we don't embed functions from foreign contexts into +// optimized code. +TEST(LeakGlobalContextViaFunction) { + i::FLAG_allow_natives_syntax = true; + v8::HandleScope outer_scope; + v8::Persistent<v8::Context> ctx1 = v8::Context::New(); + v8::Persistent<v8::Context> ctx2 = v8::Context::New(); + ctx1->Enter(); + + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(4, NumberOfGlobalObjects()); + { - HeapIteratorTestHelper helper(a_saved, *b); - helper.IterateHeap(HeapIterator::kNoFiltering); - CHECK(helper.a_found()); - CHECK(helper.b_found()); + v8::HandleScope inner_scope; + CompileRun("var v = function() { return 42; }"); + v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v")); + ctx2->Enter(); + ctx2->Global()->Set(v8_str("o"), v); + v8::Local<v8::Value> res = CompileRun( + "function f(x) { return x(); }" + "for (var i = 0; i < 10; ++i) f(o);" + "%OptimizeFunctionOnNextCall(f);" + "f(o);"); + CHECK_EQ(42, res->Int32Value()); + ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); + ctx2->Exit(); + ctx1->Exit(); + ctx1.Dispose(); + } + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(2, NumberOfGlobalObjects()); + ctx2.Dispose(); + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(0, NumberOfGlobalObjects()); +} + + +TEST(LeakGlobalContextViaMapKeyed) { + i::FLAG_allow_natives_syntax = true; + v8::HandleScope outer_scope; + v8::Persistent<v8::Context> ctx1 = v8::Context::New(); + v8::Persistent<v8::Context> ctx2 = v8::Context::New(); + ctx1->Enter(); + + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(4, NumberOfGlobalObjects()); + + { + v8::HandleScope inner_scope; + CompileRun("var v = [42, 43]"); + v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v")); + ctx2->Enter(); + ctx2->Global()->Set(v8_str("o"), v); + v8::Local<v8::Value> res = CompileRun( + "function f() { return o[0]; }" + "for (var i = 0; i < 10; ++i) f();" + "%OptimizeFunctionOnNextCall(f);" + "f();"); + CHECK_EQ(42, res->Int32Value()); + ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); + ctx2->Exit(); + ctx1->Exit(); + ctx1.Dispose(); } - // ...but is now unreachable. + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(2, NumberOfGlobalObjects()); + ctx2.Dispose(); + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(0, NumberOfGlobalObjects()); +} + + +TEST(LeakGlobalContextViaMapProto) { + i::FLAG_allow_natives_syntax = true; + v8::HandleScope outer_scope; + v8::Persistent<v8::Context> ctx1 = v8::Context::New(); + v8::Persistent<v8::Context> ctx2 = v8::Context::New(); + ctx1->Enter(); + + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(4, NumberOfGlobalObjects()); + { - HeapIteratorTestHelper helper(a_saved, *b); - helper.IterateHeap(HeapIterator::kFilterUnreachable); - CHECK(!helper.a_found()); - CHECK(helper.b_found()); + v8::HandleScope inner_scope; + CompileRun("var v = { y: 42}"); + v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v")); + ctx2->Enter(); + ctx2->Global()->Set(v8_str("o"), v); + v8::Local<v8::Value> res = CompileRun( + "function f() {" + " var p = {x: 42};" + " p.__proto__ = o;" + " return p.x;" + "}" + "for (var i = 0; i < 10; ++i) f();" + "%OptimizeFunctionOnNextCall(f);" + "f();"); + CHECK_EQ(42, res->Int32Value()); + ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); + ctx2->Exit(); + ctx1->Exit(); + ctx1.Dispose(); } + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(2, NumberOfGlobalObjects()); + ctx2.Dispose(); + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(0, NumberOfGlobalObjects()); +} + + +TEST(InstanceOfStubWriteBarrier) { + if (!i::FLAG_crankshaft) return; + i::FLAG_allow_natives_syntax = true; +#ifdef DEBUG + i::FLAG_verify_heap = true; +#endif + InitializeVM(); + v8::HandleScope outer_scope; + + { + v8::HandleScope scope; + CompileRun( + "function foo () { }" + "function mkbar () { return new (new Function(\"\")) (); }" + "function f (x) { return (x instanceof foo); }" + "function g () { f(mkbar()); }" + "f(new foo()); f(new foo());" + "%OptimizeFunctionOnNextCall(f);" + "f(new foo()); g();"); + } + + IncrementalMarking* marking = HEAP->incremental_marking(); + marking->Abort(); + marking->Start(); + + Handle<JSFunction> f = + v8::Utils::OpenHandle( + *v8::Handle<v8::Function>::Cast( + v8::Context::GetCurrent()->Global()->Get(v8_str("f")))); + + CHECK(f->IsOptimized()); + + while (!Marking::IsBlack(Marking::MarkBitFrom(f->code())) && + !marking->IsStopped()) { + marking->Step(MB); + } + + CHECK(marking->IsMarking()); + + // Discard any pending GC requests otherwise we will get GC when we enter + // code below. + if (ISOLATE->stack_guard()->IsGCRequest()) { + ISOLATE->stack_guard()->Continue(GC_REQUEST); + } + + { + v8::HandleScope scope; + v8::Handle<v8::Object> global = v8::Context::GetCurrent()->Global(); + v8::Handle<v8::Function> g = + v8::Handle<v8::Function>::Cast(global->Get(v8_str("g"))); + g->Call(global, 0, NULL); + } + + HEAP->incremental_marking()->set_should_hurry(true); + HEAP->CollectGarbage(OLD_POINTER_SPACE); } diff --git a/test/cctest/test-lockers.cc b/test/cctest/test-lockers.cc index 7360da52..5035f876 100644 --- a/test/cctest/test-lockers.cc +++ b/test/cctest/test-lockers.cc @@ -204,7 +204,11 @@ static void StartJoinAndDeleteThreads(const i::List<JoinableThread*>& threads) { // Run many threads all locking on the same isolate TEST(IsolateLockingStress) { +#ifdef V8_TARGET_ARCH_MIPS + const int kNThreads = 50; +#else const int kNThreads = 100; +#endif i::List<JoinableThread*> threads(kNThreads); v8::Isolate* isolate = v8::Isolate::New(); for (int i = 0; i < kNThreads; i++) { @@ -237,7 +241,7 @@ class IsolateNonlockingThread : public JoinableThread { // Run many threads each accessing its own isolate without locking TEST(MultithreadedParallelIsolates) { -#ifdef V8_TARGET_ARCH_ARM +#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS) const int kNThreads = 10; #else const int kNThreads = 50; @@ -275,7 +279,11 @@ class IsolateNestedLockingThread : public JoinableThread { // Run many threads with nested locks TEST(IsolateNestedLocking) { +#ifdef V8_TARGET_ARCH_MIPS + const int kNThreads = 50; +#else const int kNThreads = 100; +#endif v8::Isolate* isolate = v8::Isolate::New(); i::List<JoinableThread*> threads(kNThreads); for (int i = 0; i < kNThreads; i++) { @@ -311,7 +319,7 @@ class SeparateIsolatesLocksNonexclusiveThread : public JoinableThread { // Run parallel threads that lock and access different isolates in parallel TEST(SeparateIsolatesLocksNonexclusive) { -#ifdef V8_TARGET_ARCH_ARM +#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS) const int kNThreads = 50; #else const int kNThreads = 100; @@ -385,7 +393,7 @@ class LockerUnlockerThread : public JoinableThread { // Use unlocker inside of a Locker, multiple threads. TEST(LockerUnlocker) { -#ifdef V8_TARGET_ARCH_ARM +#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS) const int kNThreads = 50; #else const int kNThreads = 100; @@ -438,7 +446,7 @@ class LockTwiceAndUnlockThread : public JoinableThread { // Use Unlocker inside two Lockers. TEST(LockTwiceAndUnlock) { -#ifdef V8_TARGET_ARCH_ARM +#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS) const int kNThreads = 50; #else const int kNThreads = 100; @@ -559,7 +567,11 @@ class LockUnlockLockThread : public JoinableThread { // Locker inside an Unlocker inside a Locker. TEST(LockUnlockLockMultithreaded) { +#ifdef V8_TARGET_ARCH_MIPS + const int kNThreads = 50; +#else const int kNThreads = 100; +#endif v8::Isolate* isolate = v8::Isolate::New(); Persistent<v8::Context> context; { @@ -606,7 +618,11 @@ class LockUnlockLockDefaultIsolateThread : public JoinableThread { // Locker inside an Unlocker inside a Locker for default isolate. TEST(LockUnlockLockDefaultIsolateMultithreaded) { +#ifdef V8_TARGET_ARCH_MIPS + const int kNThreads = 50; +#else const int kNThreads = 100; +#endif Persistent<v8::Context> context; { v8::Locker locker_; @@ -639,3 +655,68 @@ TEST(Regress1433) { isolate->Dispose(); } } + + +static const char* kSimpleExtensionSource = + "(function Foo() {" + " return 4;" + "})() "; + +class IsolateGenesisThread : public JoinableThread { + public: + IsolateGenesisThread(int count, const char* extension_names[]) + : JoinableThread("IsolateGenesisThread"), + count_(count), + extension_names_(extension_names) + {} + + virtual void Run() { + v8::Isolate* isolate = v8::Isolate::New(); + { + v8::Isolate::Scope isolate_scope(isolate); + CHECK(!i::Isolate::Current()->has_installed_extensions()); + v8::ExtensionConfiguration extensions(count_, extension_names_); + v8::Persistent<v8::Context> context = v8::Context::New(&extensions); + CHECK(i::Isolate::Current()->has_installed_extensions()); + context.Dispose(); + } + isolate->Dispose(); + } + private: + int count_; + const char** extension_names_; +}; + +// Test installing extensions in separate isolates concurrently. +// http://code.google.com/p/v8/issues/detail?id=1821 +TEST(ExtensionsRegistration) { +#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS) + const int kNThreads = 10; +#else + const int kNThreads = 40; +#endif + v8::RegisterExtension(new v8::Extension("test0", + kSimpleExtensionSource)); + v8::RegisterExtension(new v8::Extension("test1", + kSimpleExtensionSource)); + v8::RegisterExtension(new v8::Extension("test2", + kSimpleExtensionSource)); + v8::RegisterExtension(new v8::Extension("test3", + kSimpleExtensionSource)); + v8::RegisterExtension(new v8::Extension("test4", + kSimpleExtensionSource)); + v8::RegisterExtension(new v8::Extension("test5", + kSimpleExtensionSource)); + v8::RegisterExtension(new v8::Extension("test6", + kSimpleExtensionSource)); + v8::RegisterExtension(new v8::Extension("test7", + kSimpleExtensionSource)); + const char* extension_names[] = { "test0", "test1", + "test2", "test3", "test4", + "test5", "test6", "test7" }; + i::List<JoinableThread*> threads(kNThreads); + for (int i = 0; i < kNThreads; i++) { + threads.Add(new IsolateGenesisThread(8, extension_names)); + } + StartJoinAndDeleteThreads(threads); +} diff --git a/test/cctest/test-log.cc b/test/cctest/test-log.cc index 72e663c4..6f2324db 100644 --- a/test/cctest/test-log.cc +++ b/test/cctest/test-log.cc @@ -494,7 +494,7 @@ TEST(EquivalenceOfLoggingAndTraversal) { " (function a(j) { return function b() { return j; } })(100);\n" "})(this);"); v8::V8::PauseProfiler(); - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask); LOGGER->StringEvent("test-logging-done", ""); // Iterate heap to find compiled functions, will write to log. diff --git a/test/cctest/test-mark-compact.cc b/test/cctest/test-mark-compact.cc index dcb51a0b..cd3c4903 100644 --- a/test/cctest/test-mark-compact.cc +++ b/test/cctest/test-mark-compact.cc @@ -44,21 +44,21 @@ static void InitializeVM() { } -TEST(MarkingStack) { +TEST(MarkingDeque) { int mem_size = 20 * kPointerSize; byte* mem = NewArray<byte>(20*kPointerSize); Address low = reinterpret_cast<Address>(mem); Address high = low + mem_size; - MarkingStack s; + MarkingDeque s; s.Initialize(low, high); Address address = NULL; - while (!s.is_full()) { - s.Push(HeapObject::FromAddress(address)); + while (!s.IsFull()) { + s.PushBlack(HeapObject::FromAddress(address)); address += kPointerSize; } - while (!s.is_empty()) { + while (!s.IsEmpty()) { Address value = s.Pop()->address(); address -= kPointerSize; CHECK_EQ(address, value); @@ -78,7 +78,7 @@ TEST(Promotion) { // from new space. FLAG_gc_global = true; FLAG_always_compact = true; - HEAP->ConfigureHeap(2*256*KB, 4*MB, 4*MB); + HEAP->ConfigureHeap(2*256*KB, 8*MB, 8*MB); InitializeVM(); @@ -86,7 +86,7 @@ TEST(Promotion) { // Allocate a fixed array in the new space. int array_size = - (HEAP->MaxObjectSizeInPagedSpace() - FixedArray::kHeaderSize) / + (Page::kMaxNonCodeHeapObjectSize - FixedArray::kHeaderSize) / (kPointerSize * 4); Object* obj = HEAP->AllocateFixedArray(array_size)->ToObjectChecked(); @@ -104,7 +104,7 @@ TEST(Promotion) { TEST(NoPromotion) { - HEAP->ConfigureHeap(2*256*KB, 4*MB, 4*MB); + HEAP->ConfigureHeap(2*256*KB, 8*MB, 8*MB); // Test the situation that some objects in new space are promoted to // the old space @@ -116,9 +116,12 @@ TEST(NoPromotion) { HEAP->CollectGarbage(OLD_POINTER_SPACE); // Allocate a big Fixed array in the new space. - int size = (HEAP->MaxObjectSizeInPagedSpace() - FixedArray::kHeaderSize) / - kPointerSize; - Object* obj = HEAP->AllocateFixedArray(size)->ToObjectChecked(); + int max_size = + Min(Page::kMaxNonCodeHeapObjectSize, HEAP->MaxObjectSizeInNewSpace()); + + int length = (max_size - FixedArray::kHeaderSize) / (2*kPointerSize); + Object* obj = i::Isolate::Current()->heap()->AllocateFixedArray(length)-> + ToObjectChecked(); Handle<FixedArray> array(FixedArray::cast(obj)); @@ -228,6 +231,8 @@ TEST(MarkCompactCollector) { } +// TODO(1600): compaction of map space is temporary removed from GC. +#if 0 static Handle<Map> CreateMap() { return FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); } @@ -252,11 +257,11 @@ TEST(MapCompact) { // be able to trigger map compaction. // To give an additional chance to fail, try to force compaction which // should be impossible right now. - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(Heap::kForceCompactionMask); // And now map pointers should be encodable again. CHECK(HEAP->map_space()->MapPointersEncodable()); } - +#endif static int gc_starts = 0; static int gc_ends = 0; diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc index d98b6753..6f394b67 100755 --- a/test/cctest/test-parsing.cc +++ b/test/cctest/test-parsing.cc @@ -32,6 +32,7 @@ #include "v8.h" #include "cctest.h" +#include "compiler.h" #include "execution.h" #include "isolate.h" #include "parser.h" @@ -63,9 +64,9 @@ TEST(ScanKeywords) { CHECK(static_cast<int>(sizeof(buffer)) >= length); { i::Utf8ToUC16CharacterStream stream(keyword, length); - i::JavaScriptScanner scanner(&unicode_cache); + i::Scanner scanner(&unicode_cache); // The scanner should parse 'let' as Token::LET for this test. - scanner.SetHarmonyBlockScoping(true); + scanner.SetHarmonyScoping(true); scanner.Initialize(&stream); CHECK_EQ(key_token.token, scanner.Next()); CHECK_EQ(i::Token::EOS, scanner.Next()); @@ -73,7 +74,7 @@ TEST(ScanKeywords) { // Removing characters will make keyword matching fail. { i::Utf8ToUC16CharacterStream stream(keyword, length - 1); - i::JavaScriptScanner scanner(&unicode_cache); + i::Scanner scanner(&unicode_cache); scanner.Initialize(&stream); CHECK_EQ(i::Token::IDENTIFIER, scanner.Next()); CHECK_EQ(i::Token::EOS, scanner.Next()); @@ -84,7 +85,7 @@ TEST(ScanKeywords) { memmove(buffer, keyword, length); buffer[length] = chars_to_append[j]; i::Utf8ToUC16CharacterStream stream(buffer, length + 1); - i::JavaScriptScanner scanner(&unicode_cache); + i::Scanner scanner(&unicode_cache); scanner.Initialize(&stream); CHECK_EQ(i::Token::IDENTIFIER, scanner.Next()); CHECK_EQ(i::Token::EOS, scanner.Next()); @@ -94,7 +95,7 @@ TEST(ScanKeywords) { memmove(buffer, keyword, length); buffer[length - 1] = '_'; i::Utf8ToUC16CharacterStream stream(buffer, length); - i::JavaScriptScanner scanner(&unicode_cache); + i::Scanner scanner(&unicode_cache); scanner.Initialize(&stream); CHECK_EQ(i::Token::IDENTIFIER, scanner.Next()); CHECK_EQ(i::Token::EOS, scanner.Next()); @@ -229,7 +230,7 @@ TEST(Preparsing) { CHECK_EQ(11, error_location.end_pos); // Should not crash. const char* message = pre_impl->BuildMessage(); - i::Vector<const char*> args = pre_impl->BuildArgs(); + i::Vector<const char*> args(pre_impl->BuildArgs()); CHECK_GT(strlen(message), 0); } @@ -257,13 +258,14 @@ TEST(StandAlonePreParser) { reinterpret_cast<const i::byte*>(program), static_cast<unsigned>(strlen(program))); i::CompleteParserRecorder log; - i::JavaScriptScanner scanner(i::Isolate::Current()->unicode_cache()); + i::Scanner scanner(i::Isolate::Current()->unicode_cache()); scanner.Initialize(&stream); + int flags = i::kAllowLazy | i::kAllowNativesSyntax; v8::preparser::PreParser::PreParseResult result = v8::preparser::PreParser::PreParseProgram(&scanner, &log, - true, + flags, stack_limit); CHECK_EQ(v8::preparser::PreParser::kPreParseSuccess, result); i::ScriptDataImpl data(log.ExtractData()); @@ -272,6 +274,43 @@ TEST(StandAlonePreParser) { } +TEST(StandAlonePreParserNoNatives) { + v8::V8::Initialize(); + + int marker; + i::Isolate::Current()->stack_guard()->SetStackLimit( + reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); + + const char* programs[] = { + "%ArgleBargle(glop);", + "var x = %_IsSmi(42);", + NULL + }; + + uintptr_t stack_limit = i::Isolate::Current()->stack_guard()->real_climit(); + for (int i = 0; programs[i]; i++) { + const char* program = programs[i]; + i::Utf8ToUC16CharacterStream stream( + reinterpret_cast<const i::byte*>(program), + static_cast<unsigned>(strlen(program))); + i::CompleteParserRecorder log; + i::Scanner scanner(i::Isolate::Current()->unicode_cache()); + scanner.Initialize(&stream); + + // Flags don't allow natives syntax. + v8::preparser::PreParser::PreParseResult result = + v8::preparser::PreParser::PreParseProgram(&scanner, + &log, + i::kAllowLazy, + stack_limit); + CHECK_EQ(v8::preparser::PreParser::kPreParseSuccess, result); + i::ScriptDataImpl data(log.ExtractData()); + // Data contains syntax error. + CHECK(data.has_error()); + } +} + + TEST(RegressChromium62639) { v8::V8::Initialize(); @@ -310,10 +349,10 @@ TEST(Regress928) { "try { } catch (e) { var foo = function () { /* first */ } }" "var bar = function () { /* second */ }"; - i::Utf8ToUC16CharacterStream stream(reinterpret_cast<const i::byte*>(program), - static_cast<unsigned>(strlen(program))); - i::ScriptDataImpl* data = - i::ParserApi::PartialPreParse(&stream, NULL, false); + v8::HandleScope handles; + i::Handle<i::String> source( + FACTORY->NewStringFromAscii(i::CStrVector(program))); + i::ScriptDataImpl* data = i::ParserApi::PartialPreParse(source, NULL, false); CHECK(!data->HasError()); data->Initialize(); @@ -356,7 +395,7 @@ TEST(PreParseOverflow) { reinterpret_cast<const i::byte*>(*program), static_cast<unsigned>(kProgramSize)); i::CompleteParserRecorder log; - i::JavaScriptScanner scanner(i::Isolate::Current()->unicode_cache()); + i::Scanner scanner(i::Isolate::Current()->unicode_cache()); scanner.Initialize(&stream); @@ -574,7 +613,7 @@ void TestStreamScanner(i::UC16CharacterStream* stream, i::Token::Value* expected_tokens, int skip_pos = 0, // Zero means not skipping. int skip_to = 0) { - i::JavaScriptScanner scanner(i::Isolate::Current()->unicode_cache()); + i::Scanner scanner(i::Isolate::Current()->unicode_cache()); scanner.Initialize(stream); int i = 0; @@ -655,7 +694,7 @@ void TestScanRegExp(const char* re_source, const char* expected) { i::Utf8ToUC16CharacterStream stream( reinterpret_cast<const i::byte*>(re_source), static_cast<unsigned>(strlen(re_source))); - i::JavaScriptScanner scanner(i::Isolate::Current()->unicode_cache()); + i::Scanner scanner(i::Isolate::Current()->unicode_cache()); scanner.Initialize(&stream); i::Token::Value start = scanner.peek(); @@ -708,25 +747,170 @@ TEST(RegExpScanning) { } -void TestParserSync(i::Handle<i::String> source, bool allow_lazy) { +TEST(ScopePositions) { + // Test the parser for correctly setting the start and end positions + // of a scope. We check the scope positions of exactly one scope + // nested in the global scope of a program. 'inner source' is the + // source code that determines the part of the source belonging + // to the nested scope. 'outer_prefix' and 'outer_suffix' are + // parts of the source that belong to the global scope. + struct SourceData { + const char* outer_prefix; + const char* inner_source; + const char* outer_suffix; + i::ScopeType scope_type; + i::LanguageMode language_mode; + }; + + const SourceData source_data[] = { + { " with ({}) ", "{ block; }", " more;", i::WITH_SCOPE, i::CLASSIC_MODE }, + { " with ({}) ", "{ block; }", "; more;", i::WITH_SCOPE, i::CLASSIC_MODE }, + { " with ({}) ", "{\n" + " block;\n" + " }", "\n" + " more;", i::WITH_SCOPE, i::CLASSIC_MODE }, + { " with ({}) ", "statement;", " more;", i::WITH_SCOPE, i::CLASSIC_MODE }, + { " with ({}) ", "statement", "\n" + " more;", i::WITH_SCOPE, i::CLASSIC_MODE }, + { " with ({})\n" + " ", "statement;", "\n" + " more;", i::WITH_SCOPE, i::CLASSIC_MODE }, + { " try {} catch ", "(e) { block; }", " more;", + i::CATCH_SCOPE, i::CLASSIC_MODE }, + { " try {} catch ", "(e) { block; }", "; more;", + i::CATCH_SCOPE, i::CLASSIC_MODE }, + { " try {} catch ", "(e) {\n" + " block;\n" + " }", "\n" + " more;", i::CATCH_SCOPE, i::CLASSIC_MODE }, + { " try {} catch ", "(e) { block; }", " finally { block; } more;", + i::CATCH_SCOPE, i::CLASSIC_MODE }, + { " start;\n" + " ", "{ let block; }", " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { " start;\n" + " ", "{ let block; }", "; more;", i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { " start;\n" + " ", "{\n" + " let block;\n" + " }", "\n" + " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { " start;\n" + " function fun", "(a,b) { infunction; }", " more;", + i::FUNCTION_SCOPE, i::CLASSIC_MODE }, + { " start;\n" + " function fun", "(a,b) {\n" + " infunction;\n" + " }", "\n" + " more;", i::FUNCTION_SCOPE, i::CLASSIC_MODE }, + { " (function fun", "(a,b) { infunction; }", ")();", + i::FUNCTION_SCOPE, i::CLASSIC_MODE }, + { " for ", "(let x = 1 ; x < 10; ++ x) { block; }", " more;", + i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { " for ", "(let x = 1 ; x < 10; ++ x) { block; }", "; more;", + i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { " for ", "(let x = 1 ; x < 10; ++ x) {\n" + " block;\n" + " }", "\n" + " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { " for ", "(let x = 1 ; x < 10; ++ x) statement;", " more;", + i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { " for ", "(let x = 1 ; x < 10; ++ x) statement", "\n" + " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { " for ", "(let x = 1 ; x < 10; ++ x)\n" + " statement;", "\n" + " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { " for ", "(let x in {}) { block; }", " more;", + i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { " for ", "(let x in {}) { block; }", "; more;", + i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { " for ", "(let x in {}) {\n" + " block;\n" + " }", "\n" + " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { " for ", "(let x in {}) statement;", " more;", + i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { " for ", "(let x in {}) statement", "\n" + " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { " for ", "(let x in {})\n" + " statement;", "\n" + " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { NULL, NULL, NULL, i::EVAL_SCOPE, i::CLASSIC_MODE } + }; + + v8::HandleScope handles; + v8::Persistent<v8::Context> context = v8::Context::New(); + v8::Context::Scope context_scope(context); + + int marker; + i::Isolate::Current()->stack_guard()->SetStackLimit( + reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); + i::FLAG_harmony_scoping = true; + + for (int i = 0; source_data[i].outer_prefix; i++) { + int kPrefixLen = i::StrLength(source_data[i].outer_prefix); + int kInnerLen = i::StrLength(source_data[i].inner_source); + int kSuffixLen = i::StrLength(source_data[i].outer_suffix); + int kProgramSize = kPrefixLen + kInnerLen + kSuffixLen; + i::Vector<char> program = i::Vector<char>::New(kProgramSize + 1); + int length = i::OS::SNPrintF(program, "%s%s%s", + source_data[i].outer_prefix, + source_data[i].inner_source, + source_data[i].outer_suffix); + CHECK(length == kProgramSize); + + // Parse program source. + i::Handle<i::String> source( + FACTORY->NewStringFromAscii(i::CStrVector(program.start()))); + i::Handle<i::Script> script = FACTORY->NewScript(source); + i::Parser parser(script, i::kAllowLazy | i::EXTENDED_MODE, NULL, NULL); + i::CompilationInfo info(script); + info.MarkAsGlobal(); + info.SetLanguageMode(source_data[i].language_mode); + i::FunctionLiteral* function = parser.ParseProgram(&info); + CHECK(function != NULL); + + // Check scope types and positions. + i::Scope* scope = function->scope(); + CHECK(scope->is_global_scope()); + CHECK_EQ(scope->start_position(), 0); + CHECK_EQ(scope->end_position(), kProgramSize); + CHECK_EQ(scope->inner_scopes()->length(), 1); + + i::Scope* inner_scope = scope->inner_scopes()->at(0); + CHECK_EQ(inner_scope->type(), source_data[i].scope_type); + CHECK_EQ(inner_scope->start_position(), kPrefixLen); + // The end position of a token is one position after the last + // character belonging to that token. + CHECK_EQ(inner_scope->end_position(), kPrefixLen + kInnerLen); + } +} + + +void TestParserSync(i::Handle<i::String> source, int flags) { uintptr_t stack_limit = i::Isolate::Current()->stack_guard()->real_climit(); + bool harmony_scoping = ((i::kLanguageModeMask & flags) == i::EXTENDED_MODE); // Preparse the data. i::CompleteParserRecorder log; - i::JavaScriptScanner scanner(i::Isolate::Current()->unicode_cache()); + i::Scanner scanner(i::Isolate::Current()->unicode_cache()); i::GenericStringUC16CharacterStream stream(source, 0, source->length()); + scanner.SetHarmonyScoping(harmony_scoping); scanner.Initialize(&stream); v8::preparser::PreParser::PreParseResult result = v8::preparser::PreParser::PreParseProgram( - &scanner, &log, allow_lazy, stack_limit); + &scanner, &log, flags, stack_limit); CHECK_EQ(v8::preparser::PreParser::kPreParseSuccess, result); i::ScriptDataImpl data(log.ExtractData()); // Parse the data i::Handle<i::Script> script = FACTORY->NewScript(source); - i::Parser parser(script, false, NULL, NULL); - i::FunctionLiteral* function = - parser.ParseProgram(source, true, i::kNonStrictMode); + bool save_harmony_scoping = i::FLAG_harmony_scoping; + i::FLAG_harmony_scoping = harmony_scoping; + i::Parser parser(script, flags, NULL, NULL); + i::CompilationInfo info(script); + info.MarkAsGlobal(); + i::FunctionLiteral* function = parser.ParseProgram(&info); + i::FLAG_harmony_scoping = save_harmony_scoping; i::String* type_string = NULL; if (function == NULL) { @@ -779,6 +963,23 @@ void TestParserSync(i::Handle<i::String> source, bool allow_lazy) { } +void TestParserSyncWithFlags(i::Handle<i::String> source) { + static const int kFlagsCount = 6; + const int flags[kFlagsCount] = { + i::kNoParsingFlags | i::CLASSIC_MODE, + i::kNoParsingFlags | i::STRICT_MODE, + i::kNoParsingFlags | i::EXTENDED_MODE, + i::kAllowLazy | i::CLASSIC_MODE, + i::kAllowLazy | i::STRICT_MODE, + i::kAllowLazy | i::EXTENDED_MODE + }; + + for (int k = 0; k < kFlagsCount; ++k) { + TestParserSync(source, flags[k]); + } +} + + TEST(ParserSync) { const char* context_data[][2] = { { "", "" }, @@ -876,8 +1077,7 @@ TEST(ParserSync) { CHECK(length == kProgramSize); i::Handle<i::String> source = FACTORY->NewStringFromAscii(i::CStrVector(program.start())); - TestParserSync(source, true); - TestParserSync(source, false); + TestParserSyncWithFlags(source); } } } diff --git a/test/cctest/test-profile-generator.cc b/test/cctest/test-profile-generator.cc index 76fd244e..def829c2 100644 --- a/test/cctest/test-profile-generator.cc +++ b/test/cctest/test-profile-generator.cc @@ -52,7 +52,7 @@ TEST(TokenEnumerator) { CHECK_EQ(0, te.GetTokenId(*v8::Utils::OpenHandle(*token1))); } CHECK(!i::TokenEnumeratorTester::token_removed(&te)->at(2)); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK(i::TokenEnumeratorTester::token_removed(&te)->at(2)); CHECK_EQ(1, te.GetTokenId(*v8::Utils::OpenHandle(*token2))); CHECK_EQ(0, te.GetTokenId(*v8::Utils::OpenHandle(*token1))); diff --git a/test/cctest/test-regexp.cc b/test/cctest/test-regexp.cc index 89a91127..b7784788 100644 --- a/test/cctest/test-regexp.cc +++ b/test/cctest/test-regexp.cc @@ -530,7 +530,7 @@ class TestConfig { typedef int Key; typedef int Value; static const int kNoKey; - static const int kNoValue; + static int NoValue() { return 0; } static inline int Compare(int a, int b) { if (a < b) return -1; @@ -543,7 +543,6 @@ class TestConfig { const int TestConfig::kNoKey = 0; -const int TestConfig::kNoValue = 0; static unsigned PseudoRandom(int i, int j) { diff --git a/test/cctest/test-reloc-info.cc b/test/cctest/test-reloc-info.cc index 5bdc4c3e..e638201d 100644 --- a/test/cctest/test-reloc-info.cc +++ b/test/cctest/test-reloc-info.cc @@ -34,7 +34,7 @@ namespace internal { static void WriteRinfo(RelocInfoWriter* writer, byte* pc, RelocInfo::Mode mode, intptr_t data) { - RelocInfo rinfo(pc, mode, data); + RelocInfo rinfo(pc, mode, data, NULL); writer->Write(&rinfo); } diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc index 8e85444e..e426e7bd 100644 --- a/test/cctest/test-serialize.cc +++ b/test/cctest/test-serialize.cc @@ -114,10 +114,6 @@ TEST(ExternalReferenceEncoder) { ExternalReference(isolate->counters()->keyed_load_function_prototype()); CHECK_EQ(make_code(STATS_COUNTER, Counters::k_keyed_load_function_prototype), encoder.Encode(keyed_load_function_prototype.address())); - ExternalReference the_hole_value_location = - ExternalReference::the_hole_value_location(isolate); - CHECK_EQ(make_code(UNCLASSIFIED, 2), - encoder.Encode(the_hole_value_location.address())); ExternalReference stack_limit_address = ExternalReference::address_of_stack_limit(isolate); CHECK_EQ(make_code(UNCLASSIFIED, 4), @@ -127,14 +123,15 @@ TEST(ExternalReferenceEncoder) { CHECK_EQ(make_code(UNCLASSIFIED, 5), encoder.Encode(real_stack_limit_address.address())); #ifdef ENABLE_DEBUGGER_SUPPORT - CHECK_EQ(make_code(UNCLASSIFIED, 15), + CHECK_EQ(make_code(UNCLASSIFIED, 16), encoder.Encode(ExternalReference::debug_break(isolate).address())); #endif // ENABLE_DEBUGGER_SUPPORT CHECK_EQ(make_code(UNCLASSIFIED, 10), encoder.Encode( ExternalReference::new_space_start(isolate).address())); CHECK_EQ(make_code(UNCLASSIFIED, 3), - encoder.Encode(ExternalReference::roots_address(isolate).address())); + encoder.Encode( + ExternalReference::roots_array_start(isolate).address())); } @@ -157,15 +154,13 @@ TEST(ExternalReferenceDecoder) { decoder.Decode( make_code(STATS_COUNTER, Counters::k_keyed_load_function_prototype))); - CHECK_EQ(ExternalReference::the_hole_value_location(isolate).address(), - decoder.Decode(make_code(UNCLASSIFIED, 2))); CHECK_EQ(ExternalReference::address_of_stack_limit(isolate).address(), decoder.Decode(make_code(UNCLASSIFIED, 4))); CHECK_EQ(ExternalReference::address_of_real_stack_limit(isolate).address(), decoder.Decode(make_code(UNCLASSIFIED, 5))); #ifdef ENABLE_DEBUGGER_SUPPORT CHECK_EQ(ExternalReference::debug_break(isolate).address(), - decoder.Decode(make_code(UNCLASSIFIED, 15))); + decoder.Decode(make_code(UNCLASSIFIED, 16))); #endif // ENABLE_DEBUGGER_SUPPORT CHECK_EQ(ExternalReference::new_space_start(isolate).address(), decoder.Decode(make_code(UNCLASSIFIED, 10))); @@ -365,8 +360,8 @@ TEST(PartialSerialization) { Isolate::Current()->bootstrapper()->NativesSourceLookup(i); } } - HEAP->CollectAllGarbage(true); - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); Object* raw_foo; { @@ -490,7 +485,7 @@ TEST(ContextSerialization) { } // If we don't do this then we end up with a stray root pointing at the // context even after we have disposed of env. - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); int file_name_length = StrLength(FLAG_testing_serialization_file) + 10; Vector<char> startup_name = Vector<char>::New(file_name_length + 1); @@ -563,16 +558,20 @@ DEPENDENT_TEST(ContextDeserialization, ContextSerialization) { TEST(LinearAllocation) { v8::V8::Initialize(); int new_space_max = 512 * KB; + int paged_space_max = Page::kMaxNonCodeHeapObjectSize; + int code_space_max = HEAP->code_space()->AreaSize(); for (int size = 1000; size < 5 * MB; size += size >> 1) { + size &= ~8; // Round. int new_space_size = (size < new_space_max) ? size : new_space_max; + int paged_space_size = (size < paged_space_max) ? size : paged_space_max; HEAP->ReserveSpace( new_space_size, - size, // Old pointer space. - size, // Old data space. - size, // Code space. - size, // Map space. - size, // Cell space. + paged_space_size, // Old pointer space. + paged_space_size, // Old data space. + HEAP->code_space()->RoundSizeDownToObjectAlignment(code_space_max), + HEAP->map_space()->RoundSizeDownToObjectAlignment(paged_space_size), + HEAP->cell_space()->RoundSizeDownToObjectAlignment(paged_space_size), size); // Large object space. LinearAllocationScope linear_allocation_scope; const int kSmallFixedArrayLength = 4; @@ -599,14 +598,14 @@ TEST(LinearAllocation) { Object* pointer_last = NULL; for (int i = 0; - i + kSmallFixedArraySize <= size; + i + kSmallFixedArraySize <= paged_space_size; i += kSmallFixedArraySize) { Object* obj = HEAP->AllocateFixedArray(kSmallFixedArrayLength, TENURED)->ToObjectChecked(); int old_page_fullness = i % Page::kPageSize; int page_fullness = (i + kSmallFixedArraySize) % Page::kPageSize; if (page_fullness < old_page_fullness || - page_fullness > Page::kObjectAreaSize) { + page_fullness > HEAP->old_pointer_space()->AreaSize()) { i = RoundUp(i, Page::kPageSize); pointer_last = NULL; } @@ -618,13 +617,15 @@ TEST(LinearAllocation) { } Object* data_last = NULL; - for (int i = 0; i + kSmallStringSize <= size; i += kSmallStringSize) { + for (int i = 0; + i + kSmallStringSize <= paged_space_size; + i += kSmallStringSize) { Object* obj = HEAP->AllocateRawAsciiString(kSmallStringLength, TENURED)->ToObjectChecked(); int old_page_fullness = i % Page::kPageSize; int page_fullness = (i + kSmallStringSize) % Page::kPageSize; if (page_fullness < old_page_fullness || - page_fullness > Page::kObjectAreaSize) { + page_fullness > HEAP->old_data_space()->AreaSize()) { i = RoundUp(i, Page::kPageSize); data_last = NULL; } @@ -636,13 +637,13 @@ TEST(LinearAllocation) { } Object* map_last = NULL; - for (int i = 0; i + kMapSize <= size; i += kMapSize) { + for (int i = 0; i + kMapSize <= paged_space_size; i += kMapSize) { Object* obj = HEAP->AllocateMap(JS_OBJECT_TYPE, 42 * kPointerSize)->ToObjectChecked(); int old_page_fullness = i % Page::kPageSize; int page_fullness = (i + kMapSize) % Page::kPageSize; if (page_fullness < old_page_fullness || - page_fullness > Page::kObjectAreaSize) { + page_fullness > HEAP->map_space()->AreaSize()) { i = RoundUp(i, Page::kPageSize); map_last = NULL; } @@ -653,7 +654,7 @@ TEST(LinearAllocation) { map_last = obj; } - if (size > Page::kObjectAreaSize) { + if (size > Page::kMaxNonCodeHeapObjectSize) { // Support for reserving space in large object space is not there yet, // but using an always-allocate scope is fine for now. AlwaysAllocateScope always; diff --git a/test/cctest/test-spaces.cc b/test/cctest/test-spaces.cc index 0f22ce1a..27f64b48 100644 --- a/test/cctest/test-spaces.cc +++ b/test/cctest/test-spaces.cc @@ -1,4 +1,4 @@ -// Copyright 2006-2008 the V8 project authors. All rights reserved. +// Copyright 2011 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: @@ -32,7 +32,9 @@ using namespace v8::internal; +#if 0 static void VerifyRegionMarking(Address page_start) { +#ifdef ENABLE_CARDMARKING_WRITE_BARRIER Page* p = Page::FromAddress(page_start); p->SetRegionMarks(Page::kAllRegionsCleanMarks); @@ -54,9 +56,13 @@ static void VerifyRegionMarking(Address page_start) { addr += kPointerSize) { CHECK(Page::FromAddress(addr)->IsRegionDirty(addr)); } +#endif } +#endif +// TODO(gc) you can no longer allocate pages like this. Details are hidden. +#if 0 TEST(Page) { byte* mem = NewArray<byte>(2*Page::kPageSize); CHECK(mem != NULL); @@ -89,6 +95,7 @@ TEST(Page) { DeleteArray(mem); } +#endif namespace v8 { @@ -122,62 +129,46 @@ TEST(MemoryAllocator) { Isolate* isolate = Isolate::Current(); isolate->InitializeLoggingAndCounters(); Heap* heap = isolate->heap(); - CHECK(heap->ConfigureHeapDefault()); + CHECK(isolate->heap()->ConfigureHeapDefault()); + MemoryAllocator* memory_allocator = new MemoryAllocator(isolate); CHECK(memory_allocator->Setup(heap->MaxReserved(), heap->MaxExecutableSize())); - TestMemoryAllocatorScope test_scope(isolate, memory_allocator); + int total_pages = 0; OldSpace faked_space(heap, heap->MaxReserved(), OLD_POINTER_SPACE, NOT_EXECUTABLE); - int total_pages = 0; - int requested = MemoryAllocator::kPagesPerChunk; - int allocated; - // If we request n pages, we should get n or n - 1. - Page* first_page = memory_allocator->AllocatePages( - requested, &allocated, &faked_space); + Page* first_page = + memory_allocator->AllocatePage(&faked_space, NOT_EXECUTABLE); + + first_page->InsertAfter(faked_space.anchor()->prev_page()); CHECK(first_page->is_valid()); - CHECK(allocated == requested || allocated == requested - 1); - total_pages += allocated; + CHECK(first_page->next_page() == faked_space.anchor()); + total_pages++; - Page* last_page = first_page; - for (Page* p = first_page; p->is_valid(); p = p->next_page()) { - CHECK(memory_allocator->IsPageInSpace(p, &faked_space)); - last_page = p; + for (Page* p = first_page; p != faked_space.anchor(); p = p->next_page()) { + CHECK(p->owner() == &faked_space); } // Again, we should get n or n - 1 pages. - Page* others = memory_allocator->AllocatePages( - requested, &allocated, &faked_space); - CHECK(others->is_valid()); - CHECK(allocated == requested || allocated == requested - 1); - total_pages += allocated; - - memory_allocator->SetNextPage(last_page, others); + Page* other = + memory_allocator->AllocatePage(&faked_space, NOT_EXECUTABLE); + CHECK(other->is_valid()); + total_pages++; + other->InsertAfter(first_page); int page_count = 0; - for (Page* p = first_page; p->is_valid(); p = p->next_page()) { - CHECK(memory_allocator->IsPageInSpace(p, &faked_space)); + for (Page* p = first_page; p != faked_space.anchor(); p = p->next_page()) { + CHECK(p->owner() == &faked_space); page_count++; } CHECK(total_pages == page_count); Page* second_page = first_page->next_page(); CHECK(second_page->is_valid()); - - // Freeing pages at the first chunk starting at or after the second page - // should free the entire second chunk. It will return the page it was passed - // (since the second page was in the first chunk). - Page* free_return = memory_allocator->FreePages(second_page); - CHECK(free_return == second_page); - memory_allocator->SetNextPage(first_page, free_return); - - // Freeing pages in the first chunk starting at the first page should free - // the first chunk and return an invalid page. - Page* invalid_page = memory_allocator->FreePages(first_page); - CHECK(!invalid_page->is_valid()); - + memory_allocator->Free(first_page); + memory_allocator->Free(second_page); memory_allocator->TearDown(); delete memory_allocator; } @@ -196,17 +187,14 @@ TEST(NewSpace) { NewSpace new_space(heap); - void* chunk = - memory_allocator->ReserveInitialChunk(4 * heap->ReservedSemiSpaceSize()); - CHECK(chunk != NULL); - Address start = RoundUp(static_cast<Address>(chunk), - 2 * heap->ReservedSemiSpaceSize()); - CHECK(new_space.Setup(start, 2 * heap->ReservedSemiSpaceSize())); + CHECK(new_space.Setup(HEAP->ReservedSemiSpaceSize(), + HEAP->ReservedSemiSpaceSize())); CHECK(new_space.HasBeenSetup()); - while (new_space.Available() >= Page::kMaxHeapObjectSize) { + while (new_space.Available() >= Page::kMaxNonCodeHeapObjectSize) { Object* obj = - new_space.AllocateRaw(Page::kMaxHeapObjectSize)->ToObjectUnchecked(); + new_space.AllocateRaw(Page::kMaxNonCodeHeapObjectSize)-> + ToObjectUnchecked(); CHECK(new_space.Contains(HeapObject::cast(obj))); } @@ -233,16 +221,10 @@ TEST(OldSpace) { NOT_EXECUTABLE); CHECK(s != NULL); - void* chunk = memory_allocator->ReserveInitialChunk( - 4 * heap->ReservedSemiSpaceSize()); - CHECK(chunk != NULL); - Address start = static_cast<Address>(chunk); - size_t size = RoundUp(start, 2 * heap->ReservedSemiSpaceSize()) - start; - - CHECK(s->Setup(start, size)); + CHECK(s->Setup()); while (s->Available() > 0) { - s->AllocateRaw(Page::kMaxHeapObjectSize)->ToObjectUnchecked(); + s->AllocateRaw(Page::kMaxNonCodeHeapObjectSize)->ToObjectUnchecked(); } s->TearDown(); @@ -258,14 +240,12 @@ TEST(LargeObjectSpace) { LargeObjectSpace* lo = HEAP->lo_space(); CHECK(lo != NULL); - Map* faked_map = reinterpret_cast<Map*>(HeapObject::FromAddress(0)); int lo_size = Page::kPageSize; - Object* obj = lo->AllocateRaw(lo_size)->ToObjectUnchecked(); + Object* obj = lo->AllocateRaw(lo_size, NOT_EXECUTABLE)->ToObjectUnchecked(); CHECK(obj->IsHeapObject()); HeapObject* ho = HeapObject::cast(obj); - ho->set_map(faked_map); CHECK(lo->Contains(HeapObject::cast(obj))); @@ -275,14 +255,13 @@ TEST(LargeObjectSpace) { while (true) { intptr_t available = lo->Available(); - { MaybeObject* maybe_obj = lo->AllocateRaw(lo_size); + { MaybeObject* maybe_obj = lo->AllocateRaw(lo_size, NOT_EXECUTABLE); if (!maybe_obj->ToObject(&obj)) break; } - HeapObject::cast(obj)->set_map(faked_map); CHECK(lo->Available() < available); }; CHECK(!lo->IsEmpty()); - CHECK(lo->AllocateRaw(lo_size)->IsFailure()); + CHECK(lo->AllocateRaw(lo_size, NOT_EXECUTABLE)->IsFailure()); } diff --git a/test/cctest/test-strings.cc b/test/cctest/test-strings.cc index 55c21417..93f7588d 100644 --- a/test/cctest/test-strings.cc +++ b/test/cctest/test-strings.cc @@ -1,4 +1,4 @@ -// Copyright 2006-2008 the V8 project authors. All rights reserved. +// Copyright 2011 the V8 project authors. All rights reserved. // Check that we can traverse very deep stacks of ConsStrings using // StringInputBuffer. Check that Get(int) works on very deep stacks @@ -502,6 +502,35 @@ TEST(SliceFromCons) { } +class AsciiVectorResource : public v8::String::ExternalAsciiStringResource { + public: + explicit AsciiVectorResource(i::Vector<const char> vector) + : data_(vector) {} + virtual ~AsciiVectorResource() {} + virtual size_t length() const { return data_.length(); } + virtual const char* data() const { return data_.start(); } + private: + i::Vector<const char> data_; +}; + + +TEST(SliceFromExternal) { + FLAG_string_slices = true; + InitializeVM(); + v8::HandleScope scope; + AsciiVectorResource resource( + i::Vector<const char>("abcdefghijklmnopqrstuvwxyz", 26)); + Handle<String> string = FACTORY->NewExternalStringFromAscii(&resource); + CHECK(string->IsExternalString()); + Handle<String> slice = FACTORY->NewSubString(string, 1, 25); + CHECK(slice->IsSlicedString()); + CHECK(string->IsExternalString()); + CHECK_EQ(SlicedString::cast(*slice)->parent(), *string); + CHECK(SlicedString::cast(*slice)->parent()->IsExternalString()); + CHECK(slice->IsFlat()); +} + + TEST(TrivialSlice) { // This tests whether a slice that contains the entire parent string // actually creates a new string (it should not). diff --git a/test/cctest/test-threads.cc b/test/cctest/test-threads.cc index 985b9e5b..713d1e84 100644 --- a/test/cctest/test-threads.cc +++ b/test/cctest/test-threads.cc @@ -63,7 +63,7 @@ enum Turn { static Turn turn = FILL_CACHE; -class ThreadA: public v8::internal::Thread { +class ThreadA : public v8::internal::Thread { public: ThreadA() : Thread("ThreadA") { } void Run() { @@ -99,7 +99,7 @@ class ThreadA: public v8::internal::Thread { }; -class ThreadB: public v8::internal::Thread { +class ThreadB : public v8::internal::Thread { public: ThreadB() : Thread("ThreadB") { } void Run() { @@ -111,7 +111,7 @@ class ThreadB: public v8::internal::Thread { v8::Context::Scope context_scope(v8::Context::New()); // Clear the caches by forcing major GC. - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(v8::internal::Heap::kNoGCFlags); turn = SECOND_TIME_FILL_CACHE; break; } @@ -190,3 +190,19 @@ TEST(ThreadIdValidation) { delete threads[i]; } } + + +class ThreadC : public v8::internal::Thread { + public: + ThreadC() : Thread("ThreadC") { } + void Run() { + Join(); + } +}; + + +TEST(ThreadJoinSelf) { + ThreadC thread; + thread.Start(); + thread.Join(); +} diff --git a/test/cctest/test-weakmaps.cc b/test/cctest/test-weakmaps.cc index db4db254..56d59362 100644 --- a/test/cctest/test-weakmaps.cc +++ b/test/cctest/test-weakmaps.cc @@ -50,7 +50,7 @@ static void PutIntoWeakMap(Handle<JSWeakMap> weakmap, Handle<JSObject> key, int value) { Handle<ObjectHashTable> table = PutIntoObjectHashTable( - Handle<ObjectHashTable>(weakmap->table()), + Handle<ObjectHashTable>(ObjectHashTable::cast(weakmap->table())), Handle<JSObject>(JSObject::cast(*key)), Handle<Smi>(Smi::FromInt(value))); weakmap->set_table(*table); @@ -85,13 +85,14 @@ TEST(Weakness) { v8::HandleScope scope; PutIntoWeakMap(weakmap, Handle<JSObject>(JSObject::cast(*key)), 23); } - CHECK_EQ(1, weakmap->table()->NumberOfElements()); + CHECK_EQ(1, ObjectHashTable::cast(weakmap->table())->NumberOfElements()); // Force a full GC. HEAP->CollectAllGarbage(false); CHECK_EQ(0, NumberOfWeakCalls); - CHECK_EQ(1, weakmap->table()->NumberOfElements()); - CHECK_EQ(0, weakmap->table()->NumberOfDeletedElements()); + CHECK_EQ(1, ObjectHashTable::cast(weakmap->table())->NumberOfElements()); + CHECK_EQ( + 0, ObjectHashTable::cast(weakmap->table())->NumberOfDeletedElements()); // Make the global reference to the key weak. { @@ -107,12 +108,14 @@ TEST(Weakness) { // weak references whereas the second one will also clear weak maps. HEAP->CollectAllGarbage(false); CHECK_EQ(1, NumberOfWeakCalls); - CHECK_EQ(1, weakmap->table()->NumberOfElements()); - CHECK_EQ(0, weakmap->table()->NumberOfDeletedElements()); + CHECK_EQ(1, ObjectHashTable::cast(weakmap->table())->NumberOfElements()); + CHECK_EQ( + 0, ObjectHashTable::cast(weakmap->table())->NumberOfDeletedElements()); HEAP->CollectAllGarbage(false); CHECK_EQ(1, NumberOfWeakCalls); - CHECK_EQ(0, weakmap->table()->NumberOfElements()); - CHECK_EQ(1, weakmap->table()->NumberOfDeletedElements()); + CHECK_EQ(0, ObjectHashTable::cast(weakmap->table())->NumberOfElements()); + CHECK_EQ( + 1, ObjectHashTable::cast(weakmap->table())->NumberOfDeletedElements()); } @@ -122,7 +125,7 @@ TEST(Shrinking) { Handle<JSWeakMap> weakmap = AllocateJSWeakMap(); // Check initial capacity. - CHECK_EQ(32, weakmap->table()->Capacity()); + CHECK_EQ(32, ObjectHashTable::cast(weakmap->table())->Capacity()); // Fill up weak map to trigger capacity change. { @@ -135,15 +138,17 @@ TEST(Shrinking) { } // Check increased capacity. - CHECK_EQ(128, weakmap->table()->Capacity()); + CHECK_EQ(128, ObjectHashTable::cast(weakmap->table())->Capacity()); // Force a full GC. - CHECK_EQ(32, weakmap->table()->NumberOfElements()); - CHECK_EQ(0, weakmap->table()->NumberOfDeletedElements()); + CHECK_EQ(32, ObjectHashTable::cast(weakmap->table())->NumberOfElements()); + CHECK_EQ( + 0, ObjectHashTable::cast(weakmap->table())->NumberOfDeletedElements()); HEAP->CollectAllGarbage(false); - CHECK_EQ(0, weakmap->table()->NumberOfElements()); - CHECK_EQ(32, weakmap->table()->NumberOfDeletedElements()); + CHECK_EQ(0, ObjectHashTable::cast(weakmap->table())->NumberOfElements()); + CHECK_EQ( + 32, ObjectHashTable::cast(weakmap->table())->NumberOfDeletedElements()); // Check shrunk capacity. - CHECK_EQ(32, weakmap->table()->Capacity()); + CHECK_EQ(32, ObjectHashTable::cast(weakmap->table())->Capacity()); } diff --git a/test/es5conform/es5conform.status b/test/es5conform/es5conform.status index d095a247..bf3ee8bb 100644 --- a/test/es5conform/es5conform.status +++ b/test/es5conform/es5conform.status @@ -41,16 +41,6 @@ chapter10/10.4/10.4.2/10.4.2-2-c-1: FAIL_OK # We are compatible with Safari and Firefox. chapter11/11.1/11.1.5: UNIMPLEMENTED -# We do not have a global object called 'global' as required by tests. -chapter15/15.1: FAIL_OK - -# NaN is writable. We are compatible with JSC. -chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-178: FAIL_OK -# Infinity is writable. We are compatible with JSC. -chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-179: FAIL_OK -# undefined is writable. We are compatible with JSC. -chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-180: FAIL_OK - # Our Function object has an "arguments" property which is used as a # non-property in the test. chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-183: FAIL_OK @@ -106,9 +96,6 @@ chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-7: FAIL_OK # SUBSETFAIL chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-11: FAIL_OK -# We do not implement all methods on RegExp. -chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-13: FAIL - # SUBSETFAIL chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-14: FAIL_OK @@ -196,27 +183,6 @@ chapter15/15.4/15.4.4/15.4.4.22/15.4.4.22-9-c-ii-4-s: SKIP # have no effect on the actual array on which reduceRight is called. chapter15/15.4/15.4.4/15.4.4.22/15.4.4.22-9-7: FAIL_OK -# We do not correctly recognize \uFEFF as whitespace -chapter15/15.5/15.5.4/15.5.4.20/15.5.4.20-4-10: FAIL -chapter15/15.5/15.5.4/15.5.4.20/15.5.4.20-4-18: FAIL -chapter15/15.5/15.5.4/15.5.4.20/15.5.4.20-4-34: FAIL - -# RegExp.prototype is not of type RegExp - we are bug compatible with JSC. -chapter15/15.10/15.10.6/15.10.6: FAIL_OK - -# We do not have the properties of a RegExp instance on RegExp.prototype. -# The spec says we should - but we are currently bug compatible with JSC. -chapter15/15.10/15.10.7/15.10.7.1/15.10.7.1-1: FAIL_OK -chapter15/15.10/15.10.7/15.10.7.1/15.10.7.1-2: FAIL_OK -chapter15/15.10/15.10.7/15.10.7.2/15.10.7.2-1: FAIL_OK -chapter15/15.10/15.10.7/15.10.7.2/15.10.7.2-2: FAIL_OK -chapter15/15.10/15.10.7/15.10.7.3/15.10.7.3-1: FAIL_OK -chapter15/15.10/15.10.7/15.10.7.3/15.10.7.3-2: FAIL_OK -chapter15/15.10/15.10.7/15.10.7.4/15.10.7.4-1: FAIL_OK -chapter15/15.10/15.10.7/15.10.7.4/15.10.7.4-2: FAIL_OK -chapter15/15.10/15.10.7/15.10.7.5/15.10.7.5-1: FAIL_OK -chapter15/15.10/15.10.7/15.10.7.5/15.10.7.5-2: FAIL_OK - ############################################################################## # Unimplemented parts of strict mode # Setting expectations to fail only so that the tests trigger as soon as diff --git a/test/mjsunit/apply.js b/test/mjsunit/apply.js index c166110d..413ee937 100644 --- a/test/mjsunit/apply.js +++ b/test/mjsunit/apply.js @@ -190,3 +190,10 @@ assertEquals("morseper", "moreseper-prime"); delete(Array.prototype["1"]); + +// Check correct handling of non-array argument lists. +assertSame(this, f0.apply(this, {}), "non-array-1"); +assertSame(this, f0.apply(this, { length:1 }), "non-array-2"); +assertEquals(void 0, f1.apply(this, { length:1 }), "non-array-3"); +assertEquals(void 0, f1.apply(this, { 0:"foo" }), "non-array-4"); +assertEquals("foo", f1.apply(this, { length:1, 0:"foo" }), "non-array-5"); diff --git a/test/mjsunit/array-literal-transitions.js b/test/mjsunit/array-literal-transitions.js new file mode 100644 index 00000000..321340c4 --- /dev/null +++ b/test/mjsunit/array-literal-transitions.js @@ -0,0 +1,125 @@ +// Copyright 2011 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. + +// Flags: --allow-natives-syntax --smi-only-arrays --expose-gc +// Test element kind of objects. +// Since --smi-only-arrays affects builtins, its default setting at compile +// time sticks if built with snapshot. If --smi-only-arrays is deactivated +// by default, only a no-snapshot build actually has smi-only arrays enabled +// in this test case. Depending on whether smi-only arrays are actually +// enabled, this test takes the appropriate code path to check smi-only arrays. + +support_smi_only_arrays = %HasFastSmiOnlyElements(new Array()); + +// IC and Crankshaft support for smi-only elements in dynamic array literals. +function get(foo) { return foo; } // Used to generate dynamic values. + +function array_literal_test() { + var a0 = [1, 2, 3]; + assertTrue(%HasFastSmiOnlyElements(a0)); + var a1 = [get(1), get(2), get(3)]; + assertTrue(%HasFastSmiOnlyElements(a1)); + + var b0 = [1, 2, get("three")]; + assertTrue(%HasFastElements(b0)); + var b1 = [get(1), get(2), get("three")]; + assertTrue(%HasFastElements(b1)); + + var c0 = [1, 2, get(3.5)]; + assertTrue(%HasFastDoubleElements(c0)); + assertEquals(3.5, c0[2]); + assertEquals(2, c0[1]); + assertEquals(1, c0[0]); + + var c1 = [1, 2, 3.5]; + assertTrue(%HasFastDoubleElements(c1)); + assertEquals(3.5, c1[2]); + assertEquals(2, c1[1]); + assertEquals(1, c1[0]); + + var c2 = [get(1), get(2), get(3.5)]; + assertTrue(%HasFastDoubleElements(c2)); + assertEquals(3.5, c2[2]); + assertEquals(2, c2[1]); + assertEquals(1, c2[0]); + + var object = new Object(); + var d0 = [1, 2, object]; + assertTrue(%HasFastElements(d0)); + assertEquals(object, d0[2]); + assertEquals(2, d0[1]); + assertEquals(1, d0[0]); + + var e0 = [1, 2, 3.5]; + assertTrue(%HasFastDoubleElements(e0)); + assertEquals(3.5, e0[2]); + assertEquals(2, e0[1]); + assertEquals(1, e0[0]); + + var f0 = [1, 2, [1, 2]]; + assertTrue(%HasFastElements(f0)); + assertEquals([1,2], f0[2]); + assertEquals(2, f0[1]); + assertEquals(1, f0[0]); +} + +if (support_smi_only_arrays) { + for (var i = 0; i < 3; i++) { + array_literal_test(); + } + %OptimizeFunctionOnNextCall(array_literal_test); + array_literal_test(); + + function test_large_literal() { + + function d() { + gc(); + return 2.5; + } + + function o() { + gc(); + return new Object(); + } + + large = + [ 0, 1, 2, 3, 4, 5, d(), d(), d(), d(), d(), d(), o(), o(), o(), o() ]; + assertFalse(%HasDictionaryElements(large)); + assertFalse(%HasFastSmiOnlyElements(large)); + assertFalse(%HasFastDoubleElements(large)); + assertTrue(%HasFastElements(large)); + assertEquals(large, + [0, 1, 2, 3, 4, 5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, + new Object(), new Object(), new Object(), new Object()]); + } + + for (var i = 0; i < 3; i++) { + test_large_literal(); + } + %OptimizeFunctionOnNextCall(test_large_literal); + test_large_literal(); +} diff --git a/test/mjsunit/array-tostring.js b/test/mjsunit/array-tostring.js new file mode 100644 index 00000000..6708657e --- /dev/null +++ b/test/mjsunit/array-tostring.js @@ -0,0 +1,159 @@ +// Copyright 2011 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. + +// Array's toString should call the object's own join method, if one exists and +// is callable. Otherwise, just use the original Object.toString function. + +var success = "[test success]"; +var expectedThis; +function testJoin() { + assertEquals(0, arguments.length); + assertSame(expectedThis, this); + return success; +} + + +// On an Array object. + +// Default case. +var a1 = [1, 2, 3]; +assertEquals(a1.join(), a1.toString()); + +// Non-standard "join" function is called correctly. +var a2 = [1, 2, 3]; +a2.join = testJoin; +expectedThis = a2; +assertEquals(success, a2.toString()); + +// Non-callable join function is ignored and Object.prototype.toString is +// used instead. +var a3 = [1, 2, 3]; +a3.join = "not callable"; +assertEquals("[object Array]", a3.toString()); + +// Non-existing join function is treated same as non-callable. +var a4 = [1, 2, 3]; +a4.__proto__ = { toString: Array.prototype.toString }; +// No join on Array. +assertEquals("[object Array]", a4.toString()); + + +// On a non-Array object. + +// Default looks-like-an-array case. +var o1 = {length: 3, 0: 1, 1: 2, 2: 3, + toString: Array.prototype.toString, + join: Array.prototype.join}; +assertEquals(o1.join(), o1.toString()); + + +// Non-standard join is called correctly. +// Check that we don't read, e.g., length before calling join. +var o2 = {toString : Array.prototype.toString, + join: testJoin, + get length() { assertUnreachable(); }, + get 0() { assertUnreachable(); }}; +expectedThis = o2; +assertEquals(success, o2.toString()); + +// Non-standard join is called even if it looks like an array. +var o3 = {length: 3, 0: 1, 1: 2, 2: 3, + toString: Array.prototype.toString, + join: testJoin}; +expectedThis = o3; +assertEquals(success, o3.toString()); + +// Non-callable join works same as for Array. +var o4 = {length: 3, 0: 1, 1: 2, 2: 3, + toString: Array.prototype.toString, + join: "not callable"}; +assertEquals("[object Object]", o4.toString()); + + +// Non-existing join works same as for Array. +var o5 = {length: 3, 0: 1, 1: 2, 2: 3, + toString: Array.prototype.toString + /* no join */}; +assertEquals("[object Object]", o5.toString()); + + +// Test that ToObject is called before getting "join", so the instance +// that "join" is read from is the same one passed as receiver later. +var called_before = false; +expectedThis = null; +Object.defineProperty(Number.prototype, "join", {get: function() { + assertFalse(called_before); + called_before = true; + expectedThis = this; + return testJoin; + }}); +Number.prototype.arrayToString = Array.prototype.toString; +assertEquals(success, (42).arrayToString()); + +// ---------------------------------------------------------- +// Testing Array.prototype.toLocaleString + +// Ensure that it never uses Array.prototype.toString for anything. +Array.prototype.toString = function() { assertUnreachable(); }; + +// Default case. +var la1 = [1, [2, 3], 4]; +assertEquals("1,2,3,4", la1.toLocaleString()); + +// Used on a string (which looks like an array of characters). +String.prototype.toLocaleString = Array.prototype.toLocaleString; +assertEquals("1,2,3,4", "1234".toLocaleString()); + +// If toLocaleString of element is not callable, throw a TypeError. +var la2 = [1, {toLocaleString: "not callable"}, 3]; +assertThrows(function() { la2.toLocaleString(); }, TypeError); + +// If toLocaleString of element is callable, call it. +var la3 = [1, {toLocaleString: function() { return "XX";}}, 3]; +assertEquals("1,XX,3", la3.toLocaleString()); + +// Omitted elements, as well as undefined and null, become empty string. +var la4 = [1, null, 3, undefined, 5,, 7]; +assertEquals("1,,3,,5,,7", la4.toLocaleString()); + + +// ToObject is called first and the same object is being used for the +// rest of the operations. +Object.defineProperty(Number.prototype, "length", { + get: function() { + exptectedThis = this; + return 3; + }}); +for (var i = 0; i < 3; i++) { + Object.defineProperty(Number.prototype, i, { + get: function() { + assertEquals(expectedThis, this); + return +this; + }}); +} +Number.prototype.arrayToLocaleString = Array.prototype.toLocaleString; +assertEquals("42,42,42", (42).arrayToLocaleString());
\ No newline at end of file diff --git a/test/mjsunit/assert-opt-and-deopt.js b/test/mjsunit/assert-opt-and-deopt.js index c9adb5bb..51cb99ad 100644 --- a/test/mjsunit/assert-opt-and-deopt.js +++ b/test/mjsunit/assert-opt-and-deopt.js @@ -150,11 +150,6 @@ tracker.AssertDeoptCount(f, 0); f(1); -tracker.AssertOptCount(f, 0); -tracker.AssertIsOptimized(f, false); -tracker.AssertDeoptHappened(f, false); -tracker.AssertDeoptCount(f, 0); - %OptimizeFunctionOnNextCall(f); f(1); @@ -172,6 +167,7 @@ tracker.AssertDeoptCount(f, 1); // Let's trigger optimization for another type. for (var i = 0; i < 5; i++) f("a"); + %OptimizeFunctionOnNextCall(f); f("b"); diff --git a/test/mjsunit/bugs/bug-618.js b/test/mjsunit/bugs/bug-618.js index ae843267..0513f87f 100644 --- a/test/mjsunit/bugs/bug-618.js +++ b/test/mjsunit/bugs/bug-618.js @@ -42,4 +42,4 @@ function C() { assertEquals(23, new C().x); C.prototype.__defineSetter__('x', function(value) { this.y = 23; }); -assertEquals(void 0, new C().x)); +assertEquals(void 0, new C().x); diff --git a/test/mjsunit/bugs/harmony/debug-blockscopes.js b/test/mjsunit/bugs/harmony/debug-blockscopes.js index a407c531..fda32eb3 100644 --- a/test/mjsunit/bugs/harmony/debug-blockscopes.js +++ b/test/mjsunit/bugs/harmony/debug-blockscopes.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --expose-debug-as debug --harmony-block-scoping +// Flags: --expose-debug-as debug --harmony-scoping // The functions used for testing backtraces. They are at the top to make the // testing of source line/column easier. diff --git a/test/mjsunit/compiler/compare.js b/test/mjsunit/compiler/compare.js index 3f960870..460b0ab0 100644 --- a/test/mjsunit/compiler/compare.js +++ b/test/mjsunit/compiler/compare.js @@ -83,9 +83,9 @@ function TestNonPrimitive(order, f) { } TestNonPrimitive("xy", MaxLT); -TestNonPrimitive("yx", MaxLE); +TestNonPrimitive("xy", MaxLE); TestNonPrimitive("xy", MaxGE); -TestNonPrimitive("yx", MaxGT); +TestNonPrimitive("xy", MaxGT); // Test compare in case of aliased registers. function CmpX(x) { if (x == x) return 42; } diff --git a/test/mjsunit/compiler/inline-context-slots.js b/test/mjsunit/compiler/inline-context-slots.js new file mode 100644 index 00000000..d0e907b1 --- /dev/null +++ b/test/mjsunit/compiler/inline-context-slots.js @@ -0,0 +1,49 @@ +// Copyright 2011 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. + +// Test inlining of functions with context slots. + +// Flags: --allow-natives-syntax + + +// Caller/callee without a local context. + +(function() { + var X = 5; + var Y = 10; + function F() {} + F.prototype.max = function() { + return X > Y ? X : Y; + } + F.prototype.run = function() { + return this.max(); + } + var f = new F(); + for (var i=0; i<5; i++) f.run(); + %OptimizeFunctionOnNextCall(f.run); + assertEquals(10, f.run()); +})(); diff --git a/test/mjsunit/regress/regress-221.js b/test/mjsunit/compiler/lazy-const-lookup.js index d3f2e355..b4f15a1c 100644 --- a/test/mjsunit/regress/regress-221.js +++ b/test/mjsunit/compiler/lazy-const-lookup.js @@ -1,4 +1,4 @@ -// Copyright 2009 the V8 project authors. All rights reserved. +// Copyright 2011 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: @@ -25,10 +25,17 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Test that direct eval calls handle the case where eval has been -// deleted correctly. +// Flags: --allow-natives-syntax -// See http://code.google.com/p/v8/issues/detail?id=221 +function outer() { + const x = 1; + function inner() { + return x; + } + inner(); + %OptimizeFunctionOnNextCall(inner); + inner(); +} -assertThrows('eval(delete eval)'); +outer(); diff --git a/test/mjsunit/cyclic-error-to-string.js b/test/mjsunit/compiler/regress-96989.js index 2502b534..aedeb243 100644 --- a/test/mjsunit/cyclic-error-to-string.js +++ b/test/mjsunit/compiler/regress-96989.js @@ -25,22 +25,19 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Test printing of cyclic errors which return the empty string for -// compatibility with Safari and Firefox. -var e = new Error(); -assertEquals('Error', e + ''); +// Flags: --allow-natives-syntax -e = new Error(); -e.name = e; -e.message = e; -e.stack = e; -e.arguments = e; -assertEquals(': ', e + ''); +// Test correct handling of uninitialized const. -e = new Error(); -e.name = [ e ]; -e.message = [ e ]; -e.stack = [ e ]; -e.arguments = [ e ]; -assertEquals(': ', e + ''); +function test() { + for (var i = 41; i < 42; i++) { + var c = t ^ i; + } + const t; + return c; +} + +for (var i=0; i<10; i++) test(); +%OptimizeFunctionOnNextCall(test); +assertEquals(41, test()); diff --git a/test/mjsunit/compiler/regress-deopt-call-as-function.js b/test/mjsunit/compiler/regress-deopt-call-as-function.js new file mode 100644 index 00000000..c4080969 --- /dev/null +++ b/test/mjsunit/compiler/regress-deopt-call-as-function.js @@ -0,0 +1,62 @@ +// Copyright 2011 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. + +// Test deoptimization after inlined call. + +function bar(a, b) {try { return a; } finally { } } + +function test_context() { + function foo(x) { return 42; } + var s, t; + for (var i = 0x7fff0000; i < 0x80000000; i++) { + bar(t = foo(i) ? bar(42 + i - i) : bar(0), s = i + t); + } + return s; +} +assertEquals(0x7fffffff + 42, test_context()); + + +function value_context() { + function foo(x) { return 42; } + var s, t; + for (var i = 0x7fff0000; i < 0x80000000; i++) { + bar(t = foo(i), s = i + t); + } + return s; +} +assertEquals(0x7fffffff + 42, value_context()); + + +function effect_context() { + function foo(x) { return 42; } + var s, t; + for (var i = 0x7fff0000; i < 0x80000000; i++) { + bar(foo(i), s = i + 42); + } + return s; +} +assertEquals(0x7fffffff + 42, effect_context()); diff --git a/test/mjsunit/compiler/regress-inline-callfunctionstub.js b/test/mjsunit/compiler/regress-inline-callfunctionstub.js new file mode 100644 index 00000000..a39d26df --- /dev/null +++ b/test/mjsunit/compiler/regress-inline-callfunctionstub.js @@ -0,0 +1,46 @@ +// Copyright 2011 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. + +// Flags: --allow-natives-syntax + +// Test inlined of calls-as-function two levels deep. +function f() { return 42; } + +var o = {g : function () { return f(); } } +function main(func) { + var v=0; + for (var i=0; i<1; i++) { + if (func()) v = 42; + } +} + +main(o.g); +main(o.g); +main(o.g); +%OptimizeFunctionOnNextCall(main); +main(o.g); + diff --git a/test/mjsunit/compiler/strict-recompile.js b/test/mjsunit/compiler/strict-recompile.js new file mode 100644 index 00000000..96e8bcab --- /dev/null +++ b/test/mjsunit/compiler/strict-recompile.js @@ -0,0 +1,51 @@ +// Copyright 2011 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. + +// Flags: --allow-natives-syntax + +function foo() { + try { + var o = {}; + Object.defineProperty(o, 'x', {value: 12, writable: false}); + o.x = 13; + } catch(e) { + return true; + } + return false; +} + +assertFalse(foo()); + +function do_eval(str) { + "use strict"; + return eval(str); +} + +var eval_foo = do_eval('(' + foo + ')'); +for (var i = 0; i < 5; i++) assertTrue(eval_foo()); +%OptimizeFunctionOnNextCall(eval_foo); +assertTrue(eval_foo()); diff --git a/test/mjsunit/const-redecl.js b/test/mjsunit/const-redecl.js index 94597089..c0b97e6c 100644 --- a/test/mjsunit/const-redecl.js +++ b/test/mjsunit/const-redecl.js @@ -98,7 +98,8 @@ function TestAll(expected,s,opt_e) { var msg = s; if (opt_e) { e = opt_e; msg += "; " + opt_e; } assertEquals(expected, TestLocal(s,e), "local:'" + msg + "'"); - assertEquals(expected, TestGlobal(s,e), "global:'" + msg + "'"); + // Redeclarations of global consts do not throw, they are silently ignored. + assertEquals(42, TestGlobal(s, 42), "global:'" + msg + "'"); assertEquals(expected, TestContext(s,e), "context:'" + msg + "'"); } @@ -218,3 +219,62 @@ TestAll(0, "var a,b,c,d,e,f,g,h; " + loop, "x"); // Test that const inside with behaves correctly. TestAll(87, "with ({x:42}) { const x = 87; }", "x"); TestAll(undefined, "with ({x:42}) { const x; }", "x"); + + +// Additional tests for how various combinations of re-declarations affect +// the values of the var/const in question. +try { + eval("var undefined;"); +} catch (ex) { + assertUnreachable("undefined (1) has thrown"); +} + +var original_undef = undefined; +var undefined = 1; // Should be silently ignored. +assertEquals(original_undef, undefined, "undefined got overwritten"); +undefined = original_undef; + +var a; const a; const a = 1; +assertEquals(1, a, "a has wrong value"); +a = 2; +assertEquals(2, a, "a should be writable"); + +var b = 1; const b = 2; +assertEquals(2, b, "b has wrong value"); + +var c = 1; const c = 2; const c = 3; +assertEquals(3, c, "c has wrong value"); + +const d = 1; const d = 2; +assertEquals(1, d, "d has wrong value"); + +const e = 1; var e = 2; +assertEquals(1, e, "e has wrong value"); + +const f = 1; const f; +assertEquals(1, f, "f has wrong value"); + +var g; const g = 1; +assertEquals(1, g, "g has wrong value"); +g = 2; +assertEquals(2, g, "g should be writable"); + +const h; var h = 1; +assertEquals(undefined,h, "h has wrong value"); + +eval("Object.defineProperty(this, 'i', { writable: true });" + + "const i = 7;" + + "assertEquals(7, i, \"i has wrong value\");"); + +var global = this; +assertThrows(function() { + Object.defineProperty(global, 'j', { writable: true }) +}, TypeError); +const j = 2; // This is what makes the function above throw, because the +// const declaration gets hoisted and makes the property non-configurable. +assertEquals(2, j, "j has wrong value"); + +var k = 1; const k; +// You could argue about the expected result here. For now, the winning +// argument is that "const k;" is equivalent to "const k = undefined;". +assertEquals(undefined, k, "k has wrong value"); diff --git a/test/mjsunit/date.js b/test/mjsunit/date.js index a7f6cfa7..fa43cbb4 100644 --- a/test/mjsunit/date.js +++ b/test/mjsunit/date.js @@ -157,7 +157,7 @@ testToLocaleTimeString(); // Test that -0 is treated correctly in MakeDay. var d = new Date(); assertDoesNotThrow("d.setDate(-0)"); -assertDoesNotThrow("new Date(-0, -0, -0, -0, -0, -0. -0)"); +assertDoesNotThrow("new Date(-0, -0, -0, -0, -0, -0, -0)"); assertDoesNotThrow("new Date(0x40000000, 0x40000000, 0x40000000," + "0x40000000, 0x40000000, 0x40000000, 0x40000000)") assertDoesNotThrow("new Date(-0x40000001, -0x40000001, -0x40000001," + @@ -178,7 +178,7 @@ assertTrue(isNaN(Date.UTC(-271821, 3, 19, 23, 59, 59, 999))); assertTrue(isNaN(Date.UTC(-271821, 3, 19))); -// Test creation of large date values. +// Test creation with large date values. d = new Date(1969, 12, 1, 99999999999); assertTrue(isNaN(d.getTime())); d = new Date(1969, 12, 1, -99999999999); @@ -188,6 +188,12 @@ assertTrue(isNaN(d.getTime())); d = new Date(1969, 12, 1, -Infinity); assertTrue(isNaN(d.getTime())); + +// Test creation with obscure date values. +assertEquals(8640000000000000, Date.UTC(1970, 0, 1 + 100000001, -24)); +assertEquals(-8640000000000000, Date.UTC(1970, 0, 1 - 100000001, 24)); + + // Parsing ES5 ISO-8601 dates. // When TZ is omitted, it defaults to 'Z' meaning UTC. diff --git a/test/mjsunit/debug-break-inline.js b/test/mjsunit/debug-break-inline.js new file mode 100644 index 00000000..4418fa8d --- /dev/null +++ b/test/mjsunit/debug-break-inline.js @@ -0,0 +1,100 @@ +// Copyright 2011 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. + +// Flags: --expose-debug-as debug --allow-natives-syntax + +// This test tests that deoptimization due to debug breaks works for +// inlined functions where the full-code is generated before the +// debugger is attached. +// +//See http://code.google.com/p/chromium/issues/detail?id=105375 + +// Get the Debug object exposed from the debug context global object. +Debug = debug.Debug; + +var count = 0; +var break_count = 0; + +// Debug event listener which sets a breakpoint first time it is hit +// and otherwise counts break points hit and checks that the expected +// state is reached. +function listener(event, exec_state, event_data, data) { + if (event == Debug.DebugEvent.Break) { + break_count++; + if (break_count == 1) { + Debug.setBreakPoint(g, 3); + + for (var i = 0; i < exec_state.frameCount(); i++) { + var frame = exec_state.frame(i); + // When function f is optimized (1 means YES, see runtime.cc) we + // expect an optimized frame for f and g. + if (%GetOptimizationStatus(f) == 1) { + if (i == 1) { + assertTrue(frame.isOptimizedFrame()); + assertTrue(frame.isInlinedFrame()); + assertEquals(4 - i, frame.inlinedFrameIndex()); + } else if (i == 2) { + assertTrue(frame.isOptimizedFrame()); + assertFalse(frame.isInlinedFrame()); + } else { + assertFalse(frame.isOptimizedFrame()); + assertFalse(frame.isInlinedFrame()); + } + } + } + } + } +} + +function f() { + g(); +} + +function g() { + count++; + h(); + var b = 1; // Break point is set here. +} + +function h() { + debugger; +} + +f();f();f(); +%OptimizeFunctionOnNextCall(f); +f(); + +// Add the debug event listener. +Debug.setListener(listener); + +f(); + +assertEquals(5, count); +assertEquals(2, break_count); + +// Get rid of the debug event listener. +Debug.setListener(null); diff --git a/test/mjsunit/debug-evaluate-locals-optimized-double.js b/test/mjsunit/debug-evaluate-locals-optimized-double.js index 8447df53..9ed1dbbe 100644 --- a/test/mjsunit/debug-evaluate-locals-optimized-double.js +++ b/test/mjsunit/debug-evaluate-locals-optimized-double.js @@ -50,12 +50,10 @@ function listener(event, exec_state, event_data, data) { var expected_y = (i + 1) * 2 + 2 + ((i + 1) * 2 + 2) / 100; // All frames except the bottom one has normal variables a and b. - var a = ('a' === frame.localName(0)) ? 0 : 1; - var b = 1 - a; - assertEquals('a', frame.localName(a)); - assertEquals('b', frame.localName(b)); - assertEquals(expected_a, frame.localValue(a).value()); - assertEquals(expected_b, frame.localValue(b).value()); + assertEquals('a', frame.localName(0)); + assertEquals('b', frame.localName(1)); + assertEquals(expected_a, frame.localValue(0).value()); + assertEquals(expected_b, frame.localValue(1).value()); // All frames except the bottom one has arguments variables x and y. assertEquals('x', frame.argumentName(0)); diff --git a/test/mjsunit/debug-evaluate-locals-optimized.js b/test/mjsunit/debug-evaluate-locals-optimized.js index c3cd5eb2..683c139d 100644 --- a/test/mjsunit/debug-evaluate-locals-optimized.js +++ b/test/mjsunit/debug-evaluate-locals-optimized.js @@ -50,12 +50,10 @@ function listener(event, exec_state, event_data, data) { var expected_y = (i + 1) * 2 + 2; // All frames except the bottom one has normal variables a and b. - var a = ('a' === frame.localName(0)) ? 0 : 1; - var b = 1 - a; - assertEquals('a', frame.localName(a)); - assertEquals('b', frame.localName(b)); - assertEquals(expected_a, frame.localValue(a).value()); - assertEquals(expected_b, frame.localValue(b).value()); + assertEquals('a', frame.localName(0)); + assertEquals('b', frame.localName(1)); + assertEquals(expected_a, frame.localValue(0).value()); + assertEquals(expected_b, frame.localValue(1).value()); // All frames except the bottom one has arguments variables x and y. assertEquals('x', frame.argumentName(0)); @@ -121,7 +119,7 @@ function listener(event, exec_state, event_data, data) { listenerComplete = true; } } catch (e) { - exception = e.stack; + exception = e }; }; diff --git a/test/mjsunit/debug-scopes.js b/test/mjsunit/debug-scopes.js index 1c23b0bf..942bd2bb 100644 --- a/test/mjsunit/debug-scopes.js +++ b/test/mjsunit/debug-scopes.js @@ -1,4 +1,4 @@ -// Copyright 2008 the V8 project authors. All rights reserved. +// Copyright 2011 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: @@ -25,13 +25,12 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --expose-debug-as debug +// Flags: --expose-debug-as debug --allow-natives-syntax // The functions used for testing backtraces. They are at the top to make the // testing of source line/column easier. - // Get the Debug object exposed from the debug context global object. -Debug = debug.Debug; +var Debug = debug.Debug; var test_name; var listener_delegate; @@ -439,6 +438,26 @@ with(with_object) { EndTest(); +// With block in function that is marked for optimization while being executed. +BeginTest("With 7"); + +function with_7() { + with({}) { + %OptimizeFunctionOnNextCall(with_7); + debugger; + } +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.With, + debug.ScopeType.Local, + debug.ScopeType.Global], exec_state); + CheckScopeContent({}, 0, exec_state); +}; +with_7(); +EndTest(); + + // Simple closure formed by returning an inner function referering the outer // functions arguments. BeginTest("Closure 1"); @@ -950,6 +969,28 @@ try { EndTest(); +// Catch block in function that is marked for optimization while being executed. +BeginTest("Catch block 7"); +function catch_block_7() { + %OptimizeFunctionOnNextCall(catch_block_7); + try { + throw 'Exception'; + } catch (e) { + debugger; + } +}; + + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Catch, + debug.ScopeType.Local, + debug.ScopeType.Global], exec_state); + CheckScopeContent({e:'Exception'}, 0, exec_state); +}; +catch_block_7(); +EndTest(); + + assertEquals(begin_test_count, break_count, 'one or more tests did not enter the debugger'); assertEquals(begin_test_count, end_test_count, diff --git a/test/mjsunit/debug-step-3.js b/test/mjsunit/debug-step-3.js new file mode 100644 index 00000000..9cac0f56 --- /dev/null +++ b/test/mjsunit/debug-step-3.js @@ -0,0 +1,94 @@ +// Copyright 2011 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. + +// Flags: --expose-debug-as debug + +// This test tests that full code compiled without debug break slots +// is recompiled with debug break slots when debugging is started. + +// Get the Debug object exposed from the debug context global object. +Debug = debug.Debug + +var bp; +var done = false; +var step_count = 0; +var set_bp = false + +// Debug event listener which steps until the global variable done is true. +function listener(event, exec_state, event_data, data) { + if (event == Debug.DebugEvent.Break) { + if (!done) exec_state.prepareStep(Debug.StepAction.StepNext); + step_count++; + } +}; + +// Set the global variables state to prpare the stepping test. +function prepare_step_test() { + done = false; + step_count = 0; +} + +// Test function to step through. +function f() { + var a = 0; + if (set_bp) { bp = Debug.setBreakPoint(f, 3); } + var i = 1; + var j = 2; + done = true; +}; + +prepare_step_test(); +f(); + +// Add the debug event listener. +Debug.setListener(listener); + +// Make f set a breakpoint with an activation on the stack. +prepare_step_test(); +set_bp = true; +f(); +// TODO(1782): Fix issue to bring back this assert. +//assertEquals(4, step_count); +Debug.clearBreakPoint(bp); + +// Set a breakpoint on the first var statement (line 1). +set_bp = false; +bp = Debug.setBreakPoint(f, 3); + +// Step through the function ensuring that the var statements are hit as well. +prepare_step_test(); +f(); +assertEquals(4, step_count); + +// Clear the breakpoint and check that no stepping happens. +Debug.clearBreakPoint(bp); +prepare_step_test(); +f(); +assertEquals(0, step_count); + +// Get rid of the debug event listener. +Debug.setListener(null); diff --git a/test/mjsunit/debug-stepout-scope.js b/test/mjsunit/debug-stepout-scope.js new file mode 100644 index 00000000..9c040da9 --- /dev/null +++ b/test/mjsunit/debug-stepout-scope.js @@ -0,0 +1,423 @@ +// Copyright 2011 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. + +// Flags: --expose-debug-as debug --expose-natives-as=builtins + +// Check that the ScopeIterator can properly recreate the scope at +// every point when stepping through functions. + +var Debug = debug.Debug; + +function listener(event, exec_state, event_data, data) { + if (event == Debug.DebugEvent.Break) { + // Access scope details. + var scope_count = exec_state.frame().scopeCount(); + for (var i = 0; i < scope_count; i++) { + var scope = exec_state.frame().scope(i); + // assertTrue(scope.isScope()); + scope.scopeType(); + scope.scopeObject(); + } + + // Do steps until we reach the global scope again. + if (true) { + exec_state.prepareStep(Debug.StepAction.StepInMin, 1); + } + } +} + +Debug.setListener(listener); + + +function test1() { + debugger; + with ({x:1}) { + x = 2; + } +} +test1(); + + +function test2() { + if (true) { + with ({}) { + debugger; + } + } else { + with ({}) { + return 10; + } + } +} +test2(); + + +function test3() { + if (true) { + debugger; + } else { + with ({}) { + return 10; + } + } +} +test3(); + + +function test4() { + debugger; + with ({x:1}) x = 1 +} +test4(); + + +function test5() { + debugger; + var dummy = 1; + with ({}) { + with ({}) { + dummy = 2; + } + } + dummy = 3; +} +test5(); + + +function test6() { + debugger; + try { + throw 'stuff'; + } catch (e) { + e = 1; + } +} +test6(); + + +function test7() { + debugger; + function foo() {} +} +test7(); + + +function test8() { + debugger; + (function foo() {})(); +} +test8(); + + +var q = 42; +var prefixes = [ "debugger; ", + "if (false) { try { throw 0; } catch(x) { return x; } }; debugger; " ]; +var bodies = [ "1", + "1 ", + "1;", + "1; ", + "q", + "q ", + "q;", + "q; ", + "try { throw 'stuff' } catch (e) { e = 1; }", + "try { throw 'stuff' } catch (e) { e = 1; } ", + "try { throw 'stuff' } catch (e) { e = 1; };", + "try { throw 'stuff' } catch (e) { e = 1; }; " ]; +var with_bodies = [ "with ({}) {}", + "with ({x:1}) x", + "with ({x:1}) x = 1", + "with ({x:1}) x ", + "with ({x:1}) x = 1 ", + "with ({x:1}) x;", + "with ({x:1}) x = 1;", + "with ({x:1}) x; ", + "with ({x:1}) x = 1; " ]; + + +function test9() { + debugger; + for (var i = 0; i < prefixes.length; ++i) { + var pre = prefixes[i]; + for (var j = 0; j < bodies.length; ++j) { + var body = bodies[j]; + eval(pre + body); + eval("'use strict'; " + pre + body); + } + for (var j = 0; j < with_bodies.length; ++j) { + var body = with_bodies[j]; + eval(pre + body); + } + } +} +test9(); + + +function test10() { + debugger; + with ({}) { + return 10; + } +} +test10(); + + +function test11() { + debugger; + try { + throw 'stuff'; + } catch (e) { + return 10; + } +} +test11(); + + +// Test global eval and function constructor. +for (var i = 0; i < prefixes.length; ++i) { + var pre = prefixes[i]; + for (var j = 0; j < bodies.length; ++j) { + var body = bodies[j]; + eval(pre + body); + eval("'use strict'; " + pre + body); + Function(pre + body)(); + } + for (var j = 0; j < with_bodies.length; ++j) { + var body = with_bodies[j]; + eval(pre + body); + Function(pre + body)(); + } +} + + +try { + with({}) { + debugger; + eval("{}$%:^"); + } +} catch(e) { + nop(); +} + +// Return from function constructed with Function constructor. +var anon = 12; +for (var i = 0; i < prefixes.length; ++i) { + var pre = prefixes[i]; + Function(pre + "return 42")(); + Function(pre + "return 42 ")(); + Function(pre + "return 42;")(); + Function(pre + "return 42; ")(); + Function(pre + "return anon")(); + Function(pre + "return anon ")(); + Function(pre + "return anon;")(); + Function(pre + "return anon; ")(); +} + + +function nop() {} + + +function stress() { + debugger; + + L: with ({x:12}) { + break L; + } + + + with ({x: 'outer'}) { + label: { + with ({x: 'inner'}) { + break label; + } + } + } + + + with ({x: 'outer'}) { + label: { + with ({x: 'inner'}) { + break label; + } + } + nop(); + } + + + with ({x: 'outer'}) { + label: { + with ({x: 'middle'}) { + with ({x: 'inner'}) { + break label; + } + } + } + } + + + with ({x: 'outer'}) { + label: { + with ({x: 'middle'}) { + with ({x: 'inner'}) { + break label; + } + } + } + nop(); + } + + + with ({x: 'outer'}) { + for (var i = 0; i < 3; ++i) { + with ({x: 'inner' + i}) { + continue; + } + } + } + + + with ({x: 'outer'}) { + label: for (var i = 0; i < 3; ++i) { + with ({x: 'middle' + i}) { + for (var j = 0; j < 3; ++j) { + with ({x: 'inner' + j}) { + continue label; + } + } + } + } + } + + + with ({x: 'outer'}) { + try { + with ({x: 'inner'}) { + throw 0; + } + } catch (e) { + } + } + + + with ({x: 'outer'}) { + try { + with ({x: 'inner'}) { + throw 0; + } + } catch (e) { + nop(); + } + } + + + with ({x: 'outer'}) { + try { + with ({x: 'middle'}) { + with ({x: 'inner'}) { + throw 0; + } + } + } catch (e) { + } + } + + + try { + with ({x: 'outer'}) { + try { + with ({x: 'inner'}) { + throw 0; + } + } finally { + } + } + } catch (e) { + } + + + try { + with ({x: 'outer'}) { + try { + with ({x: 'inner'}) { + throw 0; + } + } finally { + nop(); + } + } + } catch (e) { + } + + + function stress1() { + with ({x:12}) { + return x; + } + } + stress1(); + + + function stress2() { + with ({x: 'outer'}) { + with ({x: 'inner'}) { + return x; + } + } + } + stress2(); + + function stress3() { + try { + with ({x: 'inner'}) { + throw 0; + } + } catch (e) { + return e; + } + } + stress3(); + + + function stress4() { + try { + with ({x: 'inner'}) { + throw 0; + } + } catch (e) { + with ({x: 'inner'}) { + return e; + } + } + } + stress4(); + +} +stress(); + + +// With block as the last(!) statement in global code. +with ({}) { debugger; }
\ No newline at end of file diff --git a/test/mjsunit/element-kind.js b/test/mjsunit/element-kind.js deleted file mode 100644 index 48a029f2..00000000 --- a/test/mjsunit/element-kind.js +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2011 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. - -// Flags: --allow-natives-syntax -// Test element kind of objects - -var element_kind = { - fast_elements : 1, - fast_double_elements : 2, - dictionary_elements : 3, - external_byte_elements : 4, - external_unsigned_byte_elements : 5, - external_short_elements : 6, - external_unsigned_short_elements : 7, - external_int_elements : 8, - external_unsigned_int_elements : 9, - external_float_elements : 10, - external_double_elements : 11, - external_pixel_elements : 12 -} - -// We expect an object to only be of one element kind. -function assertKind(expected, obj){ - assertEquals(expected == element_kind.fast_elements, - %HasFastElements(obj)); - assertEquals(expected == element_kind.fast_double_elements, - %HasFastDoubleElements(obj)); - assertEquals(expected == element_kind.dictionary_elements, - %HasDictionaryElements(obj)); - assertEquals(expected == element_kind.external_byte_elements, - %HasExternalByteElements(obj)); - assertEquals(expected == element_kind.external_unsigned_byte_elements, - %HasExternalUnsignedByteElements(obj)); - assertEquals(expected == element_kind.external_short_elements, - %HasExternalShortElements(obj)); - assertEquals(expected == element_kind.external_unsigned_short_elements, - %HasExternalUnsignedShortElements(obj)); - assertEquals(expected == element_kind.external_int_elements, - %HasExternalIntElements(obj)); - assertEquals(expected == element_kind.external_unsigned_int_elements, - %HasExternalUnsignedIntElements(obj)); - assertEquals(expected == element_kind.external_float_elements, - %HasExternalFloatElements(obj)); - assertEquals(expected == element_kind.external_double_elements, - %HasExternalDoubleElements(obj)); - assertEquals(expected == element_kind.external_pixel_elements, - %HasExternalPixelElements(obj)); - // every external kind is also an external array - assertEquals(expected >= element_kind.external_byte_elements, - %HasExternalArrayElements(obj)); -} - -var me = {}; -assertKind(element_kind.fast_elements, me); -me.dance = 0xD15C0; -me.drink = 0xC0C0A; -assertKind(element_kind.fast_elements, me); - -var you = new Array(); -for(i = 0; i < 1337; i++) { - you[i] = i; -} -assertKind(element_kind.fast_elements, you); - -assertKind(element_kind.dictionary_elements, new Array(0xC0C0A)); - -// fast_double_elements not yet available - - -assertKind(element_kind.external_byte_elements, new Int8Array(9001)); -assertKind(element_kind.external_unsigned_byte_elements, new Uint8Array(007)); -assertKind(element_kind.external_short_elements, new Int16Array(666)); -assertKind(element_kind.external_unsigned_short_elements, new Uint16Array(42)); -assertKind(element_kind.external_int_elements, new Int32Array(0xF)); -assertKind(element_kind.external_unsigned_int_elements, new Uint32Array(23)); -assertKind(element_kind.external_float_elements, new Float32Array(7)); -assertKind(element_kind.external_double_elements, new Float64Array(0)); -assertKind(element_kind.external_pixel_elements, new PixelArray(512)); diff --git a/test/mjsunit/elements-kind-depends.js b/test/mjsunit/elements-kind-depends.js new file mode 100644 index 00000000..82f188b7 --- /dev/null +++ b/test/mjsunit/elements-kind-depends.js @@ -0,0 +1,74 @@ +// Copyright 2011 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. + +// Flags: --allow-natives-syntax --smi-only-arrays + +function burn() { + var a = new Array(3); + a[0] = 10; + a[1] = 15.5; + a[2] = 20; + return a; +} + +function check(a) { + assertEquals(10, a[0]); + assertEquals(15.5, a[1]); + assertEquals(20, a[2]); +} + +var b; +for (var i = 0; i < 3; ++i) { + b = burn(); + check(b); // all OK +} +%OptimizeFunctionOnNextCall(burn); +b = burn(); +check(b); // fails + + +function loop_test(x) { + for (i=0;i<3;i++) { + x[i] = (i+1) * 0.5; + } +} + +function check2(b) { + assertEquals(0.5, b[0]); + assertEquals(1.0, b[1]); + assertEquals(1.5, b[2]); +} + +for (var i = 0; i < 3; ++i) { + b = [0,1,2]; + loop_test(b); + check2(b); +} +%OptimizeFunctionOnNextCall(loop_test); +b = [0,1,2]; +loop_test(b); +check2(b); diff --git a/test/mjsunit/elements-kind.js b/test/mjsunit/elements-kind.js new file mode 100644 index 00000000..8a8a3c74 --- /dev/null +++ b/test/mjsunit/elements-kind.js @@ -0,0 +1,340 @@ +// Copyright 2011 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. + +// Flags: --allow-natives-syntax --smi-only-arrays --expose-gc + +// Test element kind of objects. +// Since --smi-only-arrays affects builtins, its default setting at compile +// time sticks if built with snapshot. If --smi-only-arrays is deactivated +// by default, only a no-snapshot build actually has smi-only arrays enabled +// in this test case. Depending on whether smi-only arrays are actually +// enabled, this test takes the appropriate code path to check smi-only arrays. + +support_smi_only_arrays = %HasFastSmiOnlyElements([]); + +if (support_smi_only_arrays) { + print("Tests include smi-only arrays."); +} else { + print("Tests do NOT include smi-only arrays."); +} + +var elements_kind = { + fast_smi_only : 'fast smi only elements', + fast : 'fast elements', + fast_double : 'fast double elements', + dictionary : 'dictionary elements', + external_byte : 'external byte elements', + external_unsigned_byte : 'external unsigned byte elements', + external_short : 'external short elements', + external_unsigned_short : 'external unsigned short elements', + external_int : 'external int elements', + external_unsigned_int : 'external unsigned int elements', + external_float : 'external float elements', + external_double : 'external double elements', + external_pixel : 'external pixel elements' +} + +function getKind(obj) { + if (%HasFastSmiOnlyElements(obj)) return elements_kind.fast_smi_only; + if (%HasFastElements(obj)) return elements_kind.fast; + if (%HasFastDoubleElements(obj)) return elements_kind.fast_double; + if (%HasDictionaryElements(obj)) return elements_kind.dictionary; + // Every external kind is also an external array. + assertTrue(%HasExternalArrayElements(obj)); + if (%HasExternalByteElements(obj)) { + return elements_kind.external_byte; + } + if (%HasExternalUnsignedByteElements(obj)) { + return elements_kind.external_unsigned_byte; + } + if (%HasExternalShortElements(obj)) { + return elements_kind.external_short; + } + if (%HasExternalUnsignedShortElements(obj)) { + return elements_kind.external_unsigned_short; + } + if (%HasExternalIntElements(obj)) { + return elements_kind.external_int; + } + if (%HasExternalUnsignedIntElements(obj)) { + return elements_kind.external_unsigned_int; + } + if (%HasExternalFloatElements(obj)) { + return elements_kind.external_float; + } + if (%HasExternalDoubleElements(obj)) { + return elements_kind.external_double; + } + if (%HasExternalPixelElements(obj)) { + return elements_kind.external_pixel; + } +} + +function assertKind(expected, obj, name_opt) { + if (!support_smi_only_arrays && + expected == elements_kind.fast_smi_only) { + expected = elements_kind.fast; + } + assertEquals(expected, getKind(obj), name_opt); +} + +var me = {}; +assertKind(elements_kind.fast, me); +me.dance = 0xD15C0; +me.drink = 0xC0C0A; +assertKind(elements_kind.fast, me); + +var too = [1,2,3]; +assertKind(elements_kind.fast_smi_only, too); +too.dance = 0xD15C0; +too.drink = 0xC0C0A; +assertKind(elements_kind.fast_smi_only, too); + +// Make sure the element kind transitions from smionly when a non-smi is stored. +var you = new Array(); +assertKind(elements_kind.fast_smi_only, you); +for (var i = 0; i < 1337; i++) { + var val = i; + if (i == 1336) { + assertKind(elements_kind.fast_smi_only, you); + val = new Object(); + } + you[i] = val; +} +assertKind(elements_kind.fast, you); + +assertKind(elements_kind.dictionary, new Array(0xDECAF)); + +var fast_double_array = new Array(0xDECAF); +for (var i = 0; i < 0xDECAF; i++) fast_double_array[i] = i / 2; +assertKind(elements_kind.fast_double, fast_double_array); + +assertKind(elements_kind.external_byte, new Int8Array(9001)); +assertKind(elements_kind.external_unsigned_byte, new Uint8Array(007)); +assertKind(elements_kind.external_short, new Int16Array(666)); +assertKind(elements_kind.external_unsigned_short, new Uint16Array(42)); +assertKind(elements_kind.external_int, new Int32Array(0xF)); +assertKind(elements_kind.external_unsigned_int, new Uint32Array(23)); +assertKind(elements_kind.external_float, new Float32Array(7)); +assertKind(elements_kind.external_double, new Float64Array(0)); +assertKind(elements_kind.external_pixel, new PixelArray(512)); + +// Crankshaft support for smi-only array elements. +function monomorphic(array) { + for (var i = 0; i < 3; i++) { + array[i] = i + 10; + } + assertKind(elements_kind.fast_smi_only, array); + for (var i = 0; i < 3; i++) { + var a = array[i]; + assertEquals(i + 10, a); + } +} +var smi_only = [1, 2, 3]; +for (var i = 0; i < 3; i++) monomorphic(smi_only); +%OptimizeFunctionOnNextCall(monomorphic); +monomorphic(smi_only); + +if (support_smi_only_arrays) { + function construct_smis() { + var a = [0, 0, 0]; + a[0] = 0; // Send the COW array map to the steak house. + assertKind(elements_kind.fast_smi_only, a); + return a; + } + function construct_doubles() { + var a = construct_smis(); + a[0] = 1.5; + assertKind(elements_kind.fast_double, a); + return a; + } + function construct_objects() { + var a = construct_smis(); + a[0] = "one"; + assertKind(elements_kind.fast, a); + return a; + } + + // Test crankshafted transition SMI->DOUBLE. + function convert_to_double(array) { + array[1] = 2.5; + assertKind(elements_kind.fast_double, array); + assertEquals(2.5, array[1]); + } + var smis = construct_smis(); + for (var i = 0; i < 3; i++) convert_to_double(smis); + %OptimizeFunctionOnNextCall(convert_to_double); + smis = construct_smis(); + convert_to_double(smis); + // Test crankshafted transitions SMI->FAST and DOUBLE->FAST. + function convert_to_fast(array) { + array[1] = "two"; + assertKind(elements_kind.fast, array); + assertEquals("two", array[1]); + } + smis = construct_smis(); + for (var i = 0; i < 3; i++) convert_to_fast(smis); + var doubles = construct_doubles(); + for (var i = 0; i < 3; i++) convert_to_fast(doubles); + smis = construct_smis(); + doubles = construct_doubles(); + %OptimizeFunctionOnNextCall(convert_to_fast); + convert_to_fast(smis); + convert_to_fast(doubles); + // Test transition chain SMI->DOUBLE->FAST (crankshafted function will + // transition to FAST directly). + function convert_mixed(array, value, kind) { + array[1] = value; + assertKind(kind, array); + assertEquals(value, array[1]); + } + smis = construct_smis(); + for (var i = 0; i < 3; i++) { + convert_mixed(smis, 1.5, elements_kind.fast_double); + } + doubles = construct_doubles(); + for (var i = 0; i < 3; i++) { + convert_mixed(doubles, "three", elements_kind.fast); + } + smis = construct_smis(); + doubles = construct_doubles(); + %OptimizeFunctionOnNextCall(convert_mixed); + convert_mixed(smis, 1, elements_kind.fast); + convert_mixed(doubles, 1, elements_kind.fast); + assertTrue(%HaveSameMap(smis, doubles)); +} + +// Crankshaft support for smi-only elements in dynamic array literals. +function get(foo) { return foo; } // Used to generate dynamic values. + +function crankshaft_test() { + var a = [get(1), get(2), get(3)]; + assertKind(elements_kind.fast_smi_only, a); + var b = [get(1), get(2), get("three")]; + assertKind(elements_kind.fast, b); + var c = [get(1), get(2), get(3.5)]; + if (support_smi_only_arrays) { + assertKind(elements_kind.fast_double, c); + } else { + assertKind(elements_kind.fast, c); + } +} +for (var i = 0; i < 3; i++) { + crankshaft_test(); +} +%OptimizeFunctionOnNextCall(crankshaft_test); +crankshaft_test(); + +// Elements_kind transitions for arrays. + +// A map can have three different elements_kind transitions: SMI->DOUBLE, +// DOUBLE->OBJECT, and SMI->OBJECT. No matter in which order these three are +// created, they must always end up with the same FAST map. + +// This test is meaningless without FAST_SMI_ONLY_ELEMENTS. +if (support_smi_only_arrays) { + // Preparation: create one pair of identical objects for each case. + var a = [1, 2, 3]; + var b = [1, 2, 3]; + assertTrue(%HaveSameMap(a, b)); + assertKind(elements_kind.fast_smi_only, a); + var c = [1, 2, 3]; + c["case2"] = true; + var d = [1, 2, 3]; + d["case2"] = true; + assertTrue(%HaveSameMap(c, d)); + assertFalse(%HaveSameMap(a, c)); + assertKind(elements_kind.fast_smi_only, c); + var e = [1, 2, 3]; + e["case3"] = true; + var f = [1, 2, 3]; + f["case3"] = true; + assertTrue(%HaveSameMap(e, f)); + assertFalse(%HaveSameMap(a, e)); + assertFalse(%HaveSameMap(c, e)); + assertKind(elements_kind.fast_smi_only, e); + // Case 1: SMI->DOUBLE, DOUBLE->OBJECT, SMI->OBJECT. + a[0] = 1.5; + assertKind(elements_kind.fast_double, a); + a[0] = "foo"; + assertKind(elements_kind.fast, a); + b[0] = "bar"; + assertTrue(%HaveSameMap(a, b)); + // Case 2: SMI->DOUBLE, SMI->OBJECT, DOUBLE->OBJECT. + c[0] = 1.5; + assertKind(elements_kind.fast_double, c); + assertFalse(%HaveSameMap(c, d)); + d[0] = "foo"; + assertKind(elements_kind.fast, d); + assertFalse(%HaveSameMap(c, d)); + c[0] = "bar"; + assertTrue(%HaveSameMap(c, d)); + // Case 3: SMI->OBJECT, SMI->DOUBLE, DOUBLE->OBJECT. + e[0] = "foo"; + assertKind(elements_kind.fast, e); + assertFalse(%HaveSameMap(e, f)); + f[0] = 1.5; + assertKind(elements_kind.fast_double, f); + assertFalse(%HaveSameMap(e, f)); + f[0] = "bar"; + assertKind(elements_kind.fast, f); + assertTrue(%HaveSameMap(e, f)); +} + +// Test if Array.concat() works correctly with DOUBLE elements. +if (support_smi_only_arrays) { + var a = [1, 2]; + assertKind(elements_kind.fast_smi_only, a); + var b = [4.5, 5.5]; + assertKind(elements_kind.fast_double, b); + var c = a.concat(b); + assertEquals([1, 2, 4.5, 5.5], c); + // TODO(1810): Change implementation so that we get DOUBLE elements here? + assertKind(elements_kind.fast, c); +} + +// Test that Array.push() correctly handles SMI elements. +if (support_smi_only_arrays) { + var a = [1, 2]; + assertKind(elements_kind.fast_smi_only, a); + a.push(3, 4, 5); + assertKind(elements_kind.fast_smi_only, a); + assertEquals([1, 2, 3, 4, 5], a); +} + +// Test that Array.splice() and Array.slice() return correct ElementsKinds. +if (support_smi_only_arrays) { + var a = ["foo", "bar"]; + assertKind(elements_kind.fast, a); + var b = a.splice(0, 1); + assertKind(elements_kind.fast, b); + var c = a.slice(0, 1); + assertKind(elements_kind.fast, c); +} + +// Throw away type information in the ICs for next stress run. +gc(); diff --git a/test/mjsunit/elements-transition.js b/test/mjsunit/elements-transition.js new file mode 100644 index 00000000..5f6cc4fa --- /dev/null +++ b/test/mjsunit/elements-transition.js @@ -0,0 +1,107 @@ +// Copyright 2011 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. + +// Flags: --allow-natives-syntax --smi-only-arrays + +support_smi_only_arrays = %HasFastSmiOnlyElements([]); + +if (support_smi_only_arrays) { + function test(test_double, test_object, set, length) { + // We apply the same operations to two identical arrays. The first array + // triggers an IC miss, upon which the conversion stub is generated, but the + // actual conversion is done in runtime. The second array, arriving at + // the previously patched IC, is then converted using the conversion stub. + var array_1 = new Array(length); + var array_2 = new Array(length); + + assertTrue(%HasFastSmiOnlyElements(array_1)); + assertTrue(%HasFastSmiOnlyElements(array_2)); + for (var i = 0; i < length; i++) { + if (i == length - 5 && test_double) { + // Trigger conversion to fast double elements at length-5. + set(array_1, i, 0.5); + set(array_2, i, 0.5); + assertTrue(%HasFastDoubleElements(array_1)); + assertTrue(%HasFastDoubleElements(array_2)); + } else if (i == length - 3 && test_object) { + // Trigger conversion to fast object elements at length-3. + set(array_1, i, 'object'); + set(array_2, i, 'object'); + assertTrue(%HasFastElements(array_1)); + assertTrue(%HasFastElements(array_2)); + } else if (i != length - 7) { + // Set the element to an integer but leave a hole at length-7. + set(array_1, i, 2*i+1); + set(array_2, i, 2*i+1); + } + } + + for (var i = 0; i < length; i++) { + if (i == length - 5 && test_double) { + assertEquals(0.5, array_1[i]); + assertEquals(0.5, array_2[i]); + } else if (i == length - 3 && test_object) { + assertEquals('object', array_1[i]); + assertEquals('object', array_2[i]); + } else if (i != length - 7) { + assertEquals(2*i+1, array_1[i]); + assertEquals(2*i+1, array_2[i]); + } else { + assertEquals(undefined, array_1[i]); + assertEquals(undefined, array_2[i]); + } + } + + assertEquals(length, array_1.length); + assertEquals(length, array_2.length); + } + + test(false, false, function(a,i,v){ a[i] = v; }, 20); + test(true, false, function(a,i,v){ a[i] = v; }, 20); + test(false, true, function(a,i,v){ a[i] = v; }, 20); + test(true, true, function(a,i,v){ a[i] = v; }, 20); + + test(false, false, function(a,i,v){ a[i] = v; }, 10000); + test(true, false, function(a,i,v){ a[i] = v; }, 10000); + test(false, true, function(a,i,v){ a[i] = v; }, 10000); + test(true, true, function(a,i,v){ a[i] = v; }, 10000); + + // Check COW arrays + function get_cow() { return [1, 2, 3]; } + + function transition(x) { x[0] = 1.5; } + + var ignore = get_cow(); + transition(ignore); // Handled by runtime. + var a = get_cow(); + var b = get_cow(); + transition(a); // Handled by IC. + assertEquals(1.5, a[0]); + assertEquals(1, b[0]); +} else { + print("Test skipped because smi only arrays are not supported."); +}
\ No newline at end of file diff --git a/test/mjsunit/error-tostring.js b/test/mjsunit/error-tostring.js new file mode 100644 index 00000000..a2856414 --- /dev/null +++ b/test/mjsunit/error-tostring.js @@ -0,0 +1,85 @@ +// Copyright 2011 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. + + +// Test default string representation of an Error object. + +var e = new Error(); +assertEquals('Error', e.toString()); + + +// Test printing of cyclic errors which return the empty string for +// compatibility with Safari and Firefox. + +e = new Error(); +e.name = e; +e.message = e; +e.stack = "Does not occur in output"; +e.arguments = "Does not occur in output"; +e.type = "Does not occur in output"; +assertEquals('', e.toString()); + +e = new Error(); +e.name = [ e ]; +e.message = [ e ]; +e.stack = "Does not occur in output"; +e.arguments = "Does not occur in output"; +e.type = "Does not occur in output"; +assertEquals('', e.toString()); + + +// Test the sequence in which getters and toString operations are called +// on a given Error object. Verify the produced string representation. + +function testErrorToString(nameValue, messageValue) { + var seq = []; + var e = { + get name() { + seq.push(1); + return (nameValue === undefined) ? nameValue : { + toString: function() { seq.push(2); return nameValue; } + }; + }, + get message() { + seq.push(3); + return (messageValue === undefined) ? messageValue : { + toString: function() { seq.push(4); return messageValue; } + }; + } + }; + var string = Error.prototype.toString.call(e); + return [string,seq]; +} + +assertEquals(["Error",[1,3]], testErrorToString(undefined, undefined)); +assertEquals(["e1",[1,2,3]], testErrorToString("e1", undefined)); +assertEquals(["e1: null",[1,2,3,4]], testErrorToString("e1", null)); +assertEquals(["e1",[1,2,3,4]], testErrorToString("e1", "")); +assertEquals(["Error: e2",[1,3,4]], testErrorToString(undefined, "e2")); +assertEquals(["null: e2",[1,2,3,4]], testErrorToString(null, "e2")); +assertEquals(["e2",[1,2,3,4]], testErrorToString("", "e2")); +assertEquals(["e1: e2",[1,2,3,4]], testErrorToString("e1", "e2")); diff --git a/test/mjsunit/eval.js b/test/mjsunit/eval.js index b6284ba9..100f2165 100644 --- a/test/mjsunit/eval.js +++ b/test/mjsunit/eval.js @@ -39,7 +39,7 @@ assertEquals(1, count); try { eval('hest 7 &*^*&^'); - assertTrue(false, 'Did not throw on syntax error.'); + assertUnreachable('Did not throw on syntax error.'); } catch (e) { assertEquals('SyntaxError', e.name); } @@ -108,6 +108,7 @@ foo = 0; result = (function() { var foo = 2; + // Should be non-direct call. return x.eval('foo'); })(); assertEquals(0, result); @@ -115,12 +116,33 @@ assertEquals(0, result); foo = 0; result = (function() { + var foo = 2; + // Should be non-direct call. + return (1,eval)('foo'); + })(); +assertEquals(0, result); + +foo = 0; +result = + (function() { var eval = function(x) { return x; }; var foo = eval(2); + // Should be non-direct call. return e('foo'); })(); assertEquals(0, result); +foo = 0; +result = + (function() { + var foo = 2; + // Should be direct call. + with ({ eval : e }) { + return eval('foo'); + } + })(); +assertEquals(2, result); + result = (function() { var eval = function(x) { return 2 * x; }; @@ -135,19 +157,17 @@ result = })(); assertEquals(this, result); -result = - (function() { - var obj = { f: function(eval) { return eval("this"); } }; - return obj.f(eval); - })(); -assertEquals(this, result); +(function() { + var obj = { f: function(eval) { return eval("this"); } }; + result = obj.f(eval); + assertEquals(obj, result); +})(); -result = - (function() { - var obj = { f: function(eval) { arguments; return eval("this"); } }; - return obj.f(eval); - })(); -assertEquals(this, result); +(function() { + var obj = { f: function(eval) { arguments; return eval("this"); } }; + result = obj.f(eval); + assertEquals(obj, result); +})(); eval = function(x) { return 2 * x; }; result = @@ -156,6 +176,9 @@ result = })(); assertEquals(4, result); + + + // Regression test: calling a function named eval found in a context that is // not the global context should get the global object as receiver. result = diff --git a/test/mjsunit/function-bind.js b/test/mjsunit/function-bind.js index e9d02213..4a8f2d2a 100644 --- a/test/mjsunit/function-bind.js +++ b/test/mjsunit/function-bind.js @@ -29,29 +29,31 @@ // Simple tests. function foo(x, y, z) { - return x + y + z; + return [this, arguments.length, x]; } +assertEquals(3, foo.length); + var f = foo.bind(foo); -assertEquals(3, f(1, 1, 1)); +assertEquals([foo, 3, 1], f(1, 2, 3)); assertEquals(3, f.length); -f = foo.bind(foo, 2); -assertEquals(4, f(1, 1)); +f = foo.bind(foo, 1); +assertEquals([foo, 3, 1], f(2, 3)); assertEquals(2, f.length); -f = foo.bind(foo, 2, 2); -assertEquals(5, f(1)); +f = foo.bind(foo, 1, 2); +assertEquals([foo, 3, 1], f(3)); assertEquals(1, f.length); -f = foo.bind(foo, 2, 2, 2); -assertEquals(6, f()); +f = foo.bind(foo, 1, 2, 3); +assertEquals([foo, 3, 1], f()); assertEquals(0, f.length); // Test that length works correctly even if more than the actual number // of arguments are given when binding. f = foo.bind(foo, 1, 2, 3, 4, 5, 6, 7, 8, 9); -assertEquals(6, f()); +assertEquals([foo, 9, 1], f()); assertEquals(0, f.length); // Use a different bound object. @@ -78,64 +80,97 @@ assertEquals(0, f.length); // When only giving the thisArg, any number of binds should have // the same effect. f = foo.bind(foo); -assertEquals(3, f(1, 1, 1)); -f = foo.bind(foo).bind(foo).bind(foo).bind(foo); -assertEquals(3, f(1, 1, 1)); +assertEquals([foo, 3, 1], f(1, 2, 3)); + +var not_foo = {}; +f = foo.bind(foo).bind(not_foo).bind(not_foo).bind(not_foo); +assertEquals([foo, 3, 1], f(1, 2, 3)); assertEquals(3, f.length); // Giving bound parameters should work at any place in the chain. -f = foo.bind(foo, 1).bind(foo).bind(foo).bind(foo); -assertEquals(3, f(1, 1)); +f = foo.bind(foo, 1).bind(not_foo).bind(not_foo).bind(not_foo); +assertEquals([foo, 3, 1], f(2, 3)); assertEquals(2, f.length); -f = foo.bind(foo).bind(foo, 1).bind(foo).bind(foo); -assertEquals(3, f(1, 1)); +f = foo.bind(foo).bind(not_foo, 1).bind(not_foo).bind(not_foo); +assertEquals([foo, 3, 1], f(2, 3)); assertEquals(2, f.length); -f = foo.bind(foo).bind(foo).bind(foo,1 ).bind(foo); -assertEquals(3, f(1, 1)); +f = foo.bind(foo).bind(not_foo).bind(not_foo,1 ).bind(not_foo); +assertEquals([foo, 3, 1], f(2, 3)); assertEquals(2, f.length); -f = foo.bind(foo).bind(foo).bind(foo).bind(foo, 1); -assertEquals(3, f(1, 1)); +f = foo.bind(foo).bind(not_foo).bind(not_foo).bind(not_foo, 1); +assertEquals([foo, 3, 1], f(2, 3)); assertEquals(2, f.length); -// Several parameters can be given, and given in different bind invokations. -f = foo.bind(foo, 1, 1).bind(foo).bind(foo).bind(foo); -assertEquals(3, f(1)); +// Several parameters can be given, and given in different bind invocations. +f = foo.bind(foo, 1, 2).bind(not_foo).bind(not_foo).bind(not_foo); +assertEquals([foo, 3, 1], f(3)); +assertEquals(1, f.length); + +f = foo.bind(foo).bind(not_foo, 1, 2).bind(not_foo).bind(not_foo); +assertEquals([foo, 3, 1], f(1)); assertEquals(1, f.length); -f = foo.bind(foo).bind(foo, 1, 1).bind(foo).bind(foo); -assertEquals(3, f(1)); +f = foo.bind(foo).bind(not_foo, 1, 2).bind(not_foo).bind(not_foo); +assertEquals([foo, 3, 1], f(3)); assertEquals(1, f.length); -f = foo.bind(foo).bind(foo, 1, 1).bind(foo).bind(foo); -assertEquals(3, f(1)); +f = foo.bind(foo).bind(not_foo).bind(not_foo, 1, 2).bind(not_foo); +assertEquals([foo, 3, 1], f(1)); assertEquals(1, f.length); -f = foo.bind(foo).bind(foo).bind(foo, 1, 1).bind(foo); -assertEquals(3, f(1)); +f = foo.bind(foo).bind(not_foo).bind(not_foo).bind(not_foo, 1, 2); +assertEquals([foo, 3, 1], f(3)); assertEquals(1, f.length); -f = foo.bind(foo).bind(foo).bind(foo).bind(foo, 1, 1); -assertEquals(3, f(1)); +f = foo.bind(foo, 1).bind(not_foo, 2).bind(not_foo).bind(not_foo); +assertEquals([foo, 3, 1], f(3)); assertEquals(1, f.length); -f = foo.bind(foo, 1).bind(foo, 1).bind(foo).bind(foo); -assertEquals(3, f(1)); +f = foo.bind(foo, 1).bind(not_foo).bind(not_foo, 2).bind(not_foo); +assertEquals([foo, 3, 1], f(3)); assertEquals(1, f.length); -f = foo.bind(foo, 1).bind(foo).bind(foo, 1).bind(foo); -assertEquals(3, f(1)); +f = foo.bind(foo, 1).bind(not_foo).bind(not_foo).bind(not_foo, 2); +assertEquals([foo, 3, 1], f(3)); assertEquals(1, f.length); -f = foo.bind(foo, 1).bind(foo).bind(foo).bind(foo, 1); -assertEquals(3, f(1)); +f = foo.bind(foo).bind(not_foo, 1).bind(not_foo).bind(not_foo, 2); +assertEquals([foo, 3, 1], f(3)); assertEquals(1, f.length); -f = foo.bind(foo).bind(foo, 1).bind(foo).bind(foo, 1); -assertEquals(3, f(1)); +// The wrong number of arguments can be given to bound functions too. +f = foo.bind(foo); +assertEquals(3, f.length); +assertEquals([foo, 0, undefined], f()); +assertEquals([foo, 1, 1], f(1)); +assertEquals([foo, 2, 1], f(1, 2)); +assertEquals([foo, 3, 1], f(1, 2, 3)); +assertEquals([foo, 4, 1], f(1, 2, 3, 4)); + +f = foo.bind(foo, 1); +assertEquals(2, f.length); +assertEquals([foo, 1, 1], f()); +assertEquals([foo, 2, 1], f(2)); +assertEquals([foo, 3, 1], f(2, 3)); +assertEquals([foo, 4, 1], f(2, 3, 4)); + +f = foo.bind(foo, 1, 2); assertEquals(1, f.length); +assertEquals([foo, 2, 1], f()); +assertEquals([foo, 3, 1], f(3)); +assertEquals([foo, 4, 1], f(3, 4)); + +f = foo.bind(foo, 1, 2, 3); +assertEquals(0, f.length); +assertEquals([foo, 3, 1], f()); +assertEquals([foo, 4, 1], f(4)); + +f = foo.bind(foo, 1, 2, 3, 4); +assertEquals(0, f.length); +assertEquals([foo, 4, 1], f()); // Test constructor calls. @@ -171,13 +206,91 @@ assertEquals(3, obj2.z); // Test bind chains when used as a constructor. - f = bar.bind(bar, 1).bind(bar, 2).bind(bar, 3); obj2 = new f(); assertEquals(1, obj2.x); assertEquals(2, obj2.y); assertEquals(3, obj2.z); -// Test instanceof obj2 is bar, not f. +// Test obj2 is instanceof both bar and f. assertTrue(obj2 instanceof bar); -assertFalse(obj2 instanceof f); +assertTrue(obj2 instanceof f); + +// This-args are not relevant to instanceof. +f = bar.bind(foo.prototype, 1). + bind(String.prototype, 2). + bind(Function.prototype, 3); +var obj3 = new f(); +assertTrue(obj3 instanceof bar); +assertTrue(obj3 instanceof f); +assertFalse(obj3 instanceof foo); +assertFalse(obj3 instanceof Function); +assertFalse(obj3 instanceof String); + +// thisArg is converted to object. +f = foo.bind(undefined); +assertEquals([this, 0, undefined], f()); + +f = foo.bind(null); +assertEquals([this, 0, undefined], f()); + +f = foo.bind(42); +assertEquals([Object(42), 0, undefined], f()); + +f = foo.bind("foo"); +assertEquals([Object("foo"), 0, undefined], f()); + +f = foo.bind(true); +assertEquals([Object(true), 0, undefined], f()); + +// Strict functions don't convert thisArg. +function soo(x, y, z) { + "use strict"; + return [this, arguments.length, x]; +} + +var s = soo.bind(undefined); +assertEquals([undefined, 0, undefined], s()); + +s = soo.bind(null); +assertEquals([null, 0, undefined], s()); + +s = soo.bind(42); +assertEquals([42, 0, undefined], s()); + +s = soo.bind("foo"); +assertEquals(["foo", 0, undefined], s()); + +s = soo.bind(true); +assertEquals([true, 0, undefined], s()); + +// Test that .arguments and .caller are poisoned according to the ES5 spec. + +// Check that property descriptors are correct (unconfigurable, unenumerable, +// and both get and set is the ThrowTypeError function). +var cdesc = Object.getOwnPropertyDescriptor(f, "caller"); +var adesc = Object.getOwnPropertyDescriptor(f, "arguments"); + +assertFalse(cdesc.enumerable); +assertFalse(cdesc.configurable); + +assertFalse(adesc.enumerable); +assertFalse(adesc.configurable); + +assertSame(cdesc.get, cdesc.set); +assertSame(cdesc.get, adesc.get); +assertSame(cdesc.get, adesc.set); + +assertTrue(cdesc.get instanceof Function); +assertEquals(0, cdesc.get.length); +assertThrows(cdesc.get, TypeError); + +assertThrows(function() { return f.caller; }, TypeError); +assertThrows(function() { f.caller = 42; }, TypeError); +assertThrows(function() { return f.arguments; }, TypeError); +assertThrows(function() { f.arguments = 42; }, TypeError); + +// Shouldn't throw. Accessing the functions caller must throw if +// the caller is strict and the callee isn't. A bound function is built-in, +// but not considered strict. +(function foo() { return foo.caller; }).bind()(); diff --git a/test/mjsunit/fuzz-natives.js b/test/mjsunit/fuzz-natives.js index ff6677e6..c4d18d04 100644 --- a/test/mjsunit/fuzz-natives.js +++ b/test/mjsunit/fuzz-natives.js @@ -163,6 +163,9 @@ var knownProblems = { "PromoteScheduledException": true, "DeleteHandleScopeExtensions": true, + // Vararg with minimum number > 0. + "Call": true, + // Requires integer arguments to be non-negative. "Apply": true, diff --git a/test/mjsunit/global-const-var-conflicts.js b/test/mjsunit/global-const-var-conflicts.js index d38d0ee8..2fca96f9 100644 --- a/test/mjsunit/global-const-var-conflicts.js +++ b/test/mjsunit/global-const-var-conflicts.js @@ -26,7 +26,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Check that dynamically introducing conflicting consts/vars -// leads to exceptions. +// is silently ignored (and does not lead to exceptions). var caught = 0; @@ -46,12 +46,12 @@ eval("var c"); try { eval("const c"); } catch (e) { caught++; assertTrue(e instanceof TypeError); } assertTrue(typeof c == 'undefined'); try { eval("const c = 1"); } catch (e) { caught++; assertTrue(e instanceof TypeError); } -assertTrue(typeof c == 'undefined'); +assertEquals(1, c); eval("var d = 0"); try { eval("const d"); } catch (e) { caught++; assertTrue(e instanceof TypeError); } -assertEquals(0, d); +assertEquals(undefined, d); try { eval("const d = 1"); } catch (e) { caught++; assertTrue(e instanceof TypeError); } -assertEquals(0, d); +assertEquals(1, d); -assertEquals(8, caught); +assertEquals(0, caught); diff --git a/test/mjsunit/harmony/block-conflicts.js b/test/mjsunit/harmony/block-conflicts.js index 8d3de6f9..ee2d9794 100644 --- a/test/mjsunit/harmony/block-conflicts.js +++ b/test/mjsunit/harmony/block-conflicts.js @@ -25,10 +25,13 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --harmony-block-scoping +// Flags: --harmony-scoping // Test for conflicting variable bindings. +// TODO(ES6): properly activate extended mode +"use strict"; + function CheckException(e) { var string = e.toString(); assertTrue(string.indexOf("has already been declared") >= 0 || @@ -80,6 +83,11 @@ var letbinds = [ "let x", "let x = function() {}", "let x, y", "let y, x", + "const x = 0", + "const x = undefined", + "const x = function() {}", + "const x = 2, y = 3", + "const y = 4, x = 5", ]; var varbinds = [ "var x", "var x = 0", diff --git a/test/mjsunit/harmony/block-early-errors.js b/test/mjsunit/harmony/block-early-errors.js new file mode 100644 index 00000000..791f001a --- /dev/null +++ b/test/mjsunit/harmony/block-early-errors.js @@ -0,0 +1,55 @@ +// Copyright 2011 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. + +// Flags: --harmony-scoping + +function CheckException(e) { + var string = e.toString(); + assertInstanceof(e, SyntaxError); + assertTrue(string.indexOf("Illegal let") >= 0); +} + +function Check(str) { + try { + eval("(function () { " + str + " })"); + assertUnreachable(); + } catch (e) { + CheckException(e); + } + try { + eval("(function () { { " + str + " } })"); + assertUnreachable(); + } catch (e) { + CheckException(e); + } +} + +// Check for early syntax errors when using let +// declarations outside of extended mode. +Check("let x;"); +Check("let x = 1;"); +Check("let x, y;"); diff --git a/test/mjsunit/harmony/block-for.js b/test/mjsunit/harmony/block-for.js new file mode 100644 index 00000000..e84f0d2f --- /dev/null +++ b/test/mjsunit/harmony/block-for.js @@ -0,0 +1,146 @@ +// Copyright 2011 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. + +// Flags: --harmony-scoping + +// TODO(ES6): properly activate extended mode +"use strict"; + +function props(x) { + var array = []; + for (let p in x) array.push(p); + return array.sort(); +} + +assertEquals(0, props({}).length); +assertEquals(1, props({x:1}).length); +assertEquals(2, props({x:1, y:2}).length); + +assertArrayEquals(["x"], props({x:1})); +assertArrayEquals(["x", "y"], props({x:1, y:2})); +assertArrayEquals(["x", "y", "zoom"], props({x:1, y:2, zoom:3})); + +assertEquals(0, props([]).length); +assertEquals(1, props([1]).length); +assertEquals(2, props([1,2]).length); + +assertArrayEquals(["0"], props([1])); +assertArrayEquals(["0", "1"], props([1,2])); +assertArrayEquals(["0", "1", "2"], props([1,2,3])); + +var o = {}; +var a = []; +let i = "outer_i"; +let s = "outer_s"; +for (let i = 0x0020; i < 0x01ff; i+=2) { + let s = 'char:' + String.fromCharCode(i); + a.push(s); + o[s] = i; +} +assertArrayEquals(a, props(o)); +assertEquals(i, "outer_i"); +assertEquals(s, "outer_s"); + +var a = []; +assertEquals(0, props(a).length); +a[Math.pow(2,30)-1] = 0; +assertEquals(1, props(a).length); +a[Math.pow(2,31)-1] = 0; +assertEquals(2, props(a).length); +a[1] = 0; +assertEquals(3, props(a).length); + +var result = ''; +for (let p in {a : [0], b : 1}) { result += p; } +assertEquals('ab', result); + +var result = ''; +for (let p in {a : {v:1}, b : 1}) { result += p; } +assertEquals('ab', result); + +var result = ''; +for (let p in { get a() {}, b : 1}) { result += p; } +assertEquals('ab', result); + +var result = ''; +for (let p in { get a() {}, set a(x) {}, b : 1}) { result += p; } +assertEquals('ab', result); + + +// Check that there is exactly one variable without initializer +// in a for-in statement with let variables. +// TODO(ES6): properly activate extended mode +assertThrows("function foo() { 'use strict'; for (let in {}) { } }", SyntaxError); +assertThrows("function foo() { 'use strict'; for (let x = 3 in {}) { } }", SyntaxError); +assertThrows("function foo() { 'use strict'; for (let x, y in {}) { } }", SyntaxError); +assertThrows("function foo() { 'use strict'; for (let x = 3, y in {}) { } }", SyntaxError); +assertThrows("function foo() { 'use strict'; for (let x, y = 4 in {}) { } }", SyntaxError); +assertThrows("function foo() { 'use strict'; for (let x = 3, y = 4 in {}) { } }", SyntaxError); + + +// In a normal for statement the iteration variable is not +// freshly allocated for each iteration. +function closures1() { + let a = []; + for (let i = 0; i < 5; ++i) { + a.push(function () { return i; }); + } + for (let j = 0; j < 5; ++j) { + assertEquals(5, a[j]()); + } +} +closures1(); + + +function closures2() { + let a = [], b = []; + for (let i = 0, j = 10; i < 5; ++i, ++j) { + a.push(function () { return i; }); + b.push(function () { return j; }); + } + for (let k = 0; k < 5; ++k) { + assertEquals(5, a[k]()); + assertEquals(15, b[k]()); + } +} +closures2(); + + +// In a for-in statement the iteration variable is fresh +// for earch iteration. +function closures3(x) { + let a = []; + for (let p in x) { + a.push(function () { return p; }); + } + let k = 0; + for (let q in x) { + assertEquals(q, a[k]()); + ++k; + } +} +closures3({a : [0], b : 1, c : {v : 1}, get d() {}, set e(x) {}}); diff --git a/test/mjsunit/harmony/block-leave.js b/test/mjsunit/harmony/block-leave.js index 73eaf294..a7f6b694 100644 --- a/test/mjsunit/harmony/block-leave.js +++ b/test/mjsunit/harmony/block-leave.js @@ -25,7 +25,10 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --harmony-block-scoping +// Flags: --harmony-scoping + +// TODO(ES6): properly activate extended mode +"use strict"; // We want to test the context chain shape. In each of the tests cases // below, the outer with is to force a runtime lookup of the identifier 'x' @@ -64,31 +67,30 @@ try { } catch (e) { caught = true; assertEquals(25, e); - with ({y:19}) { - assertEquals(19, y); + (function () { try { // NOTE: This checks that the block scope containing xx has been // removed from the context chain. - xx; + eval('xx'); assertTrue(false); // should not reach here } catch (e2) { assertTrue(e2 instanceof ReferenceError); } - } + })(); } assertTrue(caught); -with ({x: 'outer'}) { +(function(x) { label: { let x = 'inner'; break label; } - assertEquals('outer', x); -} + assertEquals('outer', eval('x')); +})('outer'); -with ({x: 'outer'}) { +(function(x) { label: { let x = 'middle'; { @@ -96,20 +98,20 @@ with ({x: 'outer'}) { break label; } } - assertEquals('outer', x); -} + assertEquals('outer', eval('x')); +})('outer'); -with ({x: 'outer'}) { +(function(x) { for (var i = 0; i < 10; ++i) { let x = 'inner' + i; continue; } - assertEquals('outer', x); -} + assertEquals('outer', eval('x')); +})('outer'); -with ({x: 'outer'}) { +(function(x) { label: for (var i = 0; i < 10; ++i) { let x = 'middle' + i; for (var j = 0; j < 10; ++j) { @@ -117,21 +119,21 @@ with ({x: 'outer'}) { continue label; } } - assertEquals('outer', x); -} + assertEquals('outer', eval('x')); +})('outer'); -with ({x: 'outer'}) { +(function(x) { try { let x = 'inner'; throw 0; } catch (e) { - assertEquals('outer', x); + assertEquals('outer', eval('x')); } -} +})('outer'); -with ({x: 'outer'}) { +(function(x) { try { let x = 'middle'; { @@ -139,27 +141,27 @@ with ({x: 'outer'}) { throw 0; } } catch (e) { - assertEquals('outer', x); + assertEquals('outer', eval('x')); } -} +})('outer'); try { - with ({x: 'outer'}) { + (function(x) { try { let x = 'inner'; throw 0; } finally { - assertEquals('outer', x); + assertEquals('outer', eval('x')); } - } + })('outer'); } catch (e) { if (e instanceof MjsUnitAssertionError) throw e; } try { - with ({x: 'outer'}) { + (function(x) { try { let x = 'middle'; { @@ -167,9 +169,9 @@ try { throw 0; } } finally { - assertEquals('outer', x); + assertEquals('outer', eval('x')); } - } + })('outer'); } catch (e) { if (e instanceof MjsUnitAssertionError) throw e; } @@ -179,47 +181,47 @@ try { // from with. function f() {} -with ({x: 'outer'}) { +(function(x) { label: { let x = 'inner'; break label; } f(); // The context could be restored from the stack after the call. - assertEquals('outer', x); -} + assertEquals('outer', eval('x')); +})('outer'); -with ({x: 'outer'}) { +(function(x) { for (var i = 0; i < 10; ++i) { let x = 'inner'; continue; } f(); - assertEquals('outer', x); -} + assertEquals('outer', eval('x')); +})('outer'); -with ({x: 'outer'}) { +(function(x) { try { let x = 'inner'; throw 0; } catch (e) { f(); - assertEquals('outer', x); + assertEquals('outer', eval('x')); } -} +})('outer'); try { - with ({x: 'outer'}) { + (function(x) { try { let x = 'inner'; throw 0; } finally { f(); - assertEquals('outer', x); + assertEquals('outer', eval('x')); } - } + })('outer'); } catch (e) { if (e instanceof MjsUnitAssertionError) throw e; } diff --git a/test/mjsunit/harmony/block-let-crankshaft.js b/test/mjsunit/harmony/block-let-crankshaft.js index c2fb96b6..ba5bc0d4 100644 --- a/test/mjsunit/harmony/block-let-crankshaft.js +++ b/test/mjsunit/harmony/block-let-crankshaft.js @@ -25,7 +25,10 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --harmony-block-scoping --allow-natives-syntax +// Flags: --harmony-scoping --allow-natives-syntax + +// TODO(ES6): properly activate extended mode +"use strict"; // Test that temporal dead zone semantics for function and block scoped // ket bindings are handled by the optimizing compiler. diff --git a/test/mjsunit/harmony/block-let-declaration.js b/test/mjsunit/harmony/block-let-declaration.js index 49b63481..480e0334 100644 --- a/test/mjsunit/harmony/block-let-declaration.js +++ b/test/mjsunit/harmony/block-let-declaration.js @@ -25,41 +25,113 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --harmony-block-scoping +// Flags: --harmony-scoping // Test let declarations in various settings. +// TODO(ES6): properly activate extended mode +"use strict"; // Global let x; let y = 2; +const z = 4; // Block local { let y; let x = 3; + const z = 5; } assertEquals(undefined, x); assertEquals(2,y); +assertEquals(4,z); if (true) { let y; assertEquals(undefined, y); } +// Invalid declarations are early errors in harmony mode and thus should trigger +// an exception in eval code during parsing, before even compiling or executing +// the code. Thus the generated function is not called here. function TestLocalThrows(str, expect) { - assertThrows("(function(){" + str + "})()", expect); + assertThrows("(function(){ 'use strict'; " + str + "})", expect); } function TestLocalDoesNotThrow(str) { - assertDoesNotThrow("(function(){" + str + "})()"); + assertDoesNotThrow("(function(){ 'use strict'; " + str + "})()"); } -// Unprotected statement +// Test let declarations in statement positions. TestLocalThrows("if (true) let x;", SyntaxError); +TestLocalThrows("if (true) {} else let x;", SyntaxError); TestLocalThrows("do let x; while (false)", SyntaxError); TestLocalThrows("while (false) let x;", SyntaxError); +TestLocalThrows("label: let x;", SyntaxError); +TestLocalThrows("for (;false;) let x;", SyntaxError); +TestLocalThrows("switch (true) { case true: let x; }", SyntaxError); +TestLocalThrows("switch (true) { default: let x; }", SyntaxError); +// Test const declarations with initialisers in statement positions. +TestLocalThrows("if (true) const x = 1;", SyntaxError); +TestLocalThrows("if (true) {} else const x = 1;", SyntaxError); +TestLocalThrows("do const x = 1; while (false)", SyntaxError); +TestLocalThrows("while (false) const x = 1;", SyntaxError); +TestLocalThrows("label: const x = 1;", SyntaxError); +TestLocalThrows("for (;false;) const x = 1;", SyntaxError); +TestLocalThrows("switch (true) { case true: const x = 1; }", SyntaxError); +TestLocalThrows("switch (true) { default: const x = 1; }", SyntaxError); + +// Test const declarations without initialisers. +TestLocalThrows("const x;", SyntaxError); +TestLocalThrows("const x = 1, y;", SyntaxError); +TestLocalThrows("const x, y = 1;", SyntaxError); + +// Test const declarations without initialisers in statement positions. +TestLocalThrows("if (true) const x;", SyntaxError); +TestLocalThrows("if (true) {} else const x;", SyntaxError); +TestLocalThrows("do const x; while (false)", SyntaxError); +TestLocalThrows("while (false) const x;", SyntaxError); +TestLocalThrows("label: const x;", SyntaxError); +TestLocalThrows("for (;false;) const x;", SyntaxError); +TestLocalThrows("switch (true) { case true: const x; }", SyntaxError); +TestLocalThrows("switch (true) { default: const x; }", SyntaxError); + +// Test var declarations in statement positions. TestLocalDoesNotThrow("if (true) var x;"); +TestLocalDoesNotThrow("if (true) {} else var x;"); TestLocalDoesNotThrow("do var x; while (false)"); TestLocalDoesNotThrow("while (false) var x;"); +TestLocalDoesNotThrow("label: var x;"); +TestLocalDoesNotThrow("for (;false;) var x;"); +TestLocalDoesNotThrow("switch (true) { case true: var x; }"); +TestLocalDoesNotThrow("switch (true) { default: var x; }"); + +// Test function declarations in source element and +// non-strict statement positions. +function f() { + // Non-strict source element positions. + function g0() { + "use strict"; + // Strict source element positions. + function h() { } + { + function h1() { } + } + } + { + function g1() { } + } +} +f(); + +// Test function declarations in statement position in strict mode. +TestLocalThrows("function f() { if (true) function g() {}", SyntaxError); +TestLocalThrows("function f() { if (true) {} else function g() {}", SyntaxError); +TestLocalThrows("function f() { do function g() {} while (false)", SyntaxError); +TestLocalThrows("function f() { while (false) function g() {}", SyntaxError); +TestLocalThrows("function f() { label: function g() {}", SyntaxError); +TestLocalThrows("function f() { for (;false;) function g() {}", SyntaxError); +TestLocalThrows("function f() { switch (true) { case true: function g() {} }", SyntaxError); +TestLocalThrows("function f() { switch (true) { default: function g() {} }", SyntaxError); diff --git a/test/mjsunit/harmony/block-let-semantics.js b/test/mjsunit/harmony/block-let-semantics.js index 198c3b4f..d14e7cd3 100644 --- a/test/mjsunit/harmony/block-let-semantics.js +++ b/test/mjsunit/harmony/block-let-semantics.js @@ -25,7 +25,10 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --harmony-block-scoping +// Flags: --harmony-scoping + +// TODO(ES6): properly activate extended mode +"use strict"; // Test temporal dead zone semantics of let bound variables in // function and block scopes. @@ -61,6 +64,7 @@ TestAll('let x = x + 1'); TestAll('let x = x += 1'); TestAll('let x = x++'); TestAll('let x = ++x'); +TestAll('const x = x + 1'); // Use before initialization in prior statement. TestAll('x + 1; let x;'); @@ -68,25 +72,36 @@ TestAll('x = 1; let x;'); TestAll('x += 1; let x;'); TestAll('++x; let x;'); TestAll('x++; let x;'); +TestAll('let y = x; const x = 1;'); TestAll('f(); let x; function f() { return x + 1; }'); TestAll('f(); let x; function f() { x = 1; }'); TestAll('f(); let x; function f() { x += 1; }'); TestAll('f(); let x; function f() { ++x; }'); TestAll('f(); let x; function f() { x++; }'); +TestAll('f(); const x = 1; function f() { return x; }'); TestAll('f()(); let x; function f() { return function() { return x + 1; } }'); TestAll('f()(); let x; function f() { return function() { x = 1; } }'); TestAll('f()(); let x; function f() { return function() { x += 1; } }'); TestAll('f()(); let x; function f() { return function() { ++x; } }'); TestAll('f()(); let x; function f() { return function() { x++; } }'); +TestAll('f()(); const x = 1; function f() { return function() { return x; } }'); -// Use in before initialization with a dynamic lookup. +// Use before initialization with a dynamic lookup. TestAll('eval("x + 1;"); let x;'); TestAll('eval("x = 1;"); let x;'); TestAll('eval("x += 1;"); let x;'); TestAll('eval("++x;"); let x;'); TestAll('eval("x++;"); let x;'); +TestAll('eval("x"); const x = 1;'); + +// Use before initialization with check for eval-shadowed bindings. +TestAll('function f() { eval("var y = 2;"); x + 1; }; f(); let x;'); +TestAll('function f() { eval("var y = 2;"); x = 1; }; f(); let x;'); +TestAll('function f() { eval("var y = 2;"); x += 1; }; f(); let x;'); +TestAll('function f() { eval("var y = 2;"); ++x; }; f(); let x;'); +TestAll('function f() { eval("var y = 2;"); x++; }; f(); let x;'); // Test that variables introduced by function declarations are created and // initialized upon entering a function / block scope. @@ -115,7 +130,7 @@ TestAll('{ function k() { return 0; } }; k(); '); // Test that a function declaration sees the scope it resides in. function f2() { - let m, n; + let m, n, o, p; { m = g; function g() { @@ -132,7 +147,44 @@ function f2() { function h() { return b + c; } - let b = 3; + let c = 3; } assertEquals(5, n()); + + { + o = i; + function i() { + return d; + } + let d = 4; + } + assertEquals(4, o()); + + try { + throw 5; + } catch(e) { + p = j; + function j() { + return e + f; + } + let f = 6; + } + assertEquals(11, p()); +} +f2(); + +// Test that resolution of let bound variables works with scopes that call eval. +function outer() { + function middle() { + function inner() { + return x; + } + eval("1 + 1"); + return x + inner(); + } + + let x = 1; + return middle(); } + +assertEquals(2, outer()); diff --git a/test/mjsunit/harmony/block-scoping.js b/test/mjsunit/harmony/block-scoping.js index 266e3807..31194d99 100644 --- a/test/mjsunit/harmony/block-scoping.js +++ b/test/mjsunit/harmony/block-scoping.js @@ -25,9 +25,12 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --allow-natives-syntax --harmony-block-scoping +// Flags: --allow-natives-syntax --harmony-scoping // Test functionality of block scopes. +// TODO(ES6): properly activate extended mode +"use strict"; + // Hoisting of var declarations. function f1() { { @@ -44,12 +47,16 @@ f1(); function f2(one) { var x = one + 1; let y = one + 2; + const u = one + 4; { let z = one + 3; + const v = one + 5; assertEquals(1, eval('one')); assertEquals(2, eval('x')); assertEquals(3, eval('y')); assertEquals(4, eval('z')); + assertEquals(5, eval('u')); + assertEquals(6, eval('v')); } } f2(1); @@ -59,12 +66,17 @@ f2(1); function f3(one) { var x = one + 1; let y = one + 2; + const u = one + 4; { let z = one + 3; + const v = one + 5; assertEquals(1, one); assertEquals(2, x); assertEquals(3, y); assertEquals(4, z); + assertEquals(5, u); + assertEquals(6, v); + } } f3(1); @@ -74,13 +86,17 @@ f3(1); function f4(one) { var x = one + 1; let y = one + 2; + const u = one + 4; { let z = one + 3; + const v = one + 5; function f() { assertEquals(1, eval('one')); assertEquals(2, eval('x')); assertEquals(3, eval('y')); assertEquals(4, eval('z')); + assertEquals(5, eval('u')); + assertEquals(6, eval('v')); }; } } @@ -91,13 +107,17 @@ f4(1); function f5(one) { var x = one + 1; let y = one + 2; + const u = one + 4; { let z = one + 3; + const v = one + 5; function f() { assertEquals(1, one); assertEquals(2, x); assertEquals(3, y); assertEquals(4, z); + assertEquals(5, u); + assertEquals(6, v); }; } } @@ -107,8 +127,10 @@ f5(1); // Return from block. function f6() { let x = 1; + const u = 3; { let y = 2; + const v = 4; return x + y; } } @@ -120,13 +142,26 @@ function f7(a) { let b = 1; var c = 1; var d = 1; - { // let variables shadowing argument, let and var variables + const e = 1; + { // let variables shadowing argument, let, const and var variables let a = 2; let b = 2; let c = 2; + let e = 2; + assertEquals(2,a); + assertEquals(2,b); + assertEquals(2,c); + assertEquals(2,e); + } + { // const variables shadowing argument, let, const and var variables + const a = 2; + const b = 2; + const c = 2; + const e = 2; assertEquals(2,a); assertEquals(2,b); assertEquals(2,c); + assertEquals(2,e); } try { throw 'stuff1'; @@ -156,6 +191,12 @@ function f7(a) { } catch (c) { // catch variable shadowing var variable assertEquals('stuff3',c); + { + // const variable shadowing catch variable + const c = 3; + assertEquals(3,c); + } + assertEquals('stuff3',c); try { throw 'stuff4'; } catch(c) { @@ -178,14 +219,16 @@ function f7(a) { c = 2; } assertEquals(1,c); - (function(a,b,c) { - // arguments shadowing argument, let and var variable + (function(a,b,c,e) { + // arguments shadowing argument, let, const and var variable a = 2; b = 2; c = 2; + e = 2; assertEquals(2,a); assertEquals(2,b); assertEquals(2,c); + assertEquals(2,e); // var variable shadowing var variable var d = 2; })(1,1); @@ -193,24 +236,30 @@ function f7(a) { assertEquals(1,b); assertEquals(1,c); assertEquals(1,d); + assertEquals(1,e); } f7(1); -// Ensure let variables are block local and var variables function local. +// Ensure let and const variables are block local +// and var variables function local. function f8() { var let_accessors = []; var var_accessors = []; + var const_accessors = []; for (var i = 0; i < 10; i++) { let x = i; var y = i; + const z = i; let_accessors[i] = function() { return x; } var_accessors[i] = function() { return y; } + const_accessors[i] = function() { return z; } } for (var j = 0; j < 10; j++) { y = j + 10; assertEquals(j, let_accessors[j]()); assertEquals(y, var_accessors[j]()); + assertEquals(j, const_accessors[j]()); } } f8(); diff --git a/test/mjsunit/harmony/collections.js b/test/mjsunit/harmony/collections.js new file mode 100644 index 00000000..4b435c16 --- /dev/null +++ b/test/mjsunit/harmony/collections.js @@ -0,0 +1,280 @@ +// Copyright 2011 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. + +// Flags: --harmony-collections --expose-gc + + +// Test valid getter and setter calls on Sets. +function TestValidSetCalls(m) { + assertDoesNotThrow(function () { m.add(new Object) }); + assertDoesNotThrow(function () { m.has(new Object) }); + assertDoesNotThrow(function () { m.delete(new Object) }); +} +TestValidSetCalls(new Set); + + +// Test valid getter and setter calls on Maps and WeakMaps +function TestValidMapCalls(m) { + assertDoesNotThrow(function () { m.get(new Object) }); + assertDoesNotThrow(function () { m.set(new Object) }); + assertDoesNotThrow(function () { m.has(new Object) }); + assertDoesNotThrow(function () { m.delete(new Object) }); +} +TestValidMapCalls(new Map); +TestValidMapCalls(new WeakMap); + + +// Test invalid getter and setter calls for WeakMap only +function TestInvalidCalls(m) { + assertThrows(function () { m.get(undefined) }, TypeError); + assertThrows(function () { m.set(undefined, 0) }, TypeError); + assertThrows(function () { m.get(null) }, TypeError); + assertThrows(function () { m.set(null, 0) }, TypeError); + assertThrows(function () { m.get(0) }, TypeError); + assertThrows(function () { m.set(0, 0) }, TypeError); + assertThrows(function () { m.get('a-key') }, TypeError); + assertThrows(function () { m.set('a-key', 0) }, TypeError); +} +TestInvalidCalls(new WeakMap); + + +// Test expected behavior for Sets +function TestSet(set, key) { + assertFalse(set.has(key)); + set.add(key); + assertTrue(set.has(key)); + set.delete(key); + assertFalse(set.has(key)); +} +function TestSetBehavior(set) { + for (var i = 0; i < 20; i++) { + TestSet(set, new Object); + TestSet(set, i); + TestSet(set, i / 100); + TestSet(set, 'key-' + i); + } + var keys = [ +0, -0, +Infinity, -Infinity, true, false, null, undefined ]; + for (var i = 0; i < keys.length; i++) { + TestSet(set, keys[i]); + } +} +TestSetBehavior(new Set); + + +// Test expected mapping behavior for Maps and WeakMaps +function TestMapping(map, key, value) { + map.set(key, value); + assertSame(value, map.get(key)); +} +function TestMapBehavior1(m) { + TestMapping(m, new Object, 23); + TestMapping(m, new Object, 'the-value'); + TestMapping(m, new Object, new Object); +} +TestMapBehavior1(new Map); +TestMapBehavior1(new WeakMap); + + +// Test expected mapping behavior for Maps only +function TestMapBehavior2(m) { + for (var i = 0; i < 20; i++) { + TestMapping(m, i, new Object); + TestMapping(m, i / 10, new Object); + TestMapping(m, 'key-' + i, new Object); + } + var keys = [ +0, -0, +Infinity, -Infinity, true, false, null, undefined ]; + for (var i = 0; i < keys.length; i++) { + TestMapping(m, keys[i], new Object); + } +} +TestMapBehavior2(new Map); + + +// Test expected querying behavior of Maps and WeakMaps +function TestQuery(m) { + var key = new Object; + TestMapping(m, key, 'to-be-present'); + assertTrue(m.has(key)); + assertFalse(m.has(new Object)); + TestMapping(m, key, undefined); + assertFalse(m.has(key)); + assertFalse(m.has(new Object)); +} +TestQuery(new Map); +TestQuery(new WeakMap); + + +// Test expected deletion behavior of Maps and WeakMaps +function TestDelete(m) { + var key = new Object; + TestMapping(m, key, 'to-be-deleted'); + assertTrue(m.delete(key)); + assertFalse(m.delete(key)); + assertFalse(m.delete(new Object)); + assertSame(m.get(key), undefined); +} +TestDelete(new Map); +TestDelete(new WeakMap); + + +// Test GC of Maps and WeakMaps with entry +function TestGC1(m) { + var key = new Object; + m.set(key, 'not-collected'); + gc(); + assertSame('not-collected', m.get(key)); +} +TestGC1(new Map); +TestGC1(new WeakMap); + + +// Test GC of Maps and WeakMaps with chained entries +function TestGC2(m) { + var head = new Object; + for (key = head, i = 0; i < 10; i++, key = m.get(key)) { + m.set(key, new Object); + } + gc(); + var count = 0; + for (key = head; key != undefined; key = m.get(key)) { + count++; + } + assertEquals(11, count); +} +TestGC2(new Map); +TestGC2(new WeakMap); + + +// Test property attribute [[Enumerable]] +function TestEnumerable(func) { + function props(x) { + var array = []; + for (var p in x) array.push(p); + return array.sort(); + } + assertArrayEquals([], props(func)); + assertArrayEquals([], props(func.prototype)); + assertArrayEquals([], props(new func())); +} +TestEnumerable(Set); +TestEnumerable(Map); +TestEnumerable(WeakMap); + + +// Test arbitrary properties on Maps and WeakMaps +function TestArbitrary(m) { + function TestProperty(map, property, value) { + map[property] = value; + assertEquals(value, map[property]); + } + for (var i = 0; i < 20; i++) { + TestProperty(m, i, 'val' + i); + TestProperty(m, 'foo' + i, 'bar' + i); + } + TestMapping(m, new Object, 'foobar'); +} +TestArbitrary(new Map); +TestArbitrary(new WeakMap); + + +// Test direct constructor call +assertTrue(Set() instanceof Set); +assertTrue(Map() instanceof Map); +assertTrue(WeakMap() instanceof WeakMap); + + +// Test whether NaN values as keys are treated correctly. +var s = new Set; +assertFalse(s.has(NaN)); +assertFalse(s.has(NaN + 1)); +assertFalse(s.has(23)); +s.add(NaN); +assertTrue(s.has(NaN)); +assertTrue(s.has(NaN + 1)); +assertFalse(s.has(23)); +var m = new Map; +assertFalse(m.has(NaN)); +assertFalse(m.has(NaN + 1)); +assertFalse(m.has(23)); +m.set(NaN, 'a-value'); +assertTrue(m.has(NaN)); +assertTrue(m.has(NaN + 1)); +assertFalse(m.has(23)); + + +// Test some common JavaScript idioms for Sets +var s = new Set; +assertTrue(s instanceof Set); +assertTrue(Set.prototype.add instanceof Function) +assertTrue(Set.prototype.has instanceof Function) +assertTrue(Set.prototype.delete instanceof Function) + + +// Test some common JavaScript idioms for Maps +var m = new Map; +assertTrue(m instanceof Map); +assertTrue(Map.prototype.set instanceof Function) +assertTrue(Map.prototype.get instanceof Function) +assertTrue(Map.prototype.has instanceof Function) +assertTrue(Map.prototype.delete instanceof Function) + + +// Test some common JavaScript idioms for WeakMaps +var m = new WeakMap; +assertTrue(m instanceof WeakMap); +assertTrue(WeakMap.prototype.set instanceof Function) +assertTrue(WeakMap.prototype.get instanceof Function) +assertTrue(WeakMap.prototype.has instanceof Function) +assertTrue(WeakMap.prototype.delete instanceof Function) + + +// Regression test for WeakMap prototype. +assertTrue(WeakMap.prototype.constructor === WeakMap) +assertTrue(Object.getPrototypeOf(WeakMap.prototype) === Object.prototype) + + +// Regression test for issue 1617: The prototype of the WeakMap constructor +// needs to be unique (i.e. different from the one of the Object constructor). +assertFalse(WeakMap.prototype === Object.prototype); +var o = Object.create({}); +assertFalse("get" in o); +assertFalse("set" in o); +assertEquals(undefined, o.get); +assertEquals(undefined, o.set); +var o = Object.create({}, { myValue: { + value: 10, + enumerable: false, + configurable: true, + writable: true +}}); +assertEquals(10, o.myValue); + + +// Stress Test +// There is a proposed stress-test available at the es-discuss mailing list +// which cannot be reasonably automated. Check it out by hand if you like: +// https://mail.mozilla.org/pipermail/es-discuss/2011-May/014096.html
\ No newline at end of file diff --git a/test/mjsunit/harmony/debug-blockscopes.js b/test/mjsunit/harmony/debug-blockscopes.js index 0230e84b..10aac2db 100644 --- a/test/mjsunit/harmony/debug-blockscopes.js +++ b/test/mjsunit/harmony/debug-blockscopes.js @@ -25,13 +25,15 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --expose-debug-as debug --harmony-block-scoping +// Flags: --expose-debug-as debug --harmony-scoping // The functions used for testing backtraces. They are at the top to make the // testing of source line/column easier. +// TODO(ES6): properly activate extended mode +"use strict"; // Get the Debug object exposed from the debug context global object. -Debug = debug.Debug; +var Debug = debug.Debug; var test_name; var listener_delegate; @@ -76,6 +78,7 @@ function EndTest() { end_test_count++; } +var global_object = this; // Check that the scope chain contains the expected types of scopes. function CheckScopeChain(scopes, exec_state) { @@ -89,7 +92,7 @@ function CheckScopeChain(scopes, exec_state) { if (scopes[i] == debug.ScopeType.Global) { // Objects don't have same class (one is "global", other is "Object", // so just check the properties directly. - assertPropertiesEqual(this, scope.scopeObject().value()); + assertPropertiesEqual(global_object, scope.scopeObject().value()); } } @@ -329,138 +332,139 @@ local_7(1); EndTest(); -// Single empty with block. -BeginTest("With block 1"); +// Simple closure formed by returning an inner function referering to an outer +// block local variable and an outer function's parameter. +BeginTest("Closure 1"); -function with_block_1() { - with({}) { - debugger; +function closure_1(a) { + var x = 2; + let y = 3; + if (true) { + let z = 4; + function f() { + debugger; + return a + x + y + z; + }; + return f; } } listener_delegate = function(exec_state) { - CheckScopeChain([debug.ScopeType.With, - debug.ScopeType.Local, + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Block, + debug.ScopeType.Closure, debug.ScopeType.Global], exec_state); CheckScopeContent({}, 0, exec_state); - CheckScopeContent({}, 1, exec_state); + CheckScopeContent({a:1,x:2,y:3}, 2, exec_state); }; -with_block_1(); +closure_1(1)(); EndTest(); -// Nested empty with blocks. -BeginTest("With block 2"); +// Simple for-in loop over the keys of an object. +BeginTest("For loop 1"); -function with_block_2() { - with({}) { - with({}) { - debugger; - } +function for_loop_1() { + for (let x in {y:undefined}) { + debugger; } } listener_delegate = function(exec_state) { - CheckScopeChain([debug.ScopeType.With, - debug.ScopeType.With, + CheckScopeChain([debug.ScopeType.Block, debug.ScopeType.Local, debug.ScopeType.Global], exec_state); - CheckScopeContent({}, 0, exec_state); - CheckScopeContent({}, 1, exec_state); - CheckScopeContent({}, 2, exec_state); + CheckScopeContent({x:'y'}, 0, exec_state); + // The function scope contains a temporary iteration variable. + CheckScopeContent({x:'y'}, 1, exec_state); }; -with_block_2(); +for_loop_1(); EndTest(); -// With block using an in-place object literal. -BeginTest("With block 3"); +// For-in loop over the keys of an object with a block scoped let variable +// shadowing the iteration variable. +BeginTest("For loop 2"); -function with_block_3() { - with({a:1,b:2}) { +function for_loop_2() { + for (let x in {y:undefined}) { + let x = 3; debugger; } } listener_delegate = function(exec_state) { - CheckScopeChain([debug.ScopeType.With, + CheckScopeChain([debug.ScopeType.Block, + debug.ScopeType.Block, debug.ScopeType.Local, debug.ScopeType.Global], exec_state); - CheckScopeContent({a:1,b:2}, 0, exec_state); + CheckScopeContent({x:3}, 0, exec_state); + CheckScopeContent({x:'y'}, 1, exec_state); + // The function scope contains a temporary iteration variable. + CheckScopeContent({x:'y'}, 2, exec_state); }; -with_block_3(); +for_loop_2(); EndTest(); -// Nested with blocks using in-place object literals. -BeginTest("With block 4"); +// Simple for loop. +BeginTest("For loop 3"); -function with_block_4() { - with({a:1,b:2}) { - with({a:2,b:1}) { - debugger; - } +function for_loop_3() { + for (let x = 3; x < 4; ++x) { + debugger; } } listener_delegate = function(exec_state) { - CheckScopeChain([debug.ScopeType.With, - debug.ScopeType.With, + CheckScopeChain([debug.ScopeType.Block, debug.ScopeType.Local, debug.ScopeType.Global], exec_state); - CheckScopeContent({a:2,b:1}, 0, exec_state); - CheckScopeContent({a:1,b:2}, 1, exec_state); + CheckScopeContent({x:3}, 0, exec_state); + CheckScopeContent({}, 1, exec_state); }; -with_block_4(); +for_loop_3(); EndTest(); -// With block and a block local variable. -BeginTest("With block 5"); +// For loop with a block scoped let variable shadowing the iteration variable. +BeginTest("For loop 4"); -function with_block_5() { - with({a:1}) { - let a = 2; +function for_loop_4() { + for (let x = 3; x < 4; ++x) { + let x = 5; debugger; } } listener_delegate = function(exec_state) { CheckScopeChain([debug.ScopeType.Block, - debug.ScopeType.With, + debug.ScopeType.Block, debug.ScopeType.Local, debug.ScopeType.Global], exec_state); - CheckScopeContent({a:2}, 0, exec_state); - CheckScopeContent({a:1}, 1, exec_state); + CheckScopeContent({x:5}, 0, exec_state); + CheckScopeContent({x:3}, 1, exec_state); + CheckScopeContent({}, 2, exec_state); }; -with_block_5(); +for_loop_4(); EndTest(); -// Simple closure formed by returning an inner function referering to an outer -// block local variable and an outer function's parameter. -BeginTest("Closure 1"); +// For loop with two variable declarations. +BeginTest("For loop 5"); -function closure_1(a) { - var x = 2; - let y = 3; - if (true) { - let z = 4; - function f() { - debugger; - return a + x + y + z; - }; - return f; +function for_loop_5() { + for (let x = 3, y = 5; x < 4; ++x) { + debugger; } } listener_delegate = function(exec_state) { - CheckScopeChain([debug.ScopeType.Local, - debug.ScopeType.Block, - debug.ScopeType.Closure, + CheckScopeChain([debug.ScopeType.Block, + debug.ScopeType.Local, debug.ScopeType.Global], exec_state); - CheckScopeContent({}, 0, exec_state); - CheckScopeContent({a:1,x:2,y:3}, 2, exec_state); + CheckScopeContent({x:3,y:5}, 0, exec_state); + CheckScopeContent({}, 1, exec_state); }; -closure_1(1)(); +for_loop_5(); EndTest(); diff --git a/test/mjsunit/harmony/debug-evaluate-blockscopes.js b/test/mjsunit/harmony/debug-evaluate-blockscopes.js index 549960a2..d6ce8b2b 100644 --- a/test/mjsunit/harmony/debug-evaluate-blockscopes.js +++ b/test/mjsunit/harmony/debug-evaluate-blockscopes.js @@ -25,11 +25,17 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --expose-debug-as debug --harmony-block-scoping +// Flags: --expose-debug-as debug --harmony-scoping // Test debug evaluation for functions without local context, but with // nested catch contexts. +// TODO(ES6): properly activate extended mode +"use strict"; + +var x; +var result; + function f() { { // Line 1. let i = 1; // Line 2. @@ -42,7 +48,7 @@ function f() { }; // Get the Debug object exposed from the debug context global object. -Debug = debug.Debug +var Debug = debug.Debug // Set breakpoint on line 6. var bp = Debug.setBreakPoint(f, 6); diff --git a/test/mjsunit/harmony/proxies-example-membrane.js b/test/mjsunit/harmony/proxies-example-membrane.js new file mode 100644 index 00000000..c6e7f9f9 --- /dev/null +++ b/test/mjsunit/harmony/proxies-example-membrane.js @@ -0,0 +1,512 @@ +// Copyright 2011 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. + +// Flags: --harmony + + +// A simple no-op handler. Adapted from: +// http://wiki.ecmascript.org/doku.php?id=harmony:proxies#examplea_no-op_forwarding_proxy + +function createHandler(obj) { + return { + getOwnPropertyDescriptor: function(name) { + var desc = Object.getOwnPropertyDescriptor(obj, name); + if (desc !== undefined) desc.configurable = true; + return desc; + }, + getPropertyDescriptor: function(name) { + var desc = Object.getOwnPropertyDescriptor(obj, name); + //var desc = Object.getPropertyDescriptor(obj, name); // not in ES5 + if (desc !== undefined) desc.configurable = true; + return desc; + }, + getOwnPropertyNames: function() { + return Object.getOwnPropertyNames(obj); + }, + getPropertyNames: function() { + return Object.getOwnPropertyNames(obj); + //return Object.getPropertyNames(obj); // not in ES5 + }, + defineProperty: function(name, desc) { + Object.defineProperty(obj, name, desc); + }, + delete: function(name) { + return delete obj[name]; + }, + fix: function() { + if (Object.isFrozen(obj)) { + var result = {}; + Object.getOwnPropertyNames(obj).forEach(function(name) { + result[name] = Object.getOwnPropertyDescriptor(obj, name); + }); + return result; + } + // As long as obj is not frozen, the proxy won't allow itself to be fixed + return undefined; // will cause a TypeError to be thrown + }, + has: function(name) { return name in obj; }, + hasOwn: function(name) { return ({}).hasOwnProperty.call(obj, name); }, + get: function(receiver, name) { return obj[name]; }, + set: function(receiver, name, val) { + obj[name] = val; // bad behavior when set fails in non-strict mode + return true; + }, + enumerate: function() { + var result = []; + for (var name in obj) { result.push(name); }; + return result; + }, + keys: function() { return Object.keys(obj); } + }; +} + + + +// Auxiliary definitions enabling tracking of object identity in output. + +var objectMap = new WeakMap; +var objectCounter = 0; + +function registerObject(x, s) { + if (x === Object(x) && !objectMap.has(x)) + objectMap.set(x, ++objectCounter + (s == undefined ? "" : ":" + s)); +} + +registerObject(this, "global"); +registerObject(Object.prototype, "Object.prototype"); + +function str(x) { + if (x === Object(x)) return "[" + typeof x + " " + objectMap.get(x) + "]"; + if (typeof x == "string") return "\"" + x + "\""; + return "" + x; +} + + + +// A simple membrane. Adapted from: +// http://wiki.ecmascript.org/doku.php?id=harmony:proxies#a_simple_membrane + +function createSimpleMembrane(target) { + var enabled = true; + + function wrap(obj) { + registerObject(obj); + print("wrap enter", str(obj)); + try { + var x = wrap2(obj); + registerObject(x, "wrapped"); + print("wrap exit", str(obj), "as", str(x)); + return x; + } catch(e) { + print("wrap exception", str(e)); + throw e; + } + } + + function wrap2(obj) { + if (obj !== Object(obj)) { + return obj; + } + + function wrapCall(fun, that, args) { + registerObject(that); + print("wrapCall enter", fun, str(that)); + try { + var x = wrapCall2(fun, that, args); + print("wrapCall exit", fun, str(that), "returning", str(x)); + return x; + } catch(e) { + print("wrapCall exception", fun, str(that), str(e)); + throw e; + } + } + + function wrapCall2(fun, that, args) { + if (!enabled) { throw new Error("disabled"); } + try { + return wrap(fun.apply(that, Array.prototype.map.call(args, wrap))); + } catch (e) { + throw wrap(e); + } + } + + var baseHandler = createHandler(obj); + var handler = Proxy.create(Object.freeze({ + get: function(receiver, name) { + return function() { + var arg = (name === "get" || name == "set") ? arguments[1] : ""; + print("handler enter", name, arg); + var x = wrapCall(baseHandler[name], baseHandler, arguments); + print("handler exit", name, arg, "returning", str(x)); + return x; + } + } + })); + registerObject(baseHandler, "basehandler"); + registerObject(handler, "handler"); + + if (typeof obj === "function") { + function callTrap() { + print("call trap enter", str(obj), str(this)); + var x = wrapCall(obj, wrap(this), arguments); + print("call trap exit", str(obj), str(this), "returning", str(x)); + return x; + } + function constructTrap() { + if (!enabled) { throw new Error("disabled"); } + try { + function forward(args) { return obj.apply(this, args) } + return wrap(new forward(Array.prototype.map.call(arguments, wrap))); + } catch (e) { + throw wrap(e); + } + } + return Proxy.createFunction(handler, callTrap, constructTrap); + } else { + var prototype = wrap(Object.getPrototypeOf(obj)); + return Proxy.create(handler, prototype); + } + } + + var gate = Object.freeze({ + enable: function() { enabled = true; }, + disable: function() { enabled = false; } + }); + + return Object.freeze({ + wrapper: wrap(target), + gate: gate + }); +} + + +var o = { + a: 6, + b: {bb: 8}, + f: function(x) { return x }, + g: function(x) { return x.a }, + h: function(x) { this.q = x } +}; +o[2] = {c: 7}; +var m = createSimpleMembrane(o); +var w = m.wrapper; +print("o =", str(o)) +print("w =", str(w)); + +var f = w.f; +var x = f(66); +var x = f({a: 1}); +var x = w.f({a: 1}); +var a = x.a; +assertEquals(6, w.a); +assertEquals(8, w.b.bb); +assertEquals(7, w[2]["c"]); +assertEquals(undefined, w.c); +assertEquals(1, w.f(1)); +assertEquals(1, w.f({a: 1}).a); +assertEquals(2, w.g({a: 2})); +assertEquals(3, (w.r = {a: 3}).a); +assertEquals(3, w.r.a); +assertEquals(3, o.r.a); +w.h(3); +assertEquals(3, w.q); +assertEquals(3, o.q); +assertEquals(4, (new w.h(4)).q); + +var wb = w.b; +var wr = w.r; +var wf = w.f; +var wf3 = w.f(3); +var wfx = w.f({a: 6}); +var wgx = w.g({a: {aa: 7}}); +var wh4 = new w.h(4); +m.gate.disable(); +assertEquals(3, wf3); +assertThrows(function() { w.a }, Error); +assertThrows(function() { w.r }, Error); +assertThrows(function() { w.r = {a: 4} }, Error); +assertThrows(function() { o.r.a }, Error); +assertEquals("object", typeof o.r); +assertEquals(5, (o.r = {a: 5}).a); +assertEquals(5, o.r.a); +assertThrows(function() { w[1] }, Error); +assertThrows(function() { w.c }, Error); +assertThrows(function() { wb.bb }, Error); +assertThrows(function() { wr.a }, Error); +assertThrows(function() { wf(4) }, Error); +assertThrows(function() { wfx.a }, Error); +assertThrows(function() { wgx.aa }, Error); +assertThrows(function() { wh4.q }, Error); + +m.gate.enable(); +assertEquals(6, w.a); +assertEquals(5, w.r.a); +assertEquals(5, o.r.a); +assertEquals(7, w.r = 7); +assertEquals(7, w.r); +assertEquals(7, o.r); +assertEquals(8, w.b.bb); +assertEquals(7, w[2]["c"]); +assertEquals(undefined, w.c); +assertEquals(8, wb.bb); +assertEquals(3, wr.a); +assertEquals(4, wf(4)); +assertEquals(3, wf3); +assertEquals(6, wfx.a); +assertEquals(7, wgx.aa); +assertEquals(4, wh4.q); + + +// An identity-preserving membrane. Adapted from: +// http://wiki.ecmascript.org/doku.php?id=harmony:proxies#an_identity-preserving_membrane + +function createMembrane(wetTarget) { + var wet2dry = WeakMap(); + var dry2wet = WeakMap(); + + function asDry(obj) { + registerObject(obj) + print("asDry enter", str(obj)) + try { + var x = asDry2(obj); + registerObject(x, "dry"); + print("asDry exit", str(obj), "as", str(x)); + return x; + } catch(e) { + print("asDry exception", str(e)); + throw e; + } + } + function asDry2(wet) { + if (wet !== Object(wet)) { + // primitives provide only irrevocable knowledge, so don't + // bother wrapping it. + return wet; + } + var dryResult = wet2dry.get(wet); + if (dryResult) { return dryResult; } + + var wetHandler = createHandler(wet); + var dryRevokeHandler = Proxy.create(Object.freeze({ + get: function(receiver, name) { + return function() { + var arg = (name === "get" || name == "set") ? arguments[1] : ""; + print("dry handler enter", name, arg); + var optWetHandler = dry2wet.get(dryRevokeHandler); + try { + var x = asDry(optWetHandler[name].apply( + optWetHandler, Array.prototype.map.call(arguments, asWet))); + print("dry handler exit", name, arg, "returning", str(x)); + return x; + } catch (eWet) { + var x = asDry(eWet); + print("dry handler exception", name, arg, "throwing", str(x)); + throw x; + } + }; + } + })); + dry2wet.set(dryRevokeHandler, wetHandler); + + if (typeof wet === "function") { + function callTrap() { + print("dry call trap enter", str(this)); + var x = asDry(wet.apply( + asWet(this), Array.prototype.map.call(arguments, asWet))); + print("dry call trap exit", str(this), "returning", str(x)); + return x; + } + function constructTrap() { + function forward(args) { return wet.apply(this, args) } + return asDry(new forward(Array.prototype.map.call(arguments, asWet))); + } + dryResult = + Proxy.createFunction(dryRevokeHandler, callTrap, constructTrap); + } else { + dryResult = + Proxy.create(dryRevokeHandler, asDry(Object.getPrototypeOf(wet))); + } + wet2dry.set(wet, dryResult); + dry2wet.set(dryResult, wet); + return dryResult; + } + + function asWet(obj) { + registerObject(obj) + print("asWet enter", str(obj)) + try { + var x = asWet2(obj) + registerObject(x, "wet") + print("asWet exit", str(obj), "as", str(x)) + return x + } catch(e) { + print("asWet exception", str(e)) + throw e + } + } + function asWet2(dry) { + if (dry !== Object(dry)) { + // primitives provide only irrevocable knowledge, so don't + // bother wrapping it. + return dry; + } + var wetResult = dry2wet.get(dry); + if (wetResult) { return wetResult; } + + var dryHandler = createHandler(dry); + var wetRevokeHandler = Proxy.create(Object.freeze({ + get: function(receiver, name) { + return function() { + var arg = (name === "get" || name == "set") ? arguments[1] : ""; + print("wet handler enter", name, arg); + var optDryHandler = wet2dry.get(wetRevokeHandler); + try { + var x = asWet(optDryHandler[name].apply( + optDryHandler, Array.prototype.map.call(arguments, asDry))); + print("wet handler exit", name, arg, "returning", str(x)); + return x; + } catch (eDry) { + var x = asWet(eDry); + print("wet handler exception", name, arg, "throwing", str(x)); + throw x; + } + }; + } + })); + wet2dry.set(wetRevokeHandler, dryHandler); + + if (typeof dry === "function") { + function callTrap() { + print("wet call trap enter", str(this)); + var x = asWet(dry.apply( + asDry(this), Array.prototype.map.call(arguments, asDry))); + print("wet call trap exit", str(this), "returning", str(x)); + return x; + } + function constructTrap() { + function forward(args) { return dry.apply(this, args) } + return asWet(new forward(Array.prototype.map.call(arguments, asDry))); + } + wetResult = + Proxy.createFunction(wetRevokeHandler, callTrap, constructTrap); + } else { + wetResult = + Proxy.create(wetRevokeHandler, asWet(Object.getPrototypeOf(dry))); + } + dry2wet.set(dry, wetResult); + wet2dry.set(wetResult, dry); + return wetResult; + } + + var gate = Object.freeze({ + revoke: function() { + dry2wet = wet2dry = Object.freeze({ + get: function(key) { throw new Error("revoked"); }, + set: function(key, val) { throw new Error("revoked"); } + }); + } + }); + + return Object.freeze({ wrapper: asDry(wetTarget), gate: gate }); +} + + +var receiver +var argument +var o = { + a: 6, + b: {bb: 8}, + f: function(x) { receiver = this; argument = x; return x }, + g: function(x) { receiver = this; argument = x; return x.a }, + h: function(x) { receiver = this; argument = x; this.q = x }, + s: function(x) { receiver = this; argument = x; this.x = {y: x}; return this } +} +o[2] = {c: 7} +var m = createMembrane(o) +var w = m.wrapper +print("o =", str(o)) +print("w =", str(w)) + +var f = w.f +var x = f(66) +var x = f({a: 1}) +var x = w.f({a: 1}) +var a = x.a +assertEquals(6, w.a) +assertEquals(8, w.b.bb) +assertEquals(7, w[2]["c"]) +assertEquals(undefined, w.c) +assertEquals(1, w.f(1)) +assertSame(o, receiver) +assertEquals(1, w.f({a: 1}).a) +assertSame(o, receiver) +assertEquals(2, w.g({a: 2})) +assertSame(o, receiver) +assertSame(w, w.f(w)) +assertSame(o, receiver) +assertSame(o, argument) +assertSame(o, w.f(o)) +assertSame(o, receiver) +// Note that argument !== o, since o isn't dry, so gets wrapped wet again. +assertEquals(3, (w.r = {a: 3}).a) +assertEquals(3, w.r.a) +assertEquals(3, o.r.a) +w.h(3) +assertEquals(3, w.q) +assertEquals(3, o.q) +assertEquals(4, (new w.h(4)).q) +assertEquals(5, w.s(5).x.y) +assertSame(o, receiver) + +var wb = w.b +var wr = w.r +var wf = w.f +var wf3 = w.f(3) +var wfx = w.f({a: 6}) +var wgx = w.g({a: {aa: 7}}) +var wh4 = new w.h(4) +var ws5 = w.s(5) +var ws5x = ws5.x +m.gate.revoke() +assertEquals(3, wf3) +assertThrows(function() { w.a }, Error) +assertThrows(function() { w.r }, Error) +assertThrows(function() { w.r = {a: 4} }, Error) +assertThrows(function() { o.r.a }, Error) +assertEquals("object", typeof o.r) +assertEquals(5, (o.r = {a: 5}).a) +assertEquals(5, o.r.a) +assertThrows(function() { w[1] }, Error) +assertThrows(function() { w.c }, Error) +assertThrows(function() { wb.bb }, Error) +assertEquals(3, wr.a) +assertThrows(function() { wf(4) }, Error) +assertEquals(6, wfx.a) +assertEquals(7, wgx.aa) +assertThrows(function() { wh4.q }, Error) +assertThrows(function() { ws5.x }, Error) +assertThrows(function() { ws5x.y }, Error) diff --git a/test/mjsunit/harmony/proxies-for.js b/test/mjsunit/harmony/proxies-for.js new file mode 100644 index 00000000..3d419c6d --- /dev/null +++ b/test/mjsunit/harmony/proxies-for.js @@ -0,0 +1,168 @@ +// Copyright 2011 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. + +// Flags: --harmony-proxies + + +// Helper. + +function TestWithProxies(test, x, y, z) { + test(Proxy.create, x, y, z) + test(function(h) {return Proxy.createFunction(h, function() {})}, x, y, z) +} + + +// Iterate over a proxy. + +function TestForIn(properties, handler) { + TestWithProxies(TestForIn2, properties, handler) +} + +function TestForIn2(create, properties, handler) { + var p = create(handler) + var found = [] + for (var x in p) found.push(x) + assertArrayEquals(properties, found) +} + +TestForIn(["0", "a"], { + enumerate: function() { return [0, "a"] } +}) + +TestForIn(["null", "a"], { + enumerate: function() { return this.enumerate2() }, + enumerate2: function() { return [null, "a"] } +}) + +TestForIn(["b", "d"], { + getPropertyNames: function() { return ["a", "b", "c", "d", "e"] }, + getPropertyDescriptor: function(k) { + switch (k) { + case "a": return {enumerable: false, value: "3"}; + case "b": return {enumerable: true, get get() {}}; + case "c": return {value: 4}; + case "d": return {get enumerable() { return true }}; + default: return undefined; + } + } +}) + +TestForIn(["b", "a", "0", "c"], Proxy.create({ + get: function(pr, pk) { + return function() { return ["b", "a", 0, "c"] } + } +})) + + + +// Iterate over an object with a proxy prototype. + +function TestForInDerived(properties, handler) { + TestWithProxies(TestForInDerived2, properties, handler) +} + +function TestForInDerived2(create, properties, handler) { + var p = create(handler) + var o = Object.create(p) + o.z = 0 + var found = [] + for (var x in o) found.push(x) + assertArrayEquals(["z"].concat(properties), found) + + var oo = Object.create(o) + oo.y = 0 + var found = [] + for (var x in oo) found.push(x) + assertArrayEquals(["y", "z"].concat(properties), found) +} + +TestForInDerived(["0", "a"], { + enumerate: function() { return [0, "a"] }, + getPropertyDescriptor: function(k) { + return k == "0" || k == "a" ? {} : undefined + } +}) + +TestForInDerived(["null", "a"], { + enumerate: function() { return this.enumerate2() }, + enumerate2: function() { return [null, "a"] }, + getPropertyDescriptor: function(k) { + return k == "null" || k == "a" ? {} : undefined + } +}) + +TestForInDerived(["b", "d"], { + getPropertyNames: function() { return ["a", "b", "c", "d", "e"] }, + getPropertyDescriptor: function(k) { + switch (k) { + case "a": return {enumerable: false, value: "3"}; + case "b": return {enumerable: true, get get() {}}; + case "c": return {value: 4}; + case "d": return {get enumerable() { return true }}; + default: return undefined; + } + } +}) + + + +// Throw exception in enumerate trap. + +function TestForInThrow(handler) { + TestWithProxies(TestForInThrow2, handler) +} + +function TestForInThrow2(create, handler) { + var p = create(handler) + var o = Object.create(p) + assertThrows(function(){ for (var x in p) {} }, "myexn") + assertThrows(function(){ for (var x in o) {} }, "myexn") +} + +TestForInThrow({ + enumerate: function() { throw "myexn" } +}) + +TestForInThrow({ + enumerate: function() { return this.enumerate2() }, + enumerate2: function() { throw "myexn" } +}) + +TestForInThrow({ + getPropertyNames: function() { throw "myexn" } +}) + +TestForInThrow({ + getPropertyNames: function() { return ["a"] }, + getPropertyDescriptor: function() { throw "myexn" } +}) + +TestForInThrow(Proxy.create({ + get: function(pr, pk) { + return function() { throw "myexn" } + } +})) diff --git a/test/mjsunit/harmony/proxies-function.js b/test/mjsunit/harmony/proxies-function.js new file mode 100644 index 00000000..3f5ace67 --- /dev/null +++ b/test/mjsunit/harmony/proxies-function.js @@ -0,0 +1,732 @@ +// Copyright 2011 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. + +// Flags: --harmony-proxies --allow-natives-syntax + + +// Helper. + +function CreateFrozen(handler, callTrap, constructTrap) { + if (handler.fix === undefined) handler.fix = function() { return {} } + var f = Proxy.createFunction(handler, callTrap, constructTrap) + Object.freeze(f) + return f +} + + +// Ensures that checking the "length" property of a function proxy doesn't +// crash due to lack of a [[Get]] method. +var handler = { + get : function(r, n) { return n == "length" ? 2 : undefined } +} + + +// Calling (call, Function.prototype.call, Function.prototype.apply, +// Function.prototype.bind). + +var global_object = this +var receiver + +function TestCall(isStrict, callTrap) { + assertEquals(42, callTrap(5, 37)) + // TODO(rossberg): strict mode seems to be broken on x64... + // assertSame(isStrict ? undefined : global_object, receiver) + + var handler = { + get: function(r, k) { + return k == "length" ? 2 : Function.prototype[k] + } + } + var f = Proxy.createFunction(handler, callTrap) + var o = {f: f} + global_object.f = f + + receiver = 333 + assertEquals(42, f(11, 31)) + // TODO(rossberg): strict mode seems to be broken on x64... + // assertSame(isStrict ? undefined : global_object, receiver) + receiver = 333 + assertEquals(42, o.f(10, 32)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, o["f"](9, 33)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, (1, o).f(8, 34)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, (1, o)["f"](7, 35)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, f.call(o, 32, 10)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, f.call(undefined, 33, 9)) + assertSame(isStrict ? undefined : global_object, receiver) + receiver = 333 + assertEquals(42, f.call(null, 33, 9)) + assertSame(isStrict ? null : global_object, receiver) + receiver = 333 + assertEquals(44, f.call(2, 21, 23)) + assertSame(2, receiver.valueOf()) + receiver = 333 + assertEquals(42, Function.prototype.call.call(f, o, 20, 22)) + assertSame(o, receiver) + receiver = 333 + assertEquals(43, Function.prototype.call.call(f, null, 20, 23)) + assertSame(isStrict ? null : global_object, receiver) + assertEquals(44, Function.prototype.call.call(f, 2, 21, 23)) + assertEquals(2, receiver.valueOf()) + receiver = 333 + assertEquals(32, f.apply(o, [16, 16])) + assertSame(o, receiver) + receiver = 333 + assertEquals(32, Function.prototype.apply.call(f, o, [17, 15])) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, %Call(o, 11, 31, f)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, %Call(null, 11, 31, f)) + assertSame(isStrict ? null : global_object, receiver) + receiver = 333 + assertEquals(42, %Apply(f, o, [11, 31], 0, 2)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, %Apply(f, null, [11, 31], 0, 2)) + assertSame(isStrict ? null : global_object, receiver) + receiver = 333 + assertEquals(42, %_CallFunction(o, 11, 31, f)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, %_CallFunction(null, 11, 31, f)) + assertSame(isStrict ? null : global_object, receiver) + + var ff = Function.prototype.bind.call(f, o, 12) + assertTrue(ff.length <= 1) // TODO(rossberg): Not spec'ed yet, be lax. + receiver = 333 + assertEquals(42, ff(30)) + assertSame(o, receiver) + receiver = 333 + assertEquals(33, Function.prototype.call.call(ff, {}, 21)) + assertSame(o, receiver) + receiver = 333 + assertEquals(32, Function.prototype.apply.call(ff, {}, [20])) + assertSame(o, receiver) + receiver = 333 + assertEquals(23, %Call({}, 11, ff)) + assertSame(o, receiver) + receiver = 333 + assertEquals(23, %Call({}, 11, 3, ff)) + assertSame(o, receiver) + receiver = 333 + assertEquals(24, %Apply(ff, {}, [12, 13], 0, 1)) + assertSame(o, receiver) + receiver = 333 + assertEquals(24, %Apply(ff, {}, [12, 13], 0, 2)) + assertSame(o, receiver) + receiver = 333 + assertEquals(34, %_CallFunction({}, 22, ff)) + assertSame(o, receiver) + receiver = 333 + assertEquals(34, %_CallFunction({}, 22, 3, ff)) + assertSame(o, receiver) + + var fff = Function.prototype.bind.call(ff, o, 30) + assertEquals(0, fff.length) + receiver = 333 + assertEquals(42, fff()) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, Function.prototype.call.call(fff, {})) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, Function.prototype.apply.call(fff, {})) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, %Call({}, fff)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, %Call({}, 11, 3, fff)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, %Apply(fff, {}, [], 0, 0)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, %Apply(fff, {}, [12, 13], 0, 0)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, %Apply(fff, {}, [12, 13], 0, 2)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, %_CallFunction({}, fff)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, %_CallFunction({}, 3, 4, 5, fff)) + assertSame(o, receiver) + + var f = CreateFrozen({}, callTrap) + receiver = 333 + assertEquals(42, f(11, 31)) + assertSame(isStrict ? undefined : global_object, receiver) + var o = {f: f} + receiver = 333 + assertEquals(42, o.f(10, 32)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, o["f"](9, 33)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, (1, o).f(8, 34)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, (1, o)["f"](7, 35)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, Function.prototype.call.call(f, o, 20, 22)) + assertSame(o, receiver) + receiver = 333 + assertEquals(32, Function.prototype.apply.call(f, o, [17, 15])) + assertSame(o, receiver) + receiver = 333 + assertEquals(23, %Call(o, 11, 12, f)) + assertSame(o, receiver) + receiver = 333 + assertEquals(27, %Apply(f, o, [12, 13, 14], 1, 2)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, %_CallFunction(o, 18, 24, f)) + assertSame(o, receiver) +} + +TestCall(false, function(x, y) { + receiver = this + return x + y +}) + +TestCall(true, function(x, y) { + "use strict" + receiver = this + return x + y +}) + +TestCall(false, function() { + receiver = this + return arguments[0] + arguments[1] +}) + +TestCall(false, Proxy.createFunction(handler, function(x, y) { + receiver = this + return x + y +})) + +TestCall(true, Proxy.createFunction(handler, function(x, y) { + "use strict" + receiver = this + return x + y +})) + +TestCall(false, CreateFrozen(handler, function(x, y) { + receiver = this + return x + y +})) + + + +// Using intrinsics as call traps. + +function TestCallIntrinsic(type, callTrap) { + var f = Proxy.createFunction({}, callTrap) + var x = f() + assertTrue(typeof x == type) +} + +TestCallIntrinsic("boolean", Boolean) +TestCallIntrinsic("number", Number) +TestCallIntrinsic("string", String) +TestCallIntrinsic("object", Object) +TestCallIntrinsic("function", Function) + + + +// Throwing from call trap. + +function TestCallThrow(callTrap) { + var f = Proxy.createFunction({}, callTrap) + assertThrows(function(){ f(11) }, "myexn") + assertThrows(function(){ ({x: f}).x(11) }, "myexn") + assertThrows(function(){ ({x: f})["x"](11) }, "myexn") + assertThrows(function(){ Function.prototype.call.call(f, {}, 2) }, "myexn") + assertThrows(function(){ Function.prototype.apply.call(f, {}, [1]) }, "myexn") + assertThrows(function(){ %Call({}, f) }, "myexn") + assertThrows(function(){ %Call({}, 1, 2, f) }, "myexn") + assertThrows(function(){ %Apply({}, f, [], 3, 0) }, "myexn") + assertThrows(function(){ %Apply({}, f, [3, 4], 0, 1) }, "myexn") + assertThrows(function(){ %_CallFunction({}, f) }, "myexn") + assertThrows(function(){ %_CallFunction({}, 1, 2, f) }, "myexn") + + var f = CreateFrozen({}, callTrap) + assertThrows(function(){ f(11) }, "myexn") + assertThrows(function(){ ({x: f}).x(11) }, "myexn") + assertThrows(function(){ ({x: f})["x"](11) }, "myexn") + assertThrows(function(){ Function.prototype.call.call(f, {}, 2) }, "myexn") + assertThrows(function(){ Function.prototype.apply.call(f, {}, [1]) }, "myexn") + assertThrows(function(){ %Call({}, f) }, "myexn") + assertThrows(function(){ %Call({}, 1, 2, f) }, "myexn") + assertThrows(function(){ %Apply({}, f, [], 3, 0) }, "myexn") + assertThrows(function(){ %Apply({}, f, [3, 4], 0, 1) }, "myexn") + assertThrows(function(){ %_CallFunction({}, f) }, "myexn") + assertThrows(function(){ %_CallFunction({}, 1, 2, f) }, "myexn") +} + +TestCallThrow(function() { throw "myexn" }) +TestCallThrow(Proxy.createFunction({}, function() { throw "myexn" })) +TestCallThrow(CreateFrozen({}, function() { throw "myexn" })) + + + +// Construction (new). + +var prototype = {myprop: 0} +var receiver + +var handlerWithPrototype = { + fix: function() { return { prototype: { value: prototype } }; }, + get: function(r, n) { + if (n == "length") return 2; + assertEquals("prototype", n); + return prototype; + } +} + +var handlerSansPrototype = { + fix: function() { return { length: { value: 2 } } }, + get: function(r, n) { + if (n == "length") return 2; + assertEquals("prototype", n); + return undefined; + } +} + +function ReturnUndef(x, y) { + "use strict"; + receiver = this; + this.sum = x + y; +} + +function ReturnThis(x, y) { + "use strict"; + receiver = this; + this.sum = x + y; + return this; +} + +function ReturnNew(x, y) { + "use strict"; + receiver = this; + return {sum: x + y}; +} + +function ReturnNewWithProto(x, y) { + "use strict"; + receiver = this; + var result = Object.create(prototype); + result.sum = x + y; + return result; +} + +function TestConstruct(proto, constructTrap) { + TestConstruct2(proto, constructTrap, handlerWithPrototype) + TestConstruct2(proto, constructTrap, handlerSansPrototype) +} + +function TestConstruct2(proto, constructTrap, handler) { + var f = Proxy.createFunction(handler, function() {}, constructTrap) + var o = new f(11, 31) + assertEquals(undefined, receiver) + assertEquals(42, o.sum) + assertSame(proto, Object.getPrototypeOf(o)) + + var f = CreateFrozen(handler, function() {}, constructTrap) + var o = new f(11, 32) + assertEquals(undefined, receiver) + assertEquals(43, o.sum) + assertSame(proto, Object.getPrototypeOf(o)) +} + +TestConstruct(Object.prototype, ReturnNew) +TestConstruct(prototype, ReturnNewWithProto) + +TestConstruct(Object.prototype, Proxy.createFunction(handler, ReturnNew)) +TestConstruct(prototype, Proxy.createFunction(handler, ReturnNewWithProto)) + +TestConstruct(Object.prototype, CreateFrozen(handler, ReturnNew)) +TestConstruct(prototype, CreateFrozen(handler, ReturnNewWithProto)) + + + +// Construction with derived construct trap. + +function TestConstructFromCall(proto, returnsThis, callTrap) { + TestConstructFromCall2(prototype, returnsThis, callTrap, handlerWithPrototype) + TestConstructFromCall2(proto, returnsThis, callTrap, handlerSansPrototype) +} + +function TestConstructFromCall2(proto, returnsThis, callTrap, handler) { + // TODO(rossberg): handling of prototype for derived construct trap will be + // fixed in a separate change. Commenting out checks below for now. + var f = Proxy.createFunction(handler, callTrap) + var o = new f(11, 31) + if (returnsThis) assertEquals(o, receiver) + assertEquals(42, o.sum) + // assertSame(proto, Object.getPrototypeOf(o)) + + var g = CreateFrozen(handler, callTrap) + // assertSame(f.prototype, g.prototype) + var o = new g(11, 32) + if (returnsThis) assertEquals(o, receiver) + assertEquals(43, o.sum) + // assertSame(proto, Object.getPrototypeOf(o)) +} + +TestConstructFromCall(Object.prototype, true, ReturnUndef) +TestConstructFromCall(Object.prototype, true, ReturnThis) +TestConstructFromCall(Object.prototype, false, ReturnNew) +TestConstructFromCall(prototype, false, ReturnNewWithProto) + +TestConstructFromCall(Object.prototype, true, + Proxy.createFunction(handler, ReturnUndef)) +TestConstructFromCall(Object.prototype, true, + Proxy.createFunction(handler, ReturnThis)) +TestConstructFromCall(Object.prototype, false, + Proxy.createFunction(handler, ReturnNew)) +TestConstructFromCall(prototype, false, + Proxy.createFunction(handler, ReturnNewWithProto)) + +TestConstructFromCall(Object.prototype, true, CreateFrozen({}, ReturnUndef)) +TestConstructFromCall(Object.prototype, true, CreateFrozen({}, ReturnThis)) +TestConstructFromCall(Object.prototype, false, CreateFrozen({}, ReturnNew)) +TestConstructFromCall(prototype, false, CreateFrozen({}, ReturnNewWithProto)) + +ReturnUndef.prototype = prototype +ReturnThis.prototype = prototype +ReturnNew.prototype = prototype +ReturnNewWithProto.prototype = prototype + +TestConstructFromCall(prototype, true, ReturnUndef) +TestConstructFromCall(prototype, true, ReturnThis) +TestConstructFromCall(Object.prototype, false, ReturnNew) +TestConstructFromCall(prototype, false, ReturnNewWithProto) + +TestConstructFromCall(Object.prototype, true, + Proxy.createFunction(handler, ReturnUndef)) +TestConstructFromCall(Object.prototype, true, + Proxy.createFunction(handler, ReturnThis)) +TestConstructFromCall(Object.prototype, false, + Proxy.createFunction(handler, ReturnNew)) +TestConstructFromCall(prototype, false, + Proxy.createFunction(handler, ReturnNewWithProto)) + +TestConstructFromCall(prototype, true, + Proxy.createFunction(handlerWithPrototype, ReturnUndef)) +TestConstructFromCall(prototype, true, + Proxy.createFunction(handlerWithPrototype, ReturnThis)) +TestConstructFromCall(Object.prototype, false, + Proxy.createFunction(handlerWithPrototype, ReturnNew)) +TestConstructFromCall(prototype, false, + Proxy.createFunction(handlerWithPrototype, + ReturnNewWithProto)) + +TestConstructFromCall(prototype, true, + CreateFrozen(handlerWithPrototype, ReturnUndef)) +TestConstructFromCall(prototype, true, + CreateFrozen(handlerWithPrototype, ReturnThis)) +TestConstructFromCall(Object.prototype, false, + CreateFrozen(handlerWithPrototype, ReturnNew)) +TestConstructFromCall(prototype, false, + CreateFrozen(handlerWithPrototype, ReturnNewWithProto)) + + + +// Throwing from the construct trap. + +function TestConstructThrow(trap) { + TestConstructThrow2(Proxy.createFunction({ fix: function() {return {};} }, + trap)) + TestConstructThrow2(Proxy.createFunction({ fix: function() {return {};} }, + function() {}, + trap)) +} + +function TestConstructThrow2(f) { + assertThrows(function(){ new f(11) }, "myexn") + Object.freeze(f) + assertThrows(function(){ new f(11) }, "myexn") +} + +TestConstructThrow(function() { throw "myexn" }) +TestConstructThrow(Proxy.createFunction({}, function() { throw "myexn" })) +TestConstructThrow(CreateFrozen({}, function() { throw "myexn" })) + + + +// Using function proxies as getters and setters. + +var value +var receiver + +function TestAccessorCall(getterCallTrap, setterCallTrap) { + var handler = { fix: function() { return {} } } + var pgetter = Proxy.createFunction(handler, getterCallTrap) + var psetter = Proxy.createFunction(handler, setterCallTrap) + + var o = {} + var oo = Object.create(o) + Object.defineProperty(o, "a", {get: pgetter, set: psetter}) + Object.defineProperty(o, "b", {get: pgetter}) + Object.defineProperty(o, "c", {set: psetter}) + Object.defineProperty(o, "3", {get: pgetter, set: psetter}) + Object.defineProperty(oo, "a", {value: 43}) + + receiver = "" + assertEquals(42, o.a) + assertSame(o, receiver) + receiver = "" + assertEquals(42, o.b) + assertSame(o, receiver) + receiver = "" + assertEquals(undefined, o.c) + assertEquals("", receiver) + receiver = "" + assertEquals(42, o["a"]) + assertSame(o, receiver) + receiver = "" + assertEquals(42, o[3]) + assertSame(o, receiver) + + receiver = "" + assertEquals(43, oo.a) + assertEquals("", receiver) + receiver = "" + assertEquals(42, oo.b) + assertSame(oo, receiver) + receiver = "" + assertEquals(undefined, oo.c) + assertEquals("", receiver) + receiver = "" + assertEquals(43, oo["a"]) + assertEquals("", receiver) + receiver = "" + assertEquals(42, oo[3]) + assertSame(oo, receiver) + + receiver = "" + assertEquals(50, o.a = 50) + assertSame(o, receiver) + assertEquals(50, value) + receiver = "" + assertEquals(51, o.b = 51) + assertEquals("", receiver) + assertEquals(50, value) // no setter + assertThrows(function() { "use strict"; o.b = 51 }, TypeError) + receiver = "" + assertEquals(52, o.c = 52) + assertSame(o, receiver) + assertEquals(52, value) + receiver = "" + assertEquals(53, o["a"] = 53) + assertSame(o, receiver) + assertEquals(53, value) + receiver = "" + assertEquals(54, o[3] = 54) + assertSame(o, receiver) + assertEquals(54, value) + + value = 0 + receiver = "" + assertEquals(60, oo.a = 60) + assertEquals("", receiver) + assertEquals(0, value) // oo has own 'a' + assertEquals(61, oo.b = 61) + assertSame("", receiver) + assertEquals(0, value) // no setter + assertThrows(function() { "use strict"; oo.b = 61 }, TypeError) + receiver = "" + assertEquals(62, oo.c = 62) + assertSame(oo, receiver) + assertEquals(62, value) + receiver = "" + assertEquals(63, oo["c"] = 63) + assertSame(oo, receiver) + assertEquals(63, value) + receiver = "" + assertEquals(64, oo[3] = 64) + assertSame(oo, receiver) + assertEquals(64, value) +} + +TestAccessorCall( + function() { receiver = this; return 42 }, + function(x) { receiver = this; value = x } +) + +TestAccessorCall( + function() { "use strict"; receiver = this; return 42 }, + function(x) { "use strict"; receiver = this; value = x } +) + +TestAccessorCall( + Proxy.createFunction({}, function() { receiver = this; return 42 }), + Proxy.createFunction({}, function(x) { receiver = this; value = x }) +) + +TestAccessorCall( + CreateFrozen({}, function() { receiver = this; return 42 }), + CreateFrozen({}, function(x) { receiver = this; value = x }) +) + + + +// TODO(rossberg): Ultimately, I want to have the following test function +// run through, but it currently fails on so many cases (some not even +// involving proxies), that I leave that for later... +/* +function TestCalls() { + var handler = { + get: function(r, k) { + return k == "length" ? 2 : Function.prototype[k] + } + } + var bind = Function.prototype.bind + var o = {} + + var traps = [ + function(x, y) { + return {receiver: this, result: x + y, strict: false} + }, + function(x, y) { "use strict"; + return {receiver: this, result: x + y, strict: true} + }, + function() { + var x = arguments[0], y = arguments[1] + return {receiver: this, result: x + y, strict: false} + }, + Proxy.createFunction(handler, function(x, y) { + return {receiver: this, result: x + y, strict: false} + }), + Proxy.createFunction(handler, function() { + var x = arguments[0], y = arguments[1] + return {receiver: this, result: x + y, strict: false} + }), + Proxy.createFunction(handler, function(x, y) { "use strict" + return {receiver: this, result: x + y, strict: true} + }), + CreateFrozen(handler, function(x, y) { + return {receiver: this, result: x + y, strict: false} + }), + CreateFrozen(handler, function(x, y) { "use strict" + return {receiver: this, result: x + y, strict: true} + }), + ] + var creates = [ + function(trap) { return trap }, + function(trap) { return CreateFrozen({}, callTrap) }, + function(trap) { return Proxy.createFunction(handler, callTrap) }, + function(trap) { + return Proxy.createFunction(handler, CreateFrozen({}, callTrap)) + }, + function(trap) { + return Proxy.createFunction(handler, Proxy.createFunction(handler, callTrap)) + }, + ] + var binds = [ + function(f, o, x, y) { return f }, + function(f, o, x, y) { return bind.call(f, o) }, + function(f, o, x, y) { return bind.call(f, o, x) }, + function(f, o, x, y) { return bind.call(f, o, x, y) }, + function(f, o, x, y) { return bind.call(f, o, x, y, 5) }, + function(f, o, x, y) { return bind.call(bind.call(f, o), {}, x, y) }, + function(f, o, x, y) { return bind.call(bind.call(f, o, x), {}, y) }, + function(f, o, x, y) { return bind.call(bind.call(f, o, x, y), {}, 5) }, + ] + var calls = [ + function(f, x, y) { return f(x, y) }, + function(f, x, y) { var g = f; return g(x, y) }, + function(f, x, y) { with ({}) return f(x, y) }, + function(f, x, y) { var g = f; with ({}) return g(x, y) }, + function(f, x, y, o) { with (o) return f(x, y) }, + function(f, x, y, o) { return f.call(o, x, y) }, + function(f, x, y, o) { return f.apply(o, [x, y]) }, + function(f, x, y, o) { return Function.prototype.call.call(f, o, x, y) }, + function(f, x, y, o) { return Function.prototype.apply.call(f, o, [x, y]) }, + function(f, x, y, o) { return %_CallFunction(o, x, y, f) }, + function(f, x, y, o) { return %Call(o, x, y, f) }, + function(f, x, y, o) { return %Apply(f, o, [null, x, y, null], 1, 2) }, + function(f, x, y, o) { return %Apply(f, o, arguments, 2, 2) }, + function(f, x, y, o) { if (typeof o == "object") return o.f(x, y) }, + function(f, x, y, o) { if (typeof o == "object") return o["f"](x, y) }, + function(f, x, y, o) { if (typeof o == "object") return (1, o).f(x, y) }, + function(f, x, y, o) { if (typeof o == "object") return (1, o)["f"](x, y) }, + ] + var receivers = [o, global_object, undefined, null, 2, "bla", true] + var expectedNonStricts = [o, global_object, global_object, global_object] + + for (var t = 0; t < traps.length; ++t) { + for (var i = 0; i < creates.length; ++i) { + for (var j = 0; j < binds.length; ++j) { + for (var k = 0; k < calls.length; ++k) { + for (var m = 0; m < receivers.length; ++m) { + for (var n = 0; n < receivers.length; ++n) { + var bound = receivers[m] + var receiver = receivers[n] + var func = binds[j](creates[i](traps[t]), bound, 31, 11) + var expected = j > 0 ? bound : receiver + var expectedNonStrict = expectedNonStricts[j > 0 ? m : n] + o.f = func + global_object.f = func + var x = calls[k](func, 11, 31, receiver) + if (x !== undefined) { + assertEquals(42, x.result) + if (calls[k].length < 4) + assertSame(x.strict ? undefined : global_object, x.receiver) + else if (x.strict) + assertSame(expected, x.receiver) + else if (expectedNonStrict === undefined) + assertSame(expected, x.receiver.valueOf()) + else + assertSame(expectedNonStrict, x.receiver) + } + } + } + } + } + } + } +} + +TestCalls() +*/ diff --git a/test/mjsunit/harmony/proxies-hash.js b/test/mjsunit/harmony/proxies-hash.js new file mode 100644 index 00000000..abfc0f5f --- /dev/null +++ b/test/mjsunit/harmony/proxies-hash.js @@ -0,0 +1,122 @@ +// Copyright 2011 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. + +// Flags: --harmony-proxies --harmony-collections + + +// Helper. + +function TestWithProxies(test, construct, handler) { + test(construct, handler, Proxy.create) + test(construct, handler, function(h) { + return Proxy.createFunction(h, function() {}) + }) +} + + +// Sets. + +function TestSet(construct, fix) { + TestWithProxies(TestSet2, construct, fix) +} + +function TestSet2(construct, fix, create) { + var handler = {fix: function() { return {} }} + var p1 = create(handler) + var p2 = create(handler) + var p3 = create(handler) + fix(p3) + + var s = construct(); + s.add(p1); + s.add(p2); + assertTrue(s.has(p1)); + assertTrue(s.has(p2)); + assertFalse(s.has(p3)); + + fix(p1) + fix(p2) + assertTrue(s.has(p1)); + assertTrue(s.has(p2)); + assertFalse(s.has(p3)); + + s.delete(p2); + assertTrue(s.has(p1)); + assertFalse(s.has(p2)); + assertFalse(s.has(p3)); +} + +TestSet(Set, Object.seal) +TestSet(Set, Object.freeze) +TestSet(Set, Object.preventExtensions) + + +// Maps and weak maps. + +function TestMap(construct, fix) { + TestWithProxies(TestMap2, construct, fix) +} + +function TestMap2(construct, fix, create) { + var handler = {fix: function() { return {} }} + var p1 = create(handler) + var p2 = create(handler) + var p3 = create(handler) + fix(p3) + + var m = construct(); + m.set(p1, 123); + m.set(p2, 321); + assertTrue(m.has(p1)); + assertTrue(m.has(p2)); + assertFalse(m.has(p3)); + assertSame(123, m.get(p1)); + assertSame(321, m.get(p2)); + + fix(p1) + fix(p2) + assertTrue(m.has(p1)); + assertTrue(m.has(p2)); + assertFalse(m.has(p3)); + assertSame(123, m.get(p1)); + assertSame(321, m.get(p2)); + + m.delete(p2); + assertTrue(m.has(p1)); + assertFalse(m.has(p2)); + assertFalse(m.has(p3)); + assertSame(123, m.get(p1)); + assertSame(undefined, m.get(p2)); +} + +TestMap(Map, Object.seal) +TestMap(Map, Object.freeze) +TestMap(Map, Object.preventExtensions) + +TestMap(WeakMap, Object.seal) +TestMap(WeakMap, Object.freeze) +TestMap(WeakMap, Object.preventExtensions) diff --git a/test/mjsunit/harmony/proxies.js b/test/mjsunit/harmony/proxies.js index 3c4e5f61..50c8613b 100644 --- a/test/mjsunit/harmony/proxies.js +++ b/test/mjsunit/harmony/proxies.js @@ -1,4 +1,4 @@ -// Copyright 2008 the V8 project authors. All rights reserved. +// Copyright 2011 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: @@ -28,70 +28,167 @@ // Flags: --harmony-proxies -// TODO(rossberg): for-in for proxies not implemented. -// TODO(rossberg): inheritance from proxies not implemented. -// TODO(rossberg): function proxies as constructors not implemented. +// Helper. +function TestWithProxies(test, x, y, z) { + test(Proxy.create, x, y, z) + test(function(h) {return Proxy.createFunction(h, function() {})}, x, y, z) +} -// Helper. -function TestWithProxies(test, handler) { - test(handler, Proxy.create) - test(handler, function(h) {return Proxy.createFunction(h, function() {})}) + +// Getting property descriptors (Object.getOwnPropertyDescriptor). + +var key + +function TestGetOwnProperty(handler) { + TestWithProxies(TestGetOwnProperty2, handler) +} + +function TestGetOwnProperty2(create, handler) { + var p = create(handler) + assertEquals(42, Object.getOwnPropertyDescriptor(p, "a").value) + assertEquals("a", key) + assertEquals(42, Object.getOwnPropertyDescriptor(p, 99).value) + assertEquals("99", key) +} + +TestGetOwnProperty({ + getOwnPropertyDescriptor: function(k) { + key = k + return {value: 42, configurable: true} + } +}) + +TestGetOwnProperty({ + getOwnPropertyDescriptor: function(k) { + return this.getOwnPropertyDescriptor2(k) + }, + getOwnPropertyDescriptor2: function(k) { + key = k + return {value: 42, configurable: true} + } +}) + +TestGetOwnProperty({ + getOwnPropertyDescriptor: function(k) { + key = k + return {get value() { return 42 }, get configurable() { return true }} + } +}) + +TestGetOwnProperty(Proxy.create({ + get: function(pr, pk) { + return function(k) { key = k; return {value: 42, configurable: true} } + } +})) + + +function TestGetOwnPropertyThrow(handler) { + TestWithProxies(TestGetOwnPropertyThrow2, handler) +} + +function TestGetOwnPropertyThrow2(create, handler) { + var p = create(handler) + assertThrows(function(){ Object.getOwnPropertyDescriptor(p, "a") }, "myexn") + assertThrows(function(){ Object.getOwnPropertyDescriptor(p, 77) }, "myexn") } +TestGetOwnPropertyThrow({ + getOwnPropertyDescriptor: function(k) { throw "myexn" } +}) + +TestGetOwnPropertyThrow({ + getOwnPropertyDescriptor: function(k) { + return this.getPropertyDescriptor2(k) + }, + getOwnPropertyDescriptor2: function(k) { throw "myexn" } +}) + +TestGetOwnPropertyThrow({ + getOwnPropertyDescriptor: function(k) { + return {get value() { throw "myexn" }} + } +}) + +TestGetOwnPropertyThrow(Proxy.create({ + get: function(pr, pk) { + return function(k) { throw "myexn" } + } +})) + + -// Getters. +// Getters (dot, brackets). + +var key function TestGet(handler) { TestWithProxies(TestGet2, handler) } -function TestGet2(handler, create) { +function TestGet2(create, handler) { var p = create(handler) assertEquals(42, p.a) + assertEquals("a", key) assertEquals(42, p["b"]) + assertEquals("b", key) + assertEquals(42, p[99]) + assertEquals("99", key) + assertEquals(42, (function(n) { return p[n] })("c")) + assertEquals("c", key) + assertEquals(42, (function(n) { return p[n] })(101)) + assertEquals("101", key) - // TODO(rossberg): inheritance from proxies not yet implemented. - // var o = Object.create(p, {x: {value: 88}}) - // assertEquals(42, o.a) - // assertEquals(42, o["b"]) - // assertEquals(88, o.x) - // assertEquals(88, o["x"]) + var o = Object.create(p, {x: {value: 88}}) + assertEquals(42, o.a) + assertEquals("a", key) + assertEquals(42, o["b"]) + assertEquals("b", key) + assertEquals(42, o[99]) + assertEquals("99", key) + assertEquals(88, o.x) + assertEquals(88, o["x"]) + assertEquals(42, (function(n) { return o[n] })("c")) + assertEquals("c", key) + assertEquals(42, (function(n) { return o[n] })(101)) + assertEquals("101", key) + assertEquals(88, (function(n) { return o[n] })("x")) } TestGet({ - get: function(r, k) { return 42 } + get: function(r, k) { key = k; return 42 } }) TestGet({ get: function(r, k) { return this.get2(r, k) }, - get2: function(r, k) { return 42 } + get2: function(r, k) { key = k; return 42 } }) TestGet({ - getPropertyDescriptor: function(k) { return {value: 42} } + getPropertyDescriptor: function(k) { key = k; return {value: 42} } }) TestGet({ getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) }, - getPropertyDescriptor2: function(k) { return {value: 42} } + getPropertyDescriptor2: function(k) { key = k; return {value: 42} } }) TestGet({ getPropertyDescriptor: function(k) { + key = k; return {get value() { return 42 }} } }) TestGet({ get: undefined, - getPropertyDescriptor: function(k) { return {value: 42} } + getPropertyDescriptor: function(k) { key = k; return {value: 42} } }) TestGet(Proxy.create({ get: function(pr, pk) { - return function(r, k) { return 42 } + return function(r, k) { key = k; return 42 } } })) @@ -100,14 +197,43 @@ function TestGetCall(handler) { TestWithProxies(TestGetCall2, handler) } -function TestGetCall2(handler, create) { +function TestGetCall2(create, handler) { var p = create(handler) assertEquals(55, p.f()) + assertEquals(55, p["f"]()) assertEquals(55, p.f("unused", "arguments")) assertEquals(55, p.f.call(p)) + assertEquals(55, p["f"].call(p)) + assertEquals(55, p[101].call(p)) assertEquals(55, p.withargs(45, 5)) assertEquals(55, p.withargs.call(p, 11, 22)) + assertEquals(55, (function(n) { return p[n]() })("f")) + assertEquals(55, (function(n) { return p[n].call(p) })("f")) + assertEquals(55, (function(n) { return p[n](15, 20) })("withargs")) + assertEquals(55, (function(n) { return p[n].call(p, 13, 21) })("withargs")) assertEquals("6655", "66" + p) // calls p.toString + + var o = Object.create(p, {g: {value: function(x) { return x + 88 }}}) + assertEquals(55, o.f()) + assertEquals(55, o["f"]()) + assertEquals(55, o.f("unused", "arguments")) + assertEquals(55, o.f.call(o)) + assertEquals(55, o.f.call(p)) + assertEquals(55, o["f"].call(p)) + assertEquals(55, o[101].call(p)) + assertEquals(55, o.withargs(45, 5)) + assertEquals(55, o.withargs.call(p, 11, 22)) + assertEquals(90, o.g(2)) + assertEquals(91, o.g.call(o, 3)) + assertEquals(92, o.g.call(p, 4)) + assertEquals(55, (function(n) { return o[n]() })("f")) + assertEquals(55, (function(n) { return o[n].call(o) })("f")) + assertEquals(55, (function(n) { return o[n](15, 20) })("withargs")) + assertEquals(55, (function(n) { return o[n].call(o, 13, 21) })("withargs")) + assertEquals(93, (function(n) { return o[n](5) })("g")) + assertEquals(94, (function(n) { return o[n].call(o, 6) })("g")) + assertEquals(95, (function(n) { return o[n].call(p, 7) })("g")) + assertEquals("6655", "66" + o) // calls o.toString } TestGetCall({ @@ -168,10 +294,20 @@ function TestGetThrow(handler) { TestWithProxies(TestGetThrow2, handler) } -function TestGetThrow2(handler, create) { +function TestGetThrow2(create, handler) { var p = create(handler) assertThrows(function(){ p.a }, "myexn") assertThrows(function(){ p["b"] }, "myexn") + assertThrows(function(){ p[3] }, "myexn") + assertThrows(function(){ (function(n) { p[n] })("c") }, "myexn") + assertThrows(function(){ (function(n) { p[n] })(99) }, "myexn") + + var o = Object.create(p, {x: {value: 88}, '4': {value: 89}}) + assertThrows(function(){ o.a }, "myexn") + assertThrows(function(){ o["b"] }, "myexn") + assertThrows(function(){ o[3] }, "myexn") + assertThrows(function(){ (function(n) { o[n] })("c") }, "myexn") + assertThrows(function(){ (function(n) { o[n] })(99) }, "myexn") } TestGetThrow({ @@ -220,11 +356,11 @@ TestGetThrow(Proxy.create({ var key var val -function TestSet(handler, create) { +function TestSet(handler) { TestWithProxies(TestSet2, handler) } -function TestSet2(handler, create) { +function TestSet2(create, handler) { var p = create(handler) assertEquals(42, p.a = 42) assertEquals("a", key) @@ -232,6 +368,16 @@ function TestSet2(handler, create) { assertEquals(43, p["b"] = 43) assertEquals("b", key) assertEquals(43, val) + assertEquals(44, p[77] = 44) + assertEquals("77", key) + assertEquals(44, val) + + assertEquals(45, (function(n) { return p[n] = 45 })("c")) + assertEquals("c", key) + assertEquals(45, val) + assertEquals(46, (function(n) { return p[n] = 46 })(99)) + assertEquals("99", key) + assertEquals(46, val) } TestSet({ @@ -304,15 +450,17 @@ TestSet(Proxy.create({ })) - -function TestSetThrow(handler, create) { +function TestSetThrow(handler) { TestWithProxies(TestSetThrow2, handler) } -function TestSetThrow2(handler, create) { +function TestSetThrow2(create, handler) { var p = create(handler) assertThrows(function(){ p.a = 42 }, "myexn") assertThrows(function(){ p["b"] = 42 }, "myexn") + assertThrows(function(){ p[22] = 42 }, "myexn") + assertThrows(function(){ (function(n) { p[n] = 45 })("c") }, "myexn") + assertThrows(function(){ (function(n) { p[n] = 46 })(99) }, "myexn") } TestSetThrow({ @@ -424,6 +572,124 @@ TestSetThrow(Proxy.create({ })) +var key +var val + +function TestSetForDerived(handler) { + TestWithProxies(TestSetForDerived2, handler) +} + +function TestSetForDerived2(create, handler) { + var p = create(handler) + var o = Object.create(p, {x: {value: 88, writable: true}, + '1': {value: 89, writable: true}}) + + key = "" + assertEquals(48, o.x = 48) + assertEquals("", key) // trap not invoked + assertEquals(48, o.x) + + assertEquals(47, o[1] = 47) + assertEquals("", key) // trap not invoked + assertEquals(47, o[1]) + + assertEquals(49, o.y = 49) + assertEquals("y", key) + assertEquals(49, o.y) + + assertEquals(50, o[2] = 50) + assertEquals("2", key) + assertEquals(50, o[2]) + + assertEquals(44, o.p_writable = 44) + assertEquals("p_writable", key) + assertEquals(44, o.p_writable) + + assertEquals(45, o.p_nonwritable = 45) + assertEquals("p_nonwritable", key) + assertEquals(45, o.p_nonwritable) + + assertEquals(46, o.p_setter = 46) + assertEquals("p_setter", key) + assertEquals(46, val) // written to parent + assertFalse(Object.prototype.hasOwnProperty.call(o, "p_setter")) + + val = "" + assertEquals(47, o.p_nosetter = 47) + assertEquals("p_nosetter", key) + assertEquals("", val) // not written at all + assertFalse(Object.prototype.hasOwnProperty.call(o, "p_nosetter")); + + key = "" + assertThrows(function(){ "use strict"; o.p_nosetter = 50 }, TypeError) + assertEquals("p_nosetter", key) + assertEquals("", val) // not written at all + + assertThrows(function(){ o.p_nonconf = 53 }, TypeError) + assertEquals("p_nonconf", key) + + assertThrows(function(){ o.p_throw = 51 }, "myexn") + assertEquals("p_throw", key) + + assertThrows(function(){ o.p_setterthrow = 52 }, "myexn") + assertEquals("p_setterthrow", key) +} + +TestSetForDerived({ + getPropertyDescriptor: function(k) { + key = k; + switch (k) { + case "p_writable": return {writable: true, configurable: true} + case "p_nonwritable": return {writable: false, configurable: true} + case "p_setter":return {set: function(x) { val = x }, configurable: true} + case "p_nosetter": return {get: function() { return 1 }, configurable: true} + case "p_nonconf":return {} + case "p_throw": throw "myexn" + case "p_setterthrow": return {set: function(x) { throw "myexn" }} + default: return undefined + } + } +}) + + +// Evil proxy-induced side-effects shouldn't crash. +// TODO(rossberg): proper behaviour isn't really spec'ed yet, so ignore results. + +TestWithProxies(function(create) { + var calls = 0 + var handler = { + getPropertyDescriptor: function() { + ++calls + return (calls % 2 == 1) + ? {get: function() { return 5 }, configurable: true} + : {set: function() { return false }, configurable: true} + } + } + var p = create(handler) + var o = Object.create(p) + // Make proxy prototype property read-only after CanPut check. + try { o.x = 4 } catch (e) { assertInstanceof(e, Error) } +}) + +TestWithProxies(function(create) { + var handler = { + getPropertyDescriptor: function() { + Object.defineProperty(o, "x", {get: function() { return 5 }}); + return {set: function() {}} + } + } + var p = create(handler) + var o = Object.create(p) + // Make object property read-only after CanPut check. + try { o.x = 4 } catch (e) { assertInstanceof(e, Error) } +}) + + + +// TODO(rossberg): TestSetReject, returning false +// TODO(rossberg): TestGetProperty, TestSetProperty + + // Property definition (Object.defineProperty and Object.defineProperties). @@ -434,7 +700,7 @@ function TestDefine(handler) { TestWithProxies(TestDefine2, handler) } -function TestDefine2(handler, create) { +function TestDefine2(create, handler) { var p = create(handler) assertEquals(p, Object.defineProperty(p, "a", {value: 44})) assertEquals("a", key) @@ -453,6 +719,12 @@ function TestDefine2(handler, create) { assertEquals(46, desc.value) assertEquals(false, desc.enumerable) + assertEquals(p, Object.defineProperty(p, 101, {value: 47, enumerable: false})) + assertEquals("101", key) + assertEquals(2, Object.getOwnPropertyNames(desc).length) + assertEquals(47, desc.value) + assertEquals(false, desc.enumerable) + var attributes = {configurable: true, mine: 66, minetoo: 23} assertEquals(p, Object.defineProperty(p, "d", attributes)) assertEquals("d", key) @@ -474,20 +746,20 @@ function TestDefine2(handler, create) { assertEquals("zzz", key) assertEquals(0, Object.getOwnPropertyNames(desc).length) -// TODO(rossberg): This test requires for-in on proxies. -// var d = create({ -// get: function(r, k) { return (k === "value") ? 77 : void 0 }, -// getOwnPropertyNames: function() { return ["value"] } -// }) -// assertEquals(1, Object.getOwnPropertyNames(d).length) -// assertEquals(77, d.value) -// assertEquals(p, Object.defineProperty(p, "p", d)) -// assertEquals("p", key) -// assertEquals(1, Object.getOwnPropertyNames(desc).length) -// assertEquals(77, desc.value) + var d = create({ + get: function(r, k) { return (k === "value") ? 77 : void 0 }, + getOwnPropertyNames: function() { return ["value"] }, + enumerate: function() { return ["value"] } + }) + assertEquals(1, Object.getOwnPropertyNames(d).length) + assertEquals(77, d.value) + assertEquals(p, Object.defineProperty(p, "p", d)) + assertEquals("p", key) + assertEquals(1, Object.getOwnPropertyNames(desc).length) + assertEquals(77, desc.value) var props = { - 'bla': {}, + '11': {}, blub: {get: function() { return true }}, '': {get value() { return 20 }}, last: {value: 21, configurable: true, mine: "eyes"} @@ -524,21 +796,21 @@ function TestDefineThrow(handler) { TestWithProxies(TestDefineThrow2, handler) } -function TestDefineThrow2(handler, create) { +function TestDefineThrow2(create, handler) { var p = create(handler) assertThrows(function(){ Object.defineProperty(p, "a", {value: 44})}, "myexn") - -// TODO(rossberg): These tests require for-in on proxies. -// var d1 = create({ -// get: function(r, k) { throw "myexn" }, -// getOwnPropertyNames: function() { return ["value"] } -// }) -// assertThrows(function(){ Object.defineProperty(p, "p", d1) }, "myexn") -// var d2 = create({ -// get: function(r, k) { return 77 }, -// getOwnPropertyNames: function() { throw "myexn" } -// }) -// assertThrows(function(){ Object.defineProperty(p, "p", d2) }, "myexn") + assertThrows(function(){ Object.defineProperty(p, 0, {value: 44})}, "myexn") + + var d1 = create({ + get: function(r, k) { throw "myexn" }, + getOwnPropertyNames: function() { return ["value"] } + }) + assertThrows(function(){ Object.defineProperty(p, "p", d1) }, "myexn") + var d2 = create({ + get: function(r, k) { return 77 }, + getOwnPropertyNames: function() { throw "myexn" } + }) + assertThrows(function(){ Object.defineProperty(p, "p", d2) }, "myexn") var props = {bla: {get value() { throw "otherexn" }}} assertThrows(function(){ Object.defineProperties(p, props) }, "otherexn") @@ -573,12 +845,14 @@ function TestDelete(handler) { TestWithProxies(TestDelete2, handler) } -function TestDelete2(handler, create) { +function TestDelete2(create, handler) { var p = create(handler) assertEquals(true, delete p.a) assertEquals("a", key) assertEquals(true, delete p["b"]) assertEquals("b", key) + assertEquals(true, delete p[1]) + assertEquals("1", key) assertEquals(false, delete p.z1) assertEquals("z1", key) @@ -591,6 +865,8 @@ function TestDelete2(handler, create) { assertEquals("c", key) assertEquals(true, delete p["d"]) assertEquals("d", key) + assertEquals(true, delete p[2]) + assertEquals("2", key) assertThrows(function(){ delete p.z3 }, TypeError) assertEquals("z3", key) @@ -619,15 +895,17 @@ function TestDeleteThrow(handler) { TestWithProxies(TestDeleteThrow2, handler) } -function TestDeleteThrow2(handler, create) { +function TestDeleteThrow2(create, handler) { var p = create(handler) assertThrows(function(){ delete p.a }, "myexn") assertThrows(function(){ delete p["b"] }, "myexn"); + assertThrows(function(){ delete p[3] }, "myexn"); (function() { "use strict" assertThrows(function(){ delete p.c }, "myexn") assertThrows(function(){ delete p["d"] }, "myexn") + assertThrows(function(){ delete p[4] }, "myexn"); })() } @@ -658,7 +936,7 @@ function TestDescriptor(handler) { TestWithProxies(TestDescriptor2, handler) } -function TestDescriptor2(handler, create) { +function TestDescriptor2(create, handler) { var p = create(handler) var descs = [ {configurable: true}, @@ -697,7 +975,7 @@ function TestDescriptorThrow(handler) { TestWithProxies(TestDescriptorThrow2, handler) } -function TestDescriptorThrow2(handler, create) { +function TestDescriptorThrow2(create, handler) { var p = create(handler) assertThrows(function(){ Object.getOwnPropertyDescriptor(p, "a") }, "myexn") } @@ -721,7 +999,7 @@ function TestComparison(eq) { TestWithProxies(TestComparison2, eq) } -function TestComparison2(eq, create) { +function TestComparison2(create, eq) { var p1 = create({}) var p2 = create({}) @@ -764,7 +1042,7 @@ function TestIn(handler) { TestWithProxies(TestIn2, handler) } -function TestIn2(handler, create) { +function TestIn2(create, handler) { var p = create(handler) assertTrue("a" in p) assertEquals("a", key) @@ -778,6 +1056,7 @@ function TestIn2(handler, create) { assertEquals(0, ("zzz" in p) ? 2 : 0) assertEquals(2, !("zzz" in p) ? 2 : 0) + // Test compilation in conditionals. if ("b" in p) { } else { assertTrue(false) @@ -830,7 +1109,7 @@ TestIn({ }) TestIn({ - get: undefined, + has: undefined, getPropertyDescriptor: function(k) { key = k; return k < "z" ? {value: 42} : void 0 } @@ -847,9 +1126,10 @@ function TestInThrow(handler) { TestWithProxies(TestInThrow2, handler) } -function TestInThrow2(handler, create) { +function TestInThrow2(create, handler) { var p = create(handler) assertThrows(function(){ return "a" in o }, "myexn") + assertThrows(function(){ return 99 in o }, "myexn") assertThrows(function(){ return !("a" in o) }, "myexn") assertThrows(function(){ return ("a" in o) ? 2 : 3 }, "myexn") assertThrows(function(){ if ("b" in o) {} }, "myexn") @@ -876,7 +1156,7 @@ TestInThrow({ }) TestInThrow({ - get: undefined, + has: undefined, getPropertyDescriptor: function(k) { throw "myexn" } }) @@ -891,6 +1171,158 @@ TestInThrow(Proxy.create({ })) +function TestInForDerived(handler) { + TestWithProxies(TestInForDerived2, handler) +} + +function TestInForDerived2(create, handler) { + var p = create(handler) + var o = Object.create(p) + + assertTrue("a" in o) + assertEquals("a", key) + assertTrue(99 in o) + assertEquals("99", key) + assertFalse("z" in o) + assertEquals("z", key) + + assertEquals(2, ("a" in o) ? 2 : 0) + assertEquals(0, !("a" in o) ? 2 : 0) + assertEquals(0, ("zzz" in o) ? 2 : 0) + assertEquals(2, !("zzz" in o) ? 2 : 0) + + if ("b" in o) { + } else { + assertTrue(false) + } + assertEquals("b", key) + + if ("zz" in o) { + assertTrue(false) + } + assertEquals("zz", key) + + if (!("c" in o)) { + assertTrue(false) + } + assertEquals("c", key) + + if (!("zzz" in o)) { + } else { + assertTrue(false) + } + assertEquals("zzz", key) +} + +TestInForDerived({ + getPropertyDescriptor: function(k) { + key = k; return k < "z" ? {value: 42, configurable: true} : void 0 + } +}) + +TestInForDerived({ + getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) }, + getPropertyDescriptor2: function(k) { + key = k; return k < "z" ? {value: 42, configurable: true} : void 0 + } +}) + +TestInForDerived({ + getPropertyDescriptor: function(k) { + key = k; + return k < "z" ? {get value() { return 42 }, configurable: true} : void 0 + } +}) + +/* TODO(rossberg): this will work once we implement the newest proposal + * regarding default traps for getPropertyDescriptor. +TestInForDerived({ + getOwnPropertyDescriptor: function(k) { + key = k; return k < "z" ? {value: 42, configurable: true} : void 0 + } +}) + +TestInForDerived({ + getOwnPropertyDescriptor: function(k) { + return this.getOwnPropertyDescriptor2(k) + }, + getOwnPropertyDescriptor2: function(k) { + key = k; return k < "z" ? {value: 42, configurable: true} : void 0 + } +}) + +TestInForDerived({ + getOwnPropertyDescriptor: function(k) { + key = k; + return k < "z" ? {get value() { return 42 }, configurable: true} : void 0 + } +}) +*/ + +TestInForDerived(Proxy.create({ + get: function(pr, pk) { + return function(k) { + key = k; return k < "z" ? {value: 42, configurable: true} : void 0 + } + } +})) + + + +// Property descriptor conversion. + +var descget + +function TestDescriptorGetOrder(handler) { + var p = Proxy.create(handler) + var o = Object.create(p, {b: {value: 0}}) + TestDescriptorGetOrder2(function(n) { return p[n] }, "vV") + TestDescriptorGetOrder2(function(n) { return n in p }, "") + TestDescriptorGetOrder2(function(n) { return o[n] }, "vV") + TestDescriptorGetOrder2(function(n) { return n in o }, "eEcCvVwWgs") +} + +function TestDescriptorGetOrder2(f, access) { + descget = "" + assertTrue(f("a")) + assertEquals(access, descget) + descget = "" + assertTrue(f(99)) + assertEquals(access, descget) + descget = "" + assertFalse(!!f("z")) + assertEquals("", descget) +} + +TestDescriptorGetOrder({ + getPropertyDescriptor: function(k) { + if (k >= "z") return void 0 + // Return a proxy as property descriptor, so that we can log accesses. + return Proxy.create({ + get: function(r, attr) { + descget += attr[0].toUpperCase() + return true + }, + has: function(attr) { + descget += attr[0] + switch (attr) { + case "writable": + case "enumerable": + case "configurable": + case "value": + return true + case "get": + case "set": + return false + default: + assertUnreachable() + } + } + }) + } +}) + + // Own Properties (Object.prototype.hasOwnProperty). @@ -900,7 +1332,7 @@ function TestHasOwn(handler) { TestWithProxies(TestHasOwn2, handler) } -function TestHasOwn2(handler, create) { +function TestHasOwn2(create, handler) { var p = create(handler) assertTrue(Object.prototype.hasOwnProperty.call(p, "a")) assertEquals("a", key) @@ -958,7 +1390,7 @@ function TestHasOwnThrow(handler) { TestWithProxies(TestHasOwnThrow2, handler) } -function TestHasOwnThrow2(handler, create) { +function TestHasOwnThrow2(create, handler) { var p = create(handler) assertThrows(function(){ Object.prototype.hasOwnProperty.call(p, "a")}, "myexn") @@ -1005,84 +1437,173 @@ TestHasOwnThrow(Proxy.create({ // Instanceof (instanceof) -function TestInstanceof() { - var o = {} +function TestProxyInstanceof() { + var o1 = {} var p1 = Proxy.create({}) - var p2 = Proxy.create({}, o) + var p2 = Proxy.create({}, o1) var p3 = Proxy.create({}, p2) + var o2 = Object.create(p2) var f0 = function() {} - f0.prototype = o + f0.prototype = o1 var f1 = function() {} f1.prototype = p1 var f2 = function() {} f2.prototype = p2 - - assertTrue(o instanceof Object) - assertFalse(o instanceof f0) - assertFalse(o instanceof f1) - assertFalse(o instanceof f2) + var f3 = function() {} + f3.prototype = o2 + + assertTrue(o1 instanceof Object) + assertFalse(o1 instanceof f0) + assertFalse(o1 instanceof f1) + assertFalse(o1 instanceof f2) + assertFalse(o1 instanceof f3) assertFalse(p1 instanceof Object) assertFalse(p1 instanceof f0) assertFalse(p1 instanceof f1) assertFalse(p1 instanceof f2) + assertFalse(p1 instanceof f3) assertTrue(p2 instanceof Object) assertTrue(p2 instanceof f0) assertFalse(p2 instanceof f1) assertFalse(p2 instanceof f2) + assertFalse(p2 instanceof f3) assertTrue(p3 instanceof Object) assertTrue(p3 instanceof f0) assertFalse(p3 instanceof f1) assertTrue(p3 instanceof f2) + assertFalse(p3 instanceof f3) + assertTrue(o2 instanceof Object) + assertTrue(o2 instanceof f0) + assertFalse(o2 instanceof f1) + assertTrue(o2 instanceof f2) + assertFalse(o2 instanceof f3) var f = Proxy.createFunction({}, function() {}) assertTrue(f instanceof Function) } -TestInstanceof() +TestProxyInstanceof() + + +function TestInstanceofProxy() { + var o0 = Object.create(null) + var o1 = {} + var o2 = Object.create(o0) + var o3 = Object.create(o1) + var o4 = Object.create(o2) + var o5 = Object.create(o3) + + function handler(o) { return {get: function() { return o } } } + var f0 = Proxy.createFunction(handler(o0), function() {}) + var f1 = Proxy.createFunction(handler(o1), function() {}) + var f2 = Proxy.createFunction(handler(o2), function() {}) + var f3 = Proxy.createFunction(handler(o3), function() {}) + var f4 = Proxy.createFunction(handler(o4), function() {}) + var f5 = Proxy.createFunction(handler(o4), function() {}) + + assertFalse(null instanceof f0) + assertFalse(o0 instanceof f0) + assertFalse(o0 instanceof f1) + assertFalse(o0 instanceof f2) + assertFalse(o0 instanceof f3) + assertFalse(o0 instanceof f4) + assertFalse(o0 instanceof f5) + assertFalse(o1 instanceof f0) + assertFalse(o1 instanceof f1) + assertFalse(o1 instanceof f2) + assertFalse(o1 instanceof f3) + assertFalse(o1 instanceof f4) + assertFalse(o1 instanceof f5) + assertTrue(o2 instanceof f0) + assertFalse(o2 instanceof f1) + assertFalse(o2 instanceof f2) + assertFalse(o2 instanceof f3) + assertFalse(o2 instanceof f4) + assertFalse(o2 instanceof f5) + assertFalse(o3 instanceof f0) + assertTrue(o3 instanceof f1) + assertFalse(o3 instanceof f2) + assertFalse(o3 instanceof f3) + assertFalse(o3 instanceof f4) + assertFalse(o3 instanceof f5) + assertTrue(o4 instanceof f0) + assertFalse(o4 instanceof f1) + assertTrue(o4 instanceof f2) + assertFalse(o4 instanceof f3) + assertFalse(o4 instanceof f4) + assertFalse(o4 instanceof f5) + assertFalse(o5 instanceof f0) + assertTrue(o5 instanceof f1) + assertFalse(o5 instanceof f2) + assertTrue(o5 instanceof f3) + assertFalse(o5 instanceof f4) + assertFalse(o5 instanceof f5) + + var f = Proxy.createFunction({}, function() {}) + var ff = Proxy.createFunction(handler(Function), function() {}) + assertTrue(f instanceof Function) + assertFalse(f instanceof ff) +} + +TestInstanceofProxy() // Prototype (Object.getPrototypeOf, Object.prototype.isPrototypeOf). function TestPrototype() { - var o = {} + var o1 = {} var p1 = Proxy.create({}) - var p2 = Proxy.create({}, o) + var p2 = Proxy.create({}, o1) var p3 = Proxy.create({}, p2) - var p4 = Proxy.create({}, 666) + var p4 = Proxy.create({}, null) + var o2 = Object.create(p3) - assertSame(Object.getPrototypeOf(o), Object.prototype) + assertSame(Object.getPrototypeOf(o1), Object.prototype) assertSame(Object.getPrototypeOf(p1), null) - assertSame(Object.getPrototypeOf(p2), o) + assertSame(Object.getPrototypeOf(p2), o1) assertSame(Object.getPrototypeOf(p3), p2) assertSame(Object.getPrototypeOf(p4), null) + assertSame(Object.getPrototypeOf(o2), p3) - assertTrue(Object.prototype.isPrototypeOf(o)) + assertTrue(Object.prototype.isPrototypeOf(o1)) assertFalse(Object.prototype.isPrototypeOf(p1)) assertTrue(Object.prototype.isPrototypeOf(p2)) assertTrue(Object.prototype.isPrototypeOf(p3)) assertFalse(Object.prototype.isPrototypeOf(p4)) - assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, o)) + assertTrue(Object.prototype.isPrototypeOf(o2)) + assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, o1)) assertFalse(Object.prototype.isPrototypeOf.call(Object.prototype, p1)) assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p2)) assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p3)) assertFalse(Object.prototype.isPrototypeOf.call(Object.prototype, p4)) - assertFalse(Object.prototype.isPrototypeOf.call(o, o)) - assertFalse(Object.prototype.isPrototypeOf.call(o, p1)) - assertTrue(Object.prototype.isPrototypeOf.call(o, p2)) - assertTrue(Object.prototype.isPrototypeOf.call(o, p3)) - assertFalse(Object.prototype.isPrototypeOf.call(o, p4)) + assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, o2)) + assertFalse(Object.prototype.isPrototypeOf.call(o1, o1)) + assertFalse(Object.prototype.isPrototypeOf.call(o1, p1)) + assertTrue(Object.prototype.isPrototypeOf.call(o1, p2)) + assertTrue(Object.prototype.isPrototypeOf.call(o1, p3)) + assertFalse(Object.prototype.isPrototypeOf.call(o1, p4)) + assertTrue(Object.prototype.isPrototypeOf.call(o1, o2)) assertFalse(Object.prototype.isPrototypeOf.call(p1, p1)) - assertFalse(Object.prototype.isPrototypeOf.call(p1, o)) + assertFalse(Object.prototype.isPrototypeOf.call(p1, o1)) assertFalse(Object.prototype.isPrototypeOf.call(p1, p2)) assertFalse(Object.prototype.isPrototypeOf.call(p1, p3)) assertFalse(Object.prototype.isPrototypeOf.call(p1, p4)) + assertFalse(Object.prototype.isPrototypeOf.call(p1, o2)) assertFalse(Object.prototype.isPrototypeOf.call(p2, p1)) assertFalse(Object.prototype.isPrototypeOf.call(p2, p2)) assertTrue(Object.prototype.isPrototypeOf.call(p2, p3)) assertFalse(Object.prototype.isPrototypeOf.call(p2, p4)) + assertTrue(Object.prototype.isPrototypeOf.call(p2, o2)) assertFalse(Object.prototype.isPrototypeOf.call(p3, p2)) + assertTrue(Object.prototype.isPrototypeOf.call(p3, o2)) + assertFalse(Object.prototype.isPrototypeOf.call(o2, o1)) + assertFalse(Object.prototype.isPrototypeOf.call(o2, p1)) + assertFalse(Object.prototype.isPrototypeOf.call(o2, p2)) + assertFalse(Object.prototype.isPrototypeOf.call(o2, p3)) + assertFalse(Object.prototype.isPrototypeOf.call(o2, p4)) + assertFalse(Object.prototype.isPrototypeOf.call(o2, o2)) var f = Proxy.createFunction({}, function() {}) assertSame(Object.getPrototypeOf(f), Function.prototype) @@ -1097,12 +1618,12 @@ TestPrototype() // Property names (Object.getOwnPropertyNames, Object.keys). function TestPropertyNames(names, handler) { - TestWithProxies(TestPropertyNames2, [names, handler]) + TestWithProxies(TestPropertyNames2, handler, names) } -function TestPropertyNames2(names_handler, create) { - var p = create(names_handler[1]) - assertArrayEquals(names_handler[0], Object.getOwnPropertyNames(p)) +function TestPropertyNames2(create, handler, names) { + var p = create(handler) + assertArrayEquals(names, Object.getOwnPropertyNames(p)) } TestPropertyNames([], { @@ -1129,7 +1650,7 @@ function TestPropertyNamesThrow(handler) { TestWithProxies(TestPropertyNamesThrow2, handler) } -function TestPropertyNamesThrow2(handler, create) { +function TestPropertyNamesThrow2(create, handler) { var p = create(handler) assertThrows(function(){ Object.getOwnPropertyNames(p) }, "myexn") } @@ -1145,12 +1666,12 @@ TestPropertyNamesThrow({ function TestKeys(names, handler) { - TestWithProxies(TestKeys2, [names, handler]) + TestWithProxies(TestKeys2, handler, names) } -function TestKeys2(names_handler, create) { - var p = create(names_handler[1]) - assertArrayEquals(names_handler[0], Object.keys(p)) +function TestKeys2(create, handler, names) { + var p = create(handler) + assertArrayEquals(names, Object.keys(p)) } TestKeys([], { @@ -1174,7 +1695,9 @@ TestKeys(["[object Object]"], { TestKeys(["a", "0"], { getOwnPropertyNames: function() { return ["a", 23, "zz", "", 0] }, - getOwnPropertyDescriptor: function(k) { return {enumerable: k.length == 1} } + getOwnPropertyDescriptor: function(k) { + return k == "" ? undefined : {enumerable: k.length == 1} + } }) TestKeys(["23", "zz", ""], { @@ -1188,10 +1711,12 @@ TestKeys(["23", "zz", ""], { TestKeys(["a", "b", "c", "5"], { get getOwnPropertyNames() { - return function() { return ["0", 4, "a", "b", "c", 5] } + return function() { return ["0", 4, "a", "b", "c", 5, "ety"] } }, get getOwnPropertyDescriptor() { - return function(k) { return {enumerable: k >= "44"} } + return function(k) { + return k == "ety" ? undefined : {enumerable: k >= "44"} + } } }) @@ -1207,7 +1732,7 @@ function TestKeysThrow(handler) { TestWithProxies(TestKeysThrow2, handler) } -function TestKeysThrow2(handler, create) { +function TestKeysThrow2(create, handler) { var p = create(handler) assertThrows(function(){ Object.keys(p) }, "myexn") } @@ -1267,7 +1792,6 @@ TestKeysThrow([], { // Fixing (Object.freeze, Object.seal, Object.preventExtensions, // Object.isFrozen, Object.isSealed, Object.isExtensible) -// TODO(rossberg): use TestWithProxies to include funciton proxies function TestFix(names, handler) { var proto = {p: 77} var assertFixing = function(o, s, f, e) { @@ -1314,19 +1838,27 @@ function TestFix(names, handler) { Object.keys(p3).sort()) assertEquals(proto, Object.getPrototypeOf(p3)) assertEquals(77, p3.p) + + var p = Proxy.create(handler, proto) + var o = Object.create(p) + assertFixing(p, false, false, true) + assertFixing(o, false, false, true) + Object.freeze(o) + assertFixing(p, false, false, true) + assertFixing(o, true, true, false) } TestFix([], { fix: function() { return {} } }) -TestFix(["a", "b", "c", "d", "zz"], { +TestFix(["a", "b", "c", "3", "zz"], { fix: function() { return { a: {value: "a", writable: true, configurable: false, enumerable: true}, b: {value: 33, writable: false, configurable: false, enumerable: true}, c: {value: 0, writable: true, configurable: true, enumerable: true}, - d: {value: true, writable: false, configurable: true, enumerable: true}, + '3': {value: true, writable: false, configurable: true, enumerable: true}, zz: {value: 0, enumerable: false} } } @@ -1377,8 +1909,8 @@ function TestFixThrow(handler) { TestWithProxies(TestFixThrow2, handler) } -function TestFixThrow2(handler) { - var p = Proxy.create(handler, {}) +function TestFixThrow2(create, handler) { + var p = create(handler, {}) assertThrows(function(){ Object.seal(p) }, "myexn") assertThrows(function(){ Object.freeze(p) }, "myexn") assertThrows(function(){ Object.preventExtensions(p) }, "myexn") @@ -1404,6 +1936,135 @@ TestFixThrow({ }) +// Freeze a proxy in the middle of operations on it. +// TODO(rossberg): actual behaviour not specified consistently at the moment, +// just make sure that we do not crash. +function TestReentrantFix(f) { + TestWithProxies(f, Object.freeze) + TestWithProxies(f, Object.seal) + TestWithProxies(f, Object.preventExtensions) +} + +TestReentrantFix(function(create, freeze) { + var handler = { + get get() { freeze(p); return undefined }, + fix: function() { return {} } + } + var p = create(handler) + // Freeze while getting get trap. + try { p.x } catch (e) { assertInstanceof(e, Error) } +}) + +TestReentrantFix(function(create, freeze) { + var handler = { + get: function() { freeze(p); return 3 }, + fix: function() { return {} } + } + var p = create(handler) + // Freeze while executing get trap. + try { p.x } catch (e) { assertInstanceof(e, Error) } +}) + +TestReentrantFix(function(create, freeze) { + var handler = { + getPropertyDescriptor: function() { freeze(p); return undefined }, + fix: function() { return {} } + } + var p = create(handler) + // Freeze while executing default get trap. + try { p.x } catch (e) { assertInstanceof(e, Error) } +}) + +TestReentrantFix(function(create, freeze) { + var handler = { + getPropertyDescriptor: function() { freeze(p); return {get: function(){}} }, + fix: function() { return {} } + } + var p = create(handler) + var o = Object.create(p) + // Freeze while getting a property from prototype. + try { o.x } catch (e) { assertInstanceof(e, Error) } +}) + +TestReentrantFix(function(create, freeze) { + var handler = { + get set() { freeze(p); return undefined }, + fix: function() { return {} } + } + var p = create(handler) + // Freeze while getting set trap. + try { p.x = 4 } catch (e) { assertInstanceof(e, Error) } +}) + +TestReentrantFix(function(create, freeze) { + var handler = { + set: function() { freeze(p); return true }, + fix: function() { return {} } + } + var p = create(handler) + // Freeze while executing set trap. + try { p.x = 4 } catch (e) { assertInstanceof(e, Error) } +}) + +TestReentrantFix(function(create, freeze) { + var handler = { + getOwnPropertyDescriptor: function() { freeze(p); return undefined }, + fix: function() { return {} } + } + var p = create(handler) + // Freeze while executing default set trap. + try { p.x } catch (e) { assertInstanceof(e, Error) } +}) + +TestReentrantFix(function(create, freeze) { + var handler = { + getPropertyDescriptor: function() { freeze(p); return {set: function(){}} }, + fix: function() { return {} } + } + var p = create(handler) + var o = Object.create(p) + // Freeze while setting a property in prototype, dropping the property! + try { o.x = 4 } catch (e) { assertInstanceof(e, Error) } +}) + +TestReentrantFix(function(create, freeze) { + var handler = { + getPropertyDescriptor: function() { freeze(p); return {set: function(){}} }, + fix: function() { return {x: {get: function(){}}} } + } + var p = create(handler) + var o = Object.create(p) + // Freeze while setting a property in prototype, making it read-only! + try { o.x = 4 } catch (e) { assertInstanceof(e, Error) } +}) + +TestReentrantFix(function(create, freeze) { + var handler = { + get fix() { freeze(p); return function(){} } + } + var p = create(handler) + // Freeze while getting fix trap. + try { Object.freeze(p) } catch (e) { assertInstanceof(e, Error) } + p = create(handler) + try { Object.seal(p) } catch (e) { assertInstanceof(e, Error) } + p = create(handler) + try { Object.preventExtensions(p) } catch (e) { assertInstanceof(e, Error) } +}) + +TestReentrantFix(function(create, freeze) { + var handler = { + fix: function() { freeze(p); return {} } + } + var p = create(handler) + // Freeze while executing fix trap. + try { Object.freeze(p) } catch (e) { assertInstanceof(e, Error) } + p = create(handler) + try { Object.seal(p) } catch (e) { assertInstanceof(e, Error) } + p = create(handler) + try { Object.preventExtensions(p) } catch (e) { assertInstanceof(e, Error) } +}) + + // String conversion (Object.prototype.toString, // Object.prototype.toLocaleString, @@ -1426,6 +2087,13 @@ function TestToString(handler) { assertEquals("my_proxy", Object.prototype.toLocaleString.call(f)) assertEquals("toString", key) assertDoesNotThrow(function(){ Function.prototype.toString.call(f) }) + + var o = Object.create(p) + key = "" + assertEquals("[object Object]", Object.prototype.toString.call(o)) + assertEquals("", key) + assertEquals("my_proxy", Object.prototype.toLocaleString.call(o)) + assertEquals("toString", key) } TestToString({ @@ -1452,6 +2120,10 @@ function TestToStringThrow(handler) { var f = Proxy.createFunction(handler, function() {}) assertEquals("[object Function]", Object.prototype.toString.call(f)) assertThrows(function(){ Object.prototype.toLocaleString.call(f) }, "myexn") + + var o = Object.create(p) + assertEquals("[object Object]", Object.prototype.toString.call(o)) + assertThrows(function(){ Object.prototype.toLocaleString.call(o) }, "myexn") } TestToStringThrow({ @@ -1485,7 +2157,7 @@ function TestValueOf(handler) { TestWithProxies(TestValueOf2, handler) } -function TestValueOf2(handler, create) { +function TestValueOf2(create, handler) { var p = create(handler) assertSame(p, Object.prototype.valueOf.call(p)) } @@ -1502,7 +2174,7 @@ function TestIsEnumerable(handler) { TestWithProxies(TestIsEnumerable2, handler) } -function TestIsEnumerable2(handler, create) { +function TestIsEnumerable2(create, handler) { var p = create(handler) assertTrue(Object.prototype.propertyIsEnumerable.call(p, "a")) assertEquals("a", key) @@ -1510,6 +2182,11 @@ function TestIsEnumerable2(handler, create) { assertEquals("2", key) assertFalse(Object.prototype.propertyIsEnumerable.call(p, "z")) assertEquals("z", key) + + var o = Object.create(p) + key = "" + assertFalse(Object.prototype.propertyIsEnumerable.call(o, "a")) + assertEquals("", key) // trap not invoked } TestIsEnumerable({ @@ -1546,7 +2223,7 @@ function TestIsEnumerableThrow(handler) { TestWithProxies(TestIsEnumerableThrow2, handler) } -function TestIsEnumerableThrow2(handler, create) { +function TestIsEnumerableThrow2(create, handler) { var p = create(handler) assertThrows(function(){ Object.prototype.propertyIsEnumerable.call(p, "a") }, "myexn") @@ -1580,103 +2257,3 @@ TestIsEnumerableThrow(Proxy.create({ return function(k) { throw "myexn" } } })) - - - -// Calling (call, Function.prototype.call, Function.prototype.apply, -// Function.prototype.bind). - -var global = this -var receiver - -function TestCall(isStrict, callTrap) { - assertEquals(42, callTrap(5, 37)) -// TODO(rossberg): unrelated bug: this does not succeed for optimized code. -// assertEquals(isStrict ? undefined : global, receiver) - - var f = Proxy.createFunction({fix: function() { return {} }}, callTrap) - receiver = 333 - assertEquals(42, f(11, 31)) - assertEquals(isStrict ? undefined : global, receiver) - var o = {} - assertEquals(42, Function.prototype.call.call(f, o, 20, 22)) - assertEquals(o, receiver) - assertEquals(43, Function.prototype.call.call(f, null, 20, 23)) - assertEquals(isStrict ? null : global, receiver) - assertEquals(44, Function.prototype.call.call(f, 2, 21, 23)) - assertEquals(2, receiver.valueOf()) - receiver = 333 - assertEquals(32, Function.prototype.apply.call(f, o, [17, 15])) - assertEquals(o, receiver) - var ff = Function.prototype.bind.call(f, o, 12) - receiver = 333 - assertEquals(42, ff(30)) - assertEquals(o, receiver) - receiver = 333 - assertEquals(32, Function.prototype.apply.call(ff, {}, [20])) - assertEquals(o, receiver) - - Object.freeze(f) - receiver = 333 - assertEquals(42, f(11, 31)) -// TODO(rossberg): unrelated bug: this does not succeed for optimized code. -// assertEquals(isStrict ? undefined : global, receiver) - receiver = 333 - assertEquals(42, Function.prototype.call.call(f, o, 20, 22)) - assertEquals(o, receiver) - receiver = 333 - assertEquals(32, Function.prototype.apply.call(f, o, [17, 15])) - assertEquals(o, receiver) - receiver = 333 - assertEquals(42, ff(30)) - assertEquals(o, receiver) - receiver = 333 - assertEquals(32, Function.prototype.apply.call(ff, {}, [20])) - assertEquals(o, receiver) -} - -TestCall(false, function(x, y) { - receiver = this; return x + y -}) - -TestCall(true, function(x, y) { - "use strict"; - receiver = this; return x + y -}) - -TestCall(false, Proxy.createFunction({}, function(x, y) { - receiver = this; return x + y -})) - -TestCall(true, Proxy.createFunction({}, function(x, y) { - "use strict"; - receiver = this; return x + y -})) - -var p = Proxy.createFunction({fix: function() {return {}}}, function(x, y) { - receiver = this; return x + y -}) -TestCall(false, p) -Object.freeze(p) -TestCall(false, p) - - -function TestCallThrow(callTrap) { - var f = Proxy.createFunction({fix: function() {return {}}}, callTrap) - assertThrows(function(){ f(11) }, "myexn") - assertThrows(function(){ Function.prototype.call.call(f, {}, 2) }, "myexn") - assertThrows(function(){ Function.prototype.apply.call(f, {}, [1]) }, "myexn") - - Object.freeze(f) - assertThrows(function(){ f(11) }, "myexn") - assertThrows(function(){ Function.prototype.call.call(f, {}, 2) }, "myexn") - assertThrows(function(){ Function.prototype.apply.call(f, {}, [1]) }, "myexn") -} - -TestCallThrow(function() { throw "myexn" }) -TestCallThrow(Proxy.createFunction({}, function() { throw "myexn" })) - -var p = Proxy.createFunction( - {fix: function() {return {}}}, function() { throw "myexn" }) -Object.freeze(p) -TestCallThrow(p) diff --git a/test/mjsunit/harmony/weakmaps.js b/test/mjsunit/harmony/weakmaps.js deleted file mode 100644 index 7b5dcaf0..00000000 --- a/test/mjsunit/harmony/weakmaps.js +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright 2011 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. - -// Flags: --harmony-weakmaps --expose-gc - - -// Test valid getter and setter calls -var m = new WeakMap; -assertDoesNotThrow(function () { m.get(new Object) }); -assertDoesNotThrow(function () { m.set(new Object) }); -assertDoesNotThrow(function () { m.has(new Object) }); -assertDoesNotThrow(function () { m.delete(new Object) }); - - -// Test invalid getter and setter calls -var m = new WeakMap; -assertThrows(function () { m.get(undefined) }, TypeError); -assertThrows(function () { m.set(undefined, 0) }, TypeError); -assertThrows(function () { m.get(0) }, TypeError); -assertThrows(function () { m.set(0, 0) }, TypeError); -assertThrows(function () { m.get('a-key') }, TypeError); -assertThrows(function () { m.set('a-key', 0) }, TypeError); - - -// Test expected mapping behavior -var m = new WeakMap; -function TestMapping(map, key, value) { - map.set(key, value); - assertSame(value, map.get(key)); -} -TestMapping(m, new Object, 23); -TestMapping(m, new Object, 'the-value'); -TestMapping(m, new Object, new Object); - - -// Test expected querying behavior -var m = new WeakMap; -var key = new Object; -TestMapping(m, key, 'to-be-present'); -assertTrue(m.has(key)); -assertFalse(m.has(new Object)); -TestMapping(m, key, undefined); -assertFalse(m.has(key)); -assertFalse(m.has(new Object)); - - -// Test expected deletion behavior -var m = new WeakMap; -var key = new Object; -TestMapping(m, key, 'to-be-deleted'); -assertTrue(m.delete(key)); -assertFalse(m.delete(key)); -assertFalse(m.delete(new Object)); -assertSame(m.get(key), undefined); - - -// Test GC of map with entry -var m = new WeakMap; -var key = new Object; -m.set(key, 'not-collected'); -gc(); -assertSame('not-collected', m.get(key)); - - -// Test GC of map with chained entries -var m = new WeakMap; -var head = new Object; -for (key = head, i = 0; i < 10; i++, key = m.get(key)) { - m.set(key, new Object); -} -gc(); -var count = 0; -for (key = head; key != undefined; key = m.get(key)) { - count++; -} -assertEquals(11, count); - - -// Test property attribute [[Enumerable]] -var m = new WeakMap; -function props(x) { - var array = []; - for (var p in x) array.push(p); - return array.sort(); -} -assertArrayEquals([], props(WeakMap)); -assertArrayEquals([], props(WeakMap.prototype)); -assertArrayEquals([], props(m)); - - -// Test arbitrary properties on weak maps -var m = new WeakMap; -function TestProperty(map, property, value) { - map[property] = value; - assertEquals(value, map[property]); -} -for (i = 0; i < 20; i++) { - TestProperty(m, i, 'val' + i); - TestProperty(m, 'foo' + i, 'bar' + i); -} -TestMapping(m, new Object, 'foobar'); - - -// Test direct constructor call -var m = WeakMap(); -assertTrue(m instanceof WeakMap); - - -// Test some common JavaScript idioms -var m = new WeakMap; -assertTrue(m instanceof WeakMap); -assertTrue(WeakMap.prototype.set instanceof Function) -assertTrue(WeakMap.prototype.get instanceof Function) -assertTrue(WeakMap.prototype.has instanceof Function) -assertTrue(WeakMap.prototype.delete instanceof Function) - - -// Regression test for WeakMap prototype. -assertTrue(WeakMap.prototype.constructor === WeakMap) -assertTrue(Object.getPrototypeOf(WeakMap.prototype) === Object.prototype) - - -// Regression test for issue 1617: The prototype of the WeakMap constructor -// needs to be unique (i.e. different from the one of the Object constructor). -assertFalse(WeakMap.prototype === Object.prototype); -var o = Object.create({}); -assertFalse("get" in o); -assertFalse("set" in o); -assertEquals(undefined, o.get); -assertEquals(undefined, o.set); -var o = Object.create({}, { myValue: { - value: 10, - enumerable: false, - configurable: true, - writable: true -}}); -assertEquals(10, o.myValue); - - -// Stress Test -// There is a proposed stress-test available at the es-discuss mailing list -// which cannot be reasonably automated. Check it out by hand if you like: -// https://mail.mozilla.org/pipermail/es-discuss/2011-May/014096.html diff --git a/test/mjsunit/mjsunit.js b/test/mjsunit/mjsunit.js index faa5a438..6f6e3230 100644 --- a/test/mjsunit/mjsunit.js +++ b/test/mjsunit/mjsunit.js @@ -223,7 +223,7 @@ var assertUnreachable; assertSame = function assertSame(expected, found, name_opt) { if (found === expected) { if (expected !== 0 || (1 / expected) == (1 / found)) return; - } else if (isNaN(expected) && isNaN(found)) { + } else if ((expected !== expected) && (found !== found)) { return; } fail(PrettyPrint(expected), found, name_opt); diff --git a/test/mjsunit/mjsunit.status b/test/mjsunit/mjsunit.status index bae09b4e..cdac99b2 100644 --- a/test/mjsunit/mjsunit.status +++ b/test/mjsunit/mjsunit.status @@ -34,9 +34,13 @@ bugs: FAIL # Fails. regress/regress-1119: FAIL -############################################################################# -# Fails due to r10102 which reverts precise stepping on the 3.6 branch. -debug-step-2: FAIL +############################################################################## + +# Issue 1845: http://code.google.com/p/v8/issues/detail?id=1845 +harmony/proxies-example-membrane: SKIP + +# NewGC: BUG(1719) slow to collect arrays over several contexts. +regress/regress-524: SKIP ############################################################################## # Too slow in debug mode with --stress-opt @@ -64,7 +68,6 @@ regress/regress-524: (PASS || TIMEOUT), SKIP if $mode == debug debug-liveedit-check-stack: SKIP debug-liveedit-patch-positions-replace: SKIP - ############################################################################## [ $arch == arm ] diff --git a/test/mjsunit/object-define-properties.js b/test/mjsunit/object-define-properties.js index 128df694..6d5032e0 100644 --- a/test/mjsunit/object-define-properties.js +++ b/test/mjsunit/object-define-properties.js @@ -54,3 +54,19 @@ var x = Object.defineProperties(obj, desc); assertEquals(x.foo, 10); assertEquals(x.bar, 42); + + +// Make sure that all property descriptors are calculated before any +// modifications are done. + +var object = {}; + +assertThrows(function() { + Object.defineProperties(object, { + foo: { value: 1 }, + bar: { value: 2, get: function() { return 3; } } + }); + }, TypeError); + +assertEquals(undefined, object.foo); +assertEquals(undefined, object.bar); diff --git a/test/mjsunit/optimized-typeof.js b/test/mjsunit/optimized-typeof.js new file mode 100644 index 00000000..b0c0725c --- /dev/null +++ b/test/mjsunit/optimized-typeof.js @@ -0,0 +1,47 @@ +// Copyright 2011 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. + +// Flags: --allow-natives-syntax + +function typeofDirectly() { + return typeof({}) === "undefined"; +} + +typeofDirectly(); +typeofDirectly(); +%OptimizeFunctionOnNextCall(typeofDirectly); +typeofDirectly(); + +function typeofViaVariable() { + var foo = typeof({}) + return foo === "undefined"; +} + +typeofViaVariable(); +typeofViaVariable(); +%OptimizeFunctionOnNextCall(typeofViaVariable); +typeofViaVariable(); diff --git a/test/mjsunit/regexp-static.js b/test/mjsunit/regexp-static.js index 0f849687..8f283f6c 100644 --- a/test/mjsunit/regexp-static.js +++ b/test/mjsunit/regexp-static.js @@ -25,18 +25,6 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Test that we throw exceptions when calling test and exec with no -// input. This is not part of the spec, but we do it for -// compatibility with JSC. -assertThrows("/a/.test()"); -assertThrows("/a/.exec()"); - -// Test that we do not throw exceptions once the static RegExp.input -// field has been set. -RegExp.input = "a"; -assertDoesNotThrow("/a/.test()"); -assertDoesNotThrow("/a/.exec()"); - // Test the (deprecated as of JS 1.5) properties of the RegExp function. var re = /((\d+)\.(\d+))/; var s = 'abc123.456def'; @@ -166,3 +154,8 @@ assertTrue(typeof RegExp.input == typeof String(), "RegExp.input coerces values var foo = "lsdfj sldkfj sdklfj læsdfjl sdkfjlsdk fjsdl fjsdljskdj flsj flsdkj flskd regexp: /foobar/\nldkfj sdlkfj sdkl"; assertTrue(/^([a-z]+): (.*)/.test(foo.substring(foo.indexOf("regexp:"))), "regexp: setup"); assertEquals("regexp", RegExp.$1, "RegExp.$1"); + + +// Check that calling with no argument is the same as calling with undefined. +assertTrue(/^undefined$/.test()); +assertEquals(["undefined"], /^undefined$/.exec()); diff --git a/test/mjsunit/regress/regress-100702.js b/test/mjsunit/regress/regress-100702.js new file mode 100644 index 00000000..46494ab7 --- /dev/null +++ b/test/mjsunit/regress/regress-100702.js @@ -0,0 +1,44 @@ +// Copyright 2011 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. + +// Regression test for correct handling of non-object receiver values +// passed to built-in array functions. + +String.prototype.isThatMe = function () { + assertFalse(this === str); +}; + +var str = "abc"; +str.isThatMe(); +str.isThatMe.call(str); + +var arr = [1]; +arr.forEach("".isThatMe, str); +arr.filter("".isThatMe, str); +arr.some("".isThatMe, str); +arr.every("".isThatMe, str); +arr.map("".isThatMe, str); diff --git a/test/mjsunit/regress/regress-109195.js b/test/mjsunit/regress/regress-109195.js new file mode 100644 index 00000000..97538aa1 --- /dev/null +++ b/test/mjsunit/regress/regress-109195.js @@ -0,0 +1,65 @@ +// Copyright 2012 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. + +// Flags: --expose-debug-as debug +var Debug = debug.Debug; + +function listener(event, exec_state, event_data, data) { + for (var i = 0, n = exec_state.frameCount(); i < n; i++) { + exec_state.frame().scopeCount(i); + } + exec_state.prepareStep(Debug.StepAction.Continue, 1); +} + +Debug.setListener(listener); + +var F = function () { + 1, function () { + var d = 0; + (function () { d; }); + debugger; + }(); +}; + +var src = "(" + F.toString() + ")()"; +eval(src); + +Function.prototype.__defineGetter__("f", function () { + debugger; + return 0; +}); + +var G = function () { + 1, function () { + var d = 0; + (function () { d; }); + debugger; + }['f']; +}; + +var src = "(" + G.toString() + ")()"; +eval(src); diff --git a/test/mjsunit/regress/regress-1110.js b/test/mjsunit/regress/regress-1110.js index 43b8d77a..124f520c 100644 --- a/test/mjsunit/regress/regress-1110.js +++ b/test/mjsunit/regress/regress-1110.js @@ -28,10 +28,9 @@ // Test that the illegal continue is thrown at parse time. try { - function Crash() { continue;if (Crash) { - } } + eval("function Crash() { assertUnreachable(); continue;if (Crash) { } }"); Crash(); - assertTrue(false); + assertUnreachable(); } catch (e) { assertTrue(e instanceof SyntaxError); assertTrue(/continue/.test(e.message)); diff --git a/test/mjsunit/regress/regress-1170.js b/test/mjsunit/regress/regress-1170.js index 95684c54..66ed9f29 100644 --- a/test/mjsunit/regress/regress-1170.js +++ b/test/mjsunit/regress/regress-1170.js @@ -49,7 +49,7 @@ try { exception = true; assertTrue(/TypeError/.test(e)); } -assertTrue(exception); +assertFalse(exception); exception = false; try { diff --git a/test/mjsunit/regress/regress-1213575.js b/test/mjsunit/regress/regress-1213575.js index 9d82064e..f3a11dba 100644 --- a/test/mjsunit/regress/regress-1213575.js +++ b/test/mjsunit/regress/regress-1213575.js @@ -25,17 +25,16 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Make sure that a const definition always -// conflicts with a defined setter. This avoid -// trying to pass 'the hole' to the setter. +// Make sure that a const definition does not try +// to pass 'the hole' to a defined setter. -this.__defineSetter__('x', function(value) { assertTrue(false); }); +this.__defineSetter__('x', function(value) { assertTrue(value === 1); }); var caught = false; try { - eval('const x'); + eval('const x = 1'); } catch(e) { assertTrue(e instanceof TypeError); caught = true; } -assertTrue(caught); +assertFalse(caught); diff --git a/test/mjsunit/regress/regress-1217.js b/test/mjsunit/regress/regress-1217.js new file mode 100644 index 00000000..65305498 --- /dev/null +++ b/test/mjsunit/regress/regress-1217.js @@ -0,0 +1,50 @@ +// Copyright 2011 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. + +// Check that RegExp.prototype is itself a RegExp object. + +var proto = RegExp.prototype; +assertEquals("[object RegExp]", Object.prototype.toString.call(proto)); + +assertEquals("", proto.source); +assertEquals(false, proto.global); +assertEquals(false, proto.multiline); +assertEquals(false, proto.ignoreCase); +assertEquals(0, proto.lastIndex); + +assertEquals("/(?:)/", proto.toString()); + +var execResult = proto.exec("argle"); +assertEquals(1, execResult.length); +assertEquals("", execResult[0]); +assertEquals("argle", execResult.input); +assertEquals(0, execResult.index); + +assertTrue(proto.test("argle")); + +// We disallow re-compiling the RegExp.prototype object. +assertThrows(function(){ proto.compile("something"); }, TypeError); diff --git a/test/mjsunit/regress/regress-1229.js b/test/mjsunit/regress/regress-1229.js index e16d278b..c0dcba91 100644 --- a/test/mjsunit/regress/regress-1229.js +++ b/test/mjsunit/regress/regress-1229.js @@ -35,10 +35,10 @@ function foo(x, y, z) { assertEquals(3, z); } -var bound_arg = [1]; +var foob = foo.bind({}, 1); function f(y, z) { - return %NewObjectFromBound(foo, bound_arg); + return %NewObjectFromBound(foob); } // Check that %NewObjectFromBound looks at correct frame for inlined function. diff --git a/test/mjsunit/regress/regress-1415.js b/test/mjsunit/regress/regress-1415.js new file mode 100644 index 00000000..f993e9b3 --- /dev/null +++ b/test/mjsunit/regress/regress-1415.js @@ -0,0 +1,42 @@ +// Copyright 2011 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. + +// Surrogate pair range. +// U+D800 +assertThrows(function(){ decodeURIComponent("%ED%A0%80"); }, URIError); +// U+DBFF +assertThrows(function(){ decodeURIComponent("%ED%AF%BF"); }, URIError); +// U+DC00 +assertThrows(function(){ decodeURIComponent("%ED%B0%80"); }, URIError); +// U+DFFF +assertThrows(function(){ decodeURIComponent("%ED%BF%BF"); }, URIError); + +// Overlong encodings +// U+007F in two bytes. +assertThrows(function(){ decodeURIComponent("%C1%BF"); }, URIError); +// U+07FF in three bytes. +assertThrows(function(){ decodeURIComponent("%E0%9F%BF"); }, URIError); diff --git a/test/mjsunit/regress/regress-1639-2.js b/test/mjsunit/regress/regress-1639-2.js new file mode 100644 index 00000000..c439dd8f --- /dev/null +++ b/test/mjsunit/regress/regress-1639-2.js @@ -0,0 +1,93 @@ +// Copyright 2011 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. + +// Flags: --expose-debug-as debug +// Get the Debug object exposed from the debug context global object. +Debug = debug.Debug + +function sendCommand(state, cmd) { + // Get the debug command processor in paused state. + var dcp = state.debugCommandProcessor(false); + var request = JSON.stringify(cmd); + var response = dcp.processDebugJSONRequest(request); +} + +var state = 0; + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) { + var line = event_data.sourceLineText(); + print('break: ' + line); + print('event data: ' + event_data.toJSONProtocol()); + print(); + assertEquals('// BREAK', line.substr(-8), + "should not break outside evaluate"); + + switch (state) { + case 0: + state = 1; + // While in the debugger and stepping through a set of instructions + // executed in the evaluate command, the stepping must stop at the end + // of the said set of instructions and not step further into native + // debugger code. + sendCommand(exec_state, { + seq : 0, + type : "request", + command : "evaluate", + arguments : { + 'expression' : 'print("A"); debugger; print("B"); // BREAK', + 'global' : true + } + }); + break; + case 1: + sendCommand(exec_state, { + seq : 0, + type : "request", + command : "continue", + arguments : { + stepaction : "next" + } + }); + break; + } + } + } catch (e) { + print(e); + } +} + +// Add the debug event listener. +Debug.setListener(listener); + +function a() { +} // BREAK + +// Set a break point and call to invoke the debug event listener. +Debug.setBreakPoint(a, 0, 0); +a(); diff --git a/test/mjsunit/regress/regress-1692.js b/test/mjsunit/regress/regress-1692.js new file mode 100644 index 00000000..06bd66cf --- /dev/null +++ b/test/mjsunit/regress/regress-1692.js @@ -0,0 +1,89 @@ +// Copyright 2011 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. + +// Test that Object.prototype.propertyIsEnumerable handles array indices +// correctly. + +var p = Object.create({}, { + a : { value : 42, enumerable : true }, + b : { value : 42, enumerable : false }, + 1 : { value : 42, enumerable : true }, + 2 : { value : 42, enumerable : false }, + f : { get: function(){}, enumerable: true }, + g : { get: function(){}, enumerable: false }, + 11 : { get: function(){}, enumerable: true }, + 12 : { get: function(){}, enumerable: false } +}); +var o = Object.create(p, { + c : { value : 42, enumerable : true }, + d : { value : 42, enumerable : false }, + 3 : { value : 42, enumerable : true }, + 4 : { value : 42, enumerable : false }, + h : { get: function(){}, enumerable: true }, + k : { get: function(){}, enumerable: false }, + 13 : { get: function(){}, enumerable: true }, + 14 : { get: function(){}, enumerable: false } +}); + +// Inherited properties are ignored. +assertFalse(o.propertyIsEnumerable("a")); +assertFalse(o.propertyIsEnumerable("b")); +assertFalse(o.propertyIsEnumerable("1")); +assertFalse(o.propertyIsEnumerable("2")); + +// Own properties. +assertTrue(o.propertyIsEnumerable("c")); +assertFalse(o.propertyIsEnumerable("d")); +assertTrue(o.propertyIsEnumerable("3")); +assertFalse(o.propertyIsEnumerable("4")); + +// Inherited accessors. +assertFalse(o.propertyIsEnumerable("f")); +assertFalse(o.propertyIsEnumerable("g")); +assertFalse(o.propertyIsEnumerable("11")); +assertFalse(o.propertyIsEnumerable("12")); + +// Own accessors. +assertTrue(o.propertyIsEnumerable("h")); +assertFalse(o.propertyIsEnumerable("k")); +assertTrue(o.propertyIsEnumerable("13")); +assertFalse(o.propertyIsEnumerable("14")); + +// Nonexisting properties. +assertFalse(o.propertyIsEnumerable("xxx")); +assertFalse(o.propertyIsEnumerable("999")); + +// String object properties. +var o = Object("string"); +// Non-string property on String object. +o[10] = 42; +assertTrue(o.propertyIsEnumerable(10)); +assertFalse(o.propertyIsEnumerable(0)); + +// Fast elements. +var o = [1,2,3,4,5]; +assertTrue(o.propertyIsEnumerable(3)); diff --git a/test/mjsunit/regress/regress-1708.js b/test/mjsunit/regress/regress-1708.js new file mode 100644 index 00000000..ab50e078 --- /dev/null +++ b/test/mjsunit/regress/regress-1708.js @@ -0,0 +1,63 @@ +// Copyright 2011 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. + +// Regression test of a very rare corner case where left-trimming an +// array caused invalid marking bit patterns on lazily swept pages. + +// Flags: --expose-gc --noincremental-marking --max-new-space-size 1000 + +(function() { + var head = new Array(1); + var tail = head; + + // Fill heap to increase old-space size and trigger lazy sweeping on + // some of the old-space pages. + for (var i = 0; i < 200; i++) { + tail[1] = new Array(1000); + tail = tail[1]; + } + array = new Array(100); + gc(); gc(); + + // At this point "array" should have been promoted to old-space and be + // located in a lazy swept page with intact marking bits. Now shift + // the array to trigger left-trimming operations. + assertEquals(100, array.length); + for (var i = 0; i < 50; i++) { + array.shift(); + } + assertEquals(50, array.length); + + // At this point "array" should have been trimmed from the left with + // marking bits being correctly transfered to the new object start. + // Scavenging operations cause lazy sweeping to advance and verify + // that marking bit patterns are still sane. + for (var i = 0; i < 200; i++) { + tail[1] = new Array(1000); + tail = tail[1]; + } +})(); diff --git a/test/mjsunit/regress/regress-1711.js b/test/mjsunit/regress/regress-1711.js new file mode 100644 index 00000000..15591b1e --- /dev/null +++ b/test/mjsunit/regress/regress-1711.js @@ -0,0 +1,38 @@ +// Copyright 2011 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. + +// string.split needs to evaluate the separator's toString even if limit +// is 0 because toString may have side effects. + +var side_effect = false; +var separator = new Object(); +separator.toString = function() { + side_effect = true; + return undefined; +} +'subject'.split(separator, 0); +assertTrue(side_effect); diff --git a/test/mjsunit/regress/regress-1713.js b/test/mjsunit/regress/regress-1713.js new file mode 100644 index 00000000..0af1144a --- /dev/null +++ b/test/mjsunit/regress/regress-1713.js @@ -0,0 +1,127 @@ +// Copyright 2011 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. + +// Flags: --allow-natives-syntax --always-compact --expose-gc + +var O = { get f() { return 0; } }; + +var CODE = []; + +var R = []; + +function Allocate4Kb(N) { + var arr = []; + do {arr.push(new Array(1024));} while (--N > 0); + return arr; +} + +function AllocateXMb(X) { + return Allocate4Kb((1024 * X) / 4); +} + +function Node(v, next) { this.v = v; this.next = next; } + +Node.prototype.execute = function (O) { + var n = this; + while (n.next !== null) n = n.next; + n.v(O); +}; + +function LongList(N, x) { + if (N == 0) return new Node(x, null); + return new Node(new Array(1024), LongList(N - 1, x)); +} + +var L = LongList(1024, function (O) { + for (var i = 0; i < 5; i++) O.f; +}); + + + +function Incremental(O, x) { + if (!x) { + return; + } + function CreateCode(i) { + var f = new Function("return O.f_" + i); + CODE.push(f); + f(); // compile + f(); // compile + f(); // compile + } + + for (var i = 0; i < 1e4; i++) CreateCode(i); + gc(); + gc(); + gc(); + + print(">>> 1 <<<"); + + L.execute(O); + + try {} catch (e) {} + + L = null; + print(">>> 2 <<<"); + AllocateXMb(8); + //rint("1"); + //llocateXMb(8); + //rint("1"); + //llocateXMb(8); + +} + +function foo(O, x) { + Incremental(O, x); + + print('f'); + + for (var i = 0; i < 5; i++) O.f; + + + print('g'); + + bar(x); +} + +function bar(x) { + if (!x) return; + %DeoptimizeFunction(foo); + AllocateXMb(8); + AllocateXMb(8); +} + +var O1 = {}; +var O2 = {}; +var O3 = {}; +var O4 = {f:0}; + +foo(O1, false); +foo(O2, false); +foo(O3, false); +%OptimizeFunctionOnNextCall(foo); +foo(O4, true); diff --git a/test/mjsunit/regress/regress-1748.js b/test/mjsunit/regress/regress-1748.js new file mode 100644 index 00000000..e287e554 --- /dev/null +++ b/test/mjsunit/regress/regress-1748.js @@ -0,0 +1,35 @@ +// Copyright 2011 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. + +// Test that /^/ only matches at beginning of string. +// Bug in x64 caused it to match when executing the RegExp on a part +// of a string that starts at a multiplum of 256. + +var str = Array(10000).join("X"); +str.replace(/^|X/g, function(m, i, s) { + if (i > 0) assertEquals("X", m, "at position 0x" + i.toString(16)); +});
\ No newline at end of file diff --git a/test/mjsunit/regress/regress-1757.js b/test/mjsunit/regress/regress-1757.js new file mode 100644 index 00000000..f7a5516c --- /dev/null +++ b/test/mjsunit/regress/regress-1757.js @@ -0,0 +1,32 @@ +// Copyright 2011 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. + +// Flags: --string-slices --expose-externalize-string + +var a = "abcdefghijklmnopqrstuvqxy"+"z"; +externalizeString(a, true); +assertEquals('b', a.substring(1).charAt(0));
\ No newline at end of file diff --git a/test/mjsunit/regress/regress-1945.js b/test/mjsunit/regress/regress-1945.js new file mode 100644 index 00000000..bffc775f --- /dev/null +++ b/test/mjsunit/regress/regress-1945.js @@ -0,0 +1,34 @@ +// Copyright 2012 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. + +// Flags: --allow-natives-syntax + +var _d = new Date(); +_d.setHours(0,0,0,0); +_d.setHours(0,0,0,0); +%OptimizeFunctionOnNextCall(_d.setHours); +_d.setHours(0,0,0,0); diff --git a/test/mjsunit/regress/regress-877615.js b/test/mjsunit/regress/regress-877615.js index d35aba62..bec5a4d1 100644 --- a/test/mjsunit/regress/regress-877615.js +++ b/test/mjsunit/regress/regress-877615.js @@ -25,13 +25,13 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -Number.prototype.toLocaleString = function() { return 'invalid'}; -assertEquals([1].toLocaleString(), 'invalid'); // invalid +Number.prototype.toLocaleString = function() { return 'invalid'; }; +assertEquals('invalid', [1].toLocaleString()); // invalid Number.prototype.toLocaleString = 'invalid'; -assertEquals([1].toLocaleString(), '1'); // 1 +assertThrows(function() { [1].toLocaleString(); }); // Not callable. +delete Number.prototype.toLocaleString; Number.prototype.toString = function() { return 'invalid' }; -assertEquals([1].toLocaleString(), '1'); // 1 -assertEquals([1].toString(), '1'); // 1 - +assertEquals([1].toLocaleString(), 'invalid'); // Uses ToObject on elements. +assertEquals([1].toString(), '1'); // Uses ToString directly on elements. diff --git a/test/mjsunit/regress/regress-91517.js b/test/mjsunit/regress/regress-91517.js deleted file mode 100644 index 68a768c4..00000000 --- a/test/mjsunit/regress/regress-91517.js +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2011 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. - -// Getting property names of an object with a prototype chain that -// triggers dictionary elements in GetLocalPropertyNames() shouldn't -// crash the runtime - -// Flags: --allow-natives-syntax - -function Object1() { - this.foo = 1; -} - -function Object2() { - this.fuz = 2; - this.objects = new Object(); - this.fuz1 = 2; - this.fuz2 = 2; - this.fuz3 = 2; - this.fuz4 = 2; - this.fuz5 = 2; - this.fuz6 = 2; - this.fuz7 = 2; - this.fuz8 = 2; - this.fuz9 = 2; - this.fuz10 = 2; - this.fuz11 = 2; - this.fuz12 = 2; - this.fuz13 = 2; - this.fuz14 = 2; - this.fuz15 = 2; - this.fuz16 = 2; - this.fuz17 = 2; - // Force dictionary-based properties - for (x=1;x<1000;x++) { - this["sdf" + x] = 2; - } -} - -function Object3() { - this.boo = 3; -} - -function Object4() { - this.baz = 4; -} - -obj1 = new Object1(); -obj2 = new Object2(); -obj3 = new Object3(); -obj4 = new Object4(); - -%SetHiddenPrototype(obj4, obj3); -%SetHiddenPrototype(obj3, obj2); -%SetHiddenPrototype(obj2, obj1); - -function contains(a, obj) { - for(var i = 0; i < a.length; i++) { - if(a[i] === obj){ - return true; - } - } - return false; -} -names = %GetLocalPropertyNames(obj4); -assertEquals(1021, names.length); -assertTrue(contains(names, "baz")); -assertTrue(contains(names, "boo")); -assertTrue(contains(names, "foo")); -assertTrue(contains(names, "fuz")); -assertTrue(contains(names, "fuz1")); -assertTrue(contains(names, "fuz2")); -assertTrue(contains(names, "fuz3")); -assertTrue(contains(names, "fuz4")); -assertTrue(contains(names, "fuz5")); -assertTrue(contains(names, "fuz6")); -assertTrue(contains(names, "fuz7")); -assertTrue(contains(names, "fuz8")); -assertTrue(contains(names, "fuz9")); -assertTrue(contains(names, "fuz10")); -assertTrue(contains(names, "fuz11")); -assertTrue(contains(names, "fuz12")); -assertTrue(contains(names, "fuz13")); -assertTrue(contains(names, "fuz14")); -assertTrue(contains(names, "fuz15")); -assertTrue(contains(names, "fuz16")); -assertTrue(contains(names, "fuz17")); -assertFalse(names[1020] == undefined); diff --git a/test/mjsunit/regress/regress-94873.js b/test/mjsunit/regress/regress-94873.js new file mode 100644 index 00000000..41ca9921 --- /dev/null +++ b/test/mjsunit/regress/regress-94873.js @@ -0,0 +1,78 @@ +// Copyright 2011 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. + +// Flags: --expose-debug-as debug +// Get the Debug object exposed from the debug context global object. +Debug = debug.Debug; + +function sendCommand(state, cmd) { + // Get the debug command processor in paused state. + var dcp = state.debugCommandProcessor(false); + var request = JSON.stringify(cmd); + var response = dcp.processDebugJSONRequest(request); + return JSON.parse(response); +} + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) { + var line = event_data.sourceLineText(); + print('break: ' + line); + + var frame = sendCommand(exec_state, { + seq: 0, + type: "request", + command: "frame" + }); + + sendCommand(exec_state, { + seq: 0, + type: "request", + command: "evaluate", + arguments: { + expression: "obj.x.toString()", + additional_context: [{ + name: "obj", + handle: frame.body.receiver.ref + }] + } + }); + } + } catch (e) { + print(e); + } +} + +Debug.setListener(listener); + +function a(x, y) { + this.x = x; + this.y = y; +} + +Debug.setBreakPoint(a, 0, 0); +new a(1, 2);
\ No newline at end of file diff --git a/test/mjsunit/regress/regress-98773.js b/test/mjsunit/regress/regress-98773.js new file mode 100644 index 00000000..eb24eb5d --- /dev/null +++ b/test/mjsunit/regress/regress-98773.js @@ -0,0 +1,39 @@ +// Copyright 2011 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. + +// Calling Array.sort on an external array is not supposed to crash. + +var array = new Int16Array(23); +array[7] = 7; array[9] = 9; +assertEquals(23, array.length); +assertEquals(7, array[7]); +assertEquals(9, array[9]); + +Array.prototype.sort.call(array); +assertEquals(23, array.length); +assertEquals(7, array[21]); +assertEquals(9, array[22]); diff --git a/test/mjsunit/regress/regress-99167.js b/test/mjsunit/regress/regress-99167.js new file mode 100644 index 00000000..5053ae5d --- /dev/null +++ b/test/mjsunit/regress/regress-99167.js @@ -0,0 +1,33 @@ +// Copyright 2011 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. + +// Flags: --expose-gc --max-new-space-size=1024 + +eval("function Node() { this.a = 1; this.a = 3; }"); +new Node; +for (var i = 0; i < 4; ++i) gc(); +for (var i = 0; i < 100000; ++i) new Node; diff --git a/test/mjsunit/regress/regress-crbug-107996.js b/test/mjsunit/regress/regress-crbug-107996.js new file mode 100644 index 00000000..dfe07e59 --- /dev/null +++ b/test/mjsunit/regress/regress-crbug-107996.js @@ -0,0 +1,64 @@ +// Copyright 2012 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. + +// Flags: --expose-debug-as debug + +Debug = debug.Debug; + +Debug.setListener(listener); + +var fourteen; +var four_in_debugger = []; + +function listener(event, exec_state, event_data, data) { + if (event == Debug.DebugEvent.Break) { + for (var i = 0; i < exec_state.frameCount(); i++) { + var frame = exec_state.frame(i); + four_in_debugger[i] = frame.evaluate("four", false).value(); + } + } +} + +function f1() { + var three = 3; + var four = 4; + (function f2() { + var seven = 7; + (function f3() { + debugger; + fourteen = three + four + seven; + })(); + })(); +} + +f1(); +assertEquals(14, fourteen); +assertEquals(4, four_in_debugger[0]); +assertEquals(4, four_in_debugger[1]); +assertEquals(4, four_in_debugger[2]); + +Debug.setListener(null); diff --git a/test/mjsunit/regress/regress-deopt-gc.js b/test/mjsunit/regress/regress-deopt-gc.js index 7b7c29a3..a74e2c5e 100644 --- a/test/mjsunit/regress/regress-deopt-gc.js +++ b/test/mjsunit/regress/regress-deopt-gc.js @@ -42,7 +42,7 @@ function deopt() { // Make sure we don't inline this function try { var a = 42; } catch(o) {}; %DeoptimizeFunction(opt_me); - gc(true); + gc(); } diff --git a/test/mjsunit/regress/short-circuit.js b/test/mjsunit/regress/short-circuit.js new file mode 100644 index 00000000..25363d6b --- /dev/null +++ b/test/mjsunit/regress/short-circuit.js @@ -0,0 +1,32 @@ +// Copyright 2011 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. + +var arr = []; + +for (var i = 0; i < 28000; i++) { + arr.push(new RegExp("prefix" + i.toString() + i.toString() + i.toString())); +} diff --git a/test/mjsunit/stack-traces-2.js b/test/mjsunit/stack-traces-2.js new file mode 100644 index 00000000..165c4dfc --- /dev/null +++ b/test/mjsunit/stack-traces-2.js @@ -0,0 +1,87 @@ +// Copyright 2011 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. + +// Flags: --builtins-in-stack-traces + + +// Poisonous object that throws a reference error if attempted converted to +// a primitive values. +var thrower = { valueOf: function() { FAIL; }, + toString: function() { FAIL; } }; + +// Tests that a native constructor function is included in the +// stack trace. +function testTraceNativeConstructor(nativeFunc) { + var nativeFuncName = nativeFunc.name; + try { + new nativeFunc(thrower); + assertUnreachable(nativeFuncName); + } catch (e) { + assertTrue(e.stack.indexOf(nativeFuncName) >= 0, nativeFuncName); + } +} + +// Tests that a native conversion function is included in the +// stack trace. +function testTraceNativeConversion(nativeFunc) { + var nativeFuncName = nativeFunc.name; + try { + nativeFunc(thrower); + assertUnreachable(nativeFuncName); + } catch (e) { + assertTrue(e.stack.indexOf(nativeFuncName) >= 0, nativeFuncName); + } +} + + +function testNotOmittedBuiltin(throwing, included) { + try { + throwing(); + assertUnreachable(included); + } catch (e) { + assertTrue(e.stack.indexOf(included) >= 0, included); + } +} + + +testTraceNativeConversion(String); // Does ToString on argument. +testTraceNativeConversion(Number); // Does ToNumber on argument. +testTraceNativeConversion(RegExp); // Does ToString on argument. + +testTraceNativeConstructor(String); // Does ToString on argument. +testTraceNativeConstructor(Number); // Does ToNumber on argument. +testTraceNativeConstructor(RegExp); // Does ToString on argument. +testTraceNativeConstructor(Date); // Does ToNumber on argument. + +// QuickSort has builtins object as receiver, and is non-native +// builtin. Should not be omitted with the --builtins-in-stack-traces flag. +testNotOmittedBuiltin(function(){ [thrower, 2].sort(function (a,b) { + (b < a) - (a < b); }); + }, "QuickSort"); + +// Not omitted even though ADD from runtime.js is a non-native builtin. +testNotOmittedBuiltin(function(){ thrower + 2; }, "ADD");
\ No newline at end of file diff --git a/test/mjsunit/stack-traces.js b/test/mjsunit/stack-traces.js index 47a5cc59..536e71bb 100644 --- a/test/mjsunit/stack-traces.js +++ b/test/mjsunit/stack-traces.js @@ -194,6 +194,46 @@ function testErrorsDuringFormatting() { } +// Poisonous object that throws a reference error if attempted converted to +// a primitive values. +var thrower = { valueOf: function() { FAIL; }, + toString: function() { FAIL; } }; + +// Tests that a native constructor function is included in the +// stack trace. +function testTraceNativeConstructor(nativeFunc) { + var nativeFuncName = nativeFunc.name; + try { + new nativeFunc(thrower); + assertUnreachable(nativeFuncName); + } catch (e) { + assertTrue(e.stack.indexOf(nativeFuncName) >= 0, nativeFuncName); + } +} + +// Tests that a native conversion function is included in the +// stack trace. +function testTraceNativeConversion(nativeFunc) { + var nativeFuncName = nativeFunc.name; + try { + nativeFunc(thrower); + assertUnreachable(nativeFuncName); + } catch (e) { + assertTrue(e.stack.indexOf(nativeFuncName) >= 0, nativeFuncName); + } +} + + +function testOmittedBuiltin(throwing, omitted) { + try { + throwing(); + assertUnreachable(omitted); + } catch (e) { + assertTrue(e.stack.indexOf(omitted) < 0, omitted); + } +} + + testTrace("testArrayNative", testArrayNative, ["Array.map (native)"]); testTrace("testNested", testNested, ["at one", "at two", "at three"]); testTrace("testMethodNameInference", testMethodNameInference, ["at Foo.bar"]); @@ -217,3 +257,21 @@ testTrace("testStrippedCustomError", testStrippedCustomError, ["hep-hey"], testCallerCensorship(); testUnintendedCallerCensorship(); testErrorsDuringFormatting(); + +testTraceNativeConversion(String); // Does ToString on argument. +testTraceNativeConversion(Number); // Does ToNumber on argument. +testTraceNativeConversion(RegExp); // Does ToString on argument. + +testTraceNativeConstructor(String); // Does ToString on argument. +testTraceNativeConstructor(Number); // Does ToNumber on argument. +testTraceNativeConstructor(RegExp); // Does ToString on argument. +testTraceNativeConstructor(Date); // Does ToNumber on argument. + +// Omitted because QuickSort has builtins object as receiver, and is non-native +// builtin. +testOmittedBuiltin(function(){ [thrower, 2].sort(function (a,b) { + (b < a) - (a < b); }); + }, "QuickSort"); + +// Omitted because ADD from runtime.js is non-native builtin. +testOmittedBuiltin(function(){ thrower + 2; }, "ADD");
\ No newline at end of file diff --git a/test/mjsunit/strict-mode-implicit-receiver.js b/test/mjsunit/strict-mode-implicit-receiver.js index 338f6d10..8284eddc 100644 --- a/test/mjsunit/strict-mode-implicit-receiver.js +++ b/test/mjsunit/strict-mode-implicit-receiver.js @@ -168,12 +168,7 @@ outer_eval_conversion3(return_this, 'object'); outer_eval_conversion3(strict_eval, 'undefined'); outer_eval_conversion3(non_strict_eval, 'object'); -// TODO(ager): I'm not sure this is in accordance with the spec. At -// the moment, any call to eval where eval is not bound in the global -// context is treated as an indirect call to eval which means that the -// global context is used and the global object is passed as the -// receiver. -outer_eval_conversion3(eval, 'object'); +outer_eval_conversion3(eval, 'undefined'); function test_constant_function() { var o = { f: function() { "use strict"; return this; } }; diff --git a/test/mjsunit/strict-mode.js b/test/mjsunit/strict-mode.js index 30234ba6..9c9bdfd5 100644 --- a/test/mjsunit/strict-mode.js +++ b/test/mjsunit/strict-mode.js @@ -1051,14 +1051,20 @@ function CheckPillDescriptor(func, name) { } assertThrows(function() { strict.caller; }, TypeError); assertThrows(function() { strict.arguments; }, TypeError); + assertThrows(function() { strict.caller = 42; }, TypeError); + assertThrows(function() { strict.arguments = 42; }, TypeError); var another = new Function("'use strict'"); assertThrows(function() { another.caller; }, TypeError); assertThrows(function() { another.arguments; }, TypeError); + assertThrows(function() { another.caller = 42; }, TypeError); + assertThrows(function() { another.arguments = 42; }, TypeError); var third = (function() { "use strict"; return function() {}; })(); assertThrows(function() { third.caller; }, TypeError); assertThrows(function() { third.arguments; }, TypeError); + assertThrows(function() { third.caller = 42; }, TypeError); + assertThrows(function() { third.arguments = 42; }, TypeError); CheckPillDescriptor(strict, "caller"); CheckPillDescriptor(strict, "arguments"); diff --git a/test/mjsunit/string-external-cached.js b/test/mjsunit/string-external-cached.js new file mode 100644 index 00000000..12312ac7 --- /dev/null +++ b/test/mjsunit/string-external-cached.js @@ -0,0 +1,94 @@ +// 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. + +// Flags: --expose-externalize-string --expose-gc +// Test data pointer caching of external strings. + +function test() { + // Test string.charAt. + var charat_str = new Array(5); + charat_str[0] = "0123456789ABCDEF0123456789ABCDEF\ +0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF\ +0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF\ +0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF\ +0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"; + charat_str[1] = "0123456789ABCDEF"; + for (var i = 0; i < 6; i++) charat_str[1] += charat_str[1]; + try { // String can only be externalized once + externalizeString(charat_str[0], false); + externalizeString(charat_str[1], true); + } catch (ex) { } + charat_str[2] = charat_str[0].slice(0, -1); + charat_str[3] = charat_str[1].slice(0, -1); + charat_str[4] = charat_str[0] + charat_str[0]; + + for (var i = 0; i < 5; i++) { + assertEquals('B', charat_str[i].charAt(6*16 + 11)); + assertEquals('C', charat_str[i].charAt(6*16 + 12)); + assertEquals('A', charat_str[i].charAt(3*16 + 10)); + assertEquals('B', charat_str[i].charAt(3*16 + 11)); + } + + charat_short = "012"; + try { // String can only be externalized once + externalizeString(charat_short, true); + } catch (ex) { } + assertEquals("1", charat_short.charAt(1)); + + // Test regexp. + var re = /(A|B)/; + var rere = /(T.{1,2}B)/; + var ascii = "ABCDEFGHIJKLMNOPQRST"; + var twobyte = "_ABCDEFGHIJKLMNOPQRST"; + try { + externalizeString(ascii, false); + externalizeString(twobyte, true); + } catch (ex) { } + assertTrue(isAsciiString(ascii)); + assertFalse(isAsciiString(twobyte)); + var ascii_slice = ascii.slice(1,-1); + var twobyte_slice = twobyte.slice(2,-1); + var ascii_cons = ascii + ascii; + var twobyte_cons = twobyte + twobyte; + for (var i = 0; i < 2; i++) { + assertEquals(["A", "A"], re.exec(ascii)); + assertEquals(["B", "B"], re.exec(ascii_slice)); + assertEquals(["TAB", "TAB"], rere.exec(ascii_cons)); + assertEquals(["A", "A"], re.exec(twobyte)); + assertEquals(["B", "B"], re.exec(twobyte_slice)); + assertEquals(["T_AB", "T_AB"], rere.exec(twobyte_cons)); + } +} + +// Run the test many times to ensure IC-s don't break things. +for (var i = 0; i < 10; i++) { + test(); +} + +// Clean up string to make Valgrind happy. +gc(); +gc(); diff --git a/test/mjsunit/string-externalize.js b/test/mjsunit/string-externalize.js index da897869..d52a7e2b 100644 --- a/test/mjsunit/string-externalize.js +++ b/test/mjsunit/string-externalize.js @@ -44,7 +44,7 @@ function test() { assertFalse(isAsciiString(twoByteExternalWithAsciiData)); var realTwoByteExternalString = - "\u1234\u1234" + (function() { return "\u1234"; })(); + "\u1234\u1234\u1234\u1234" + (function() { return "\u1234"; })(); externalizeString(realTwoByteExternalString); assertFalse(isAsciiString(realTwoByteExternalString)); diff --git a/test/mjsunit/string-slices-regexp.js b/test/mjsunit/string-slices-regexp.js index a8cadaed..98b8ef9d 100644 --- a/test/mjsunit/string-slices-regexp.js +++ b/test/mjsunit/string-slices-regexp.js @@ -1,4 +1,4 @@ -// Copyright 2009 the V8 project authors. All rights reserved. +// Copyright 2011 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: @@ -24,11 +24,6 @@ // 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. -// -// Flags: --string-slices - -//assertEquals('345"12345 6"1234567"123', -// '12345""12345 6""1234567""1234'.slice(2,-1).replace(/""/g, '"')); var foo = "lsdfj sldkfj sdklfj læsdfjl sdkfjlsdk fjsdl fjsdljskdj flsj flsdkj flskd regexp: /foobar/\nldkfj sdlkfj sdkl"; for(var i = 0; i < 1000; i++) { diff --git a/test/mjsunit/string-slices.js b/test/mjsunit/string-slices.js index 8cc1f81e..3eb30f18 100755 --- a/test/mjsunit/string-slices.js +++ b/test/mjsunit/string-slices.js @@ -1,4 +1,4 @@ -// Copyright 2008 the V8 project authors. All rights reserved. +// Copyright 2011 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: @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --string-slices --expose-externalize-string +// Flags: --expose-externalize-string --allow-natives-syntax var s = 'abcdefghijklmn'; assertEquals(s, s.substr()); @@ -100,14 +100,7 @@ for (var i = 5; i < 25; i++) { // Keep creating strings to to force allocation failure on substring creation. var x = "0123456789ABCDEF"; -x += x; // 2^5 -x += x; -x += x; -x += x; -x += x; -x += x; // 2^10 -x += x; -x += x; +for (var i = 0; i < 8; i++) x += x; var xl = x.length; var cache = []; for (var i = 0; i < 1000; i++) { @@ -119,14 +112,7 @@ for (var i = 0; i < 1000; i++) { // Same with two-byte strings var x = "\u2028123456789ABCDEF"; -x += x; // 2^5 -x += x; -x += x; -x += x; -x += x; -x += x; // 2^10 -x += x; -x += x; +for (var i = 0; i < 8; i++) x += x; var xl = x.length; var cache = []; for (var i = 0; i < 1000; i++) { @@ -189,11 +175,34 @@ assertEquals("\u03B4\u03B5\u03B6\u03B7\u03B8\u03B9abcdefghijklmnop", assertEquals("\u03B2\u03B3\u03B4\u03B5\u03B4\u03B5\u03B6\u03B7", utf.substring(5,1) + utf.substring(3,7)); -/* // Externalizing strings. -var a = "123456789qwertyuiopasdfghjklzxcvbnm"; -var b = a.slice(1,-1); +var a = "123456789" + "qwertyuiopasdfghjklzxcvbnm"; +var b = "23456789qwertyuiopasdfghjklzxcvbn" assertEquals(a.slice(1,-1), b); -externalizeString(a); + +assertTrue(isAsciiString(a)); +externalizeString(a, true); +assertFalse(isAsciiString(a)); + assertEquals(a.slice(1,-1), b); -*/ +assertTrue(/3456789qwe/.test(a)); +assertEquals(5, a.indexOf("678")); +assertEquals("12345", a.split("6")[0]); + +// Create a slice with an external string as parent string. +var c = a.slice(1,-1); + +function test_crankshaft() { + for (var i = 0; i < 20; i++) { + assertEquals(b.charAt(i), a.charAt(i + 1)); + assertEquals(b.charAt(i), c.charAt(i)); + assertEquals(b.charAt(4), c.charAt(4)); + assertTrue(/3456789qwe/.test(c)); + assertEquals(4, c.indexOf("678")); + assertEquals("2345", c.split("6")[0]); + } +} + +test_crankshaft(); +%OptimizeFunctionOnNextCall(test_crankshaft); +test_crankshaft();
\ No newline at end of file diff --git a/test/mjsunit/switch.js b/test/mjsunit/switch.js index 180f994a..6a61fe59 100644 --- a/test/mjsunit/switch.js +++ b/test/mjsunit/switch.js @@ -25,6 +25,8 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// Flags: --allow-natives-syntax + function f0() { switch (0) { // switch deliberately left empty @@ -126,6 +128,42 @@ assertEquals(3, f4(1), "fallthrough-switch.1"); assertEquals(3, f4(2), "fallthrough-switch.2"); assertEquals(5, f4(3), "fallthrough-switch.3"); +function f4_string(tag, x) { + switch(tag) { + case 'zero': + x++; + case 'two': + x++; + } + return x; +} + +// Symbols +assertEquals(2, f4_string('zero', 0), "fallthrough-string-switch.0"); +assertEquals(1, f4_string('one', 1), "fallthrough-string-switch.1"); +assertEquals(3, f4_string('two', 2), "fallthrough-string-switch.2"); + +// Strings +assertEquals(2, f4_string('_zero'.slice(1), 0), "fallthrough-string-switch.3"); +assertEquals(1, f4_string('_one'.slice(1), 1), "fallthrough-string-switch.4"); +assertEquals(3, f4_string('_two'.slice(1), 2), "fallthrough-string-switch.5"); + +// Oddball +assertEquals(3, f4_string(null, 3), "fallthrough-string-switch.6"); + +// Test for regression +function regress_string(value) { + var json = 1; + switch (typeof value) { + case 'object': + break; + + default: + + } + return json; +}; +assertEquals(1, regress_string('object'), 'regression-string'); function f5(x) { switch(x) { @@ -287,3 +325,138 @@ var verylong_size = 1000; var verylong = makeVeryLong(verylong_size); assertEquals(verylong_size * 2 + 1, verylong()); + +// +// Test suite below aims to cover all possible combinations of following: +// +// clauses | tags | type feedback | optimization +// ========================================================= +// strings | symbol | all | on +// smis | string | target | off +// mixed | oddball | non-target | +// | smis | none | +// | heapnum | | +// ========================================================= + +// Function-with-switch generator +var test_id = 0, + clause_values = { + string: ['abc', 'def', 'ghi', 'jkl'], + smi: [1, 2, 3, 4], + mixed: ['abc', 1, 'def', 2, 'ghi', 3, 'jkl', 4] + }; + +function switch_gen(clause_type, feedback, optimize) { + var values = clause_values[clause_type]; + + function opt(fn) { + if (feedback === 'all') { + values.forEach(fn); + } else if (Array.isArray(feedback)) { + // Non-target + values.filter(function(v) { + return feedback.indexOf(v) === -1; + }).forEach(fn); + } else if (feedback !== undefined) { + // Target + fn(feedback); + } else { + // None + } + + if (optimize) %OptimizeFunctionOnNextCall(fn); + + return fn; + }; + + return opt(new Function( + 'tag', + '"' + (test_id++) + '";' + + 'switch(tag) {' + + values.map(function(value) { + return 'case ' + JSON.stringify(value) + ': return' + + JSON.stringify('ok-' + value); + }).join(';') + + '}' + )); +}; + +function test_switch(clause_type, test_type, feedback, optimize) { + var pairs = [], + fn = switch_gen(clause_type, feedback, optimize); + + if (Array.isArray(test_type)) { + pairs = test_type.map(function(v) { + return { + value: v, + expected: 'ok-' + v + }; + }); + } else if (test_type === 'symbols') { + pairs = clause_values.string.map(function(v) { + return { + value: v, + expected: clause_type !== 'smi' ? 'ok-' + v : undefined + }; + }); + } else if (test_type === 'strings') { + pairs = clause_values.string.map(function(v) { + return { + value: ('%%' + v).slice(2), + expected: clause_type !== 'smi' ? 'ok-' + v : undefined + }; + }); + } else if (test_type === 'oddball') { + pairs = [ + { value: null, expected: undefined }, + { value: NaN, expected: undefined }, + { value: undefined, expected: undefined } + ]; + } else if (test_type === 'smi') { + pairs = clause_values.smi.map(function(v) { + return { + value: v, + expected: clause_type !== 'string' ? 'ok-' + v : undefined + }; + }); + } else if (test_type === 'heapnum') { + pairs = clause_values.smi.map(function(v) { + return { + value: ((v * 17)/16) - ((v*17)%16/16), + expected: clause_type !== 'string' ? 'ok-' + v : undefined + }; + }); + } + + pairs.forEach(function(pair) { + assertEquals(fn(pair.value), pair.expected); + }); +}; + +// test_switch(clause_type, test_type, feedback, optimize); + +function test_switches(opt) { + var test_types = ['symbols', 'strings', 'oddball', 'smi', 'heapnum']; + + function test(clause_type) { + var values = clause_values[clause_type]; + + test_types.forEach(function(test_type) { + test_switch(clause_type, test_type, 'all', opt); + test_switch(clause_type, test_type, 'none', opt); + + // Targeting specific clause feedback + values.forEach(function(value) { + test_switch(clause_type, test_type, [value], value, opt); + test_switch(clause_type, test_type, value, value, opt); + }); + }); + }; + + test('string'); + test('smi'); + test('mixed'); +}; + +test_switches(false); +test_switches(true); diff --git a/test/mjsunit/to_number_order.js b/test/mjsunit/to_number_order.js index d17e6000..50e4bc76 100644 --- a/test/mjsunit/to_number_order.js +++ b/test/mjsunit/to_number_order.js @@ -161,7 +161,7 @@ assertEquals("fiskfisk", x, "Compare objects b >= b valueOf order"); x = ""; assertFalse(a > b, "Compare objects a > b"); -assertEquals("fiskhest", x, "Compare objects a > b valueOf order"); +assertEquals("hestfisk", x, "Compare objects a > b valueOf order"); x = ""; assertFalse(a > void(0), "Compare objects a > undefined"); @@ -195,7 +195,7 @@ function identical_object_comparison() { x = ""; assertFalse(a > b, "Compare objects a > b"); - assertEquals("fiskhest", x, "Compare objects a > b valueOf order"); + assertEquals("hestfisk", x, "Compare objects a > b valueOf order"); x = ""; assertFalse(a > void(0), "Compare objects a > undefined"); diff --git a/test/mjsunit/unbox-double-arrays.js b/test/mjsunit/unbox-double-arrays.js index feecaec8..fd7db28a 100644 --- a/test/mjsunit/unbox-double-arrays.js +++ b/test/mjsunit/unbox-double-arrays.js @@ -77,8 +77,6 @@ function testOneArrayType(allocator) { assertEquals(value_6, a[6]); assertEquals(value_6, a[computed_6()]); // Test non-constant key assertEquals(value_7, a[7]); - assertEquals(undefined, a[large_array_size-1]); - assertEquals(undefined, a[-1]); assertEquals(large_array_size, a.length); assertTrue(%HasFastDoubleElements(a)); } @@ -89,8 +87,6 @@ function testOneArrayType(allocator) { assertEquals(value_6, a[6]); assertEquals(value_6, a[computed_6()]); // Test non-constant key assertEquals(value_7, a[7]); - assertEquals(undefined, a[large_array_size-1]); - assertEquals(undefined, a[-1]); assertEquals(large_array_size, a.length); assertTrue(%HasFastDoubleElements(a)); } @@ -101,8 +97,6 @@ function testOneArrayType(allocator) { assertEquals(value_6, a[6]); assertEquals(value_6, a[computed_6()]); // Test non-constant key assertEquals(value_7, a[7]); - assertEquals(undefined, a[large_array_size-1]); - assertEquals(undefined, a[-1]); assertEquals(large_array_size, a.length); assertTrue(%HasFastDoubleElements(a)); } @@ -113,32 +107,40 @@ function testOneArrayType(allocator) { assertEquals(value_6, a[6]); assertEquals(value_6, a[computed_6()]); // Test non-constant key assertEquals(value_7, a[7]); - assertEquals(undefined, a[large_array_size-1]); - assertEquals(undefined, a[-1]); assertEquals(large_array_size, a.length); assertTrue(%HasFastDoubleElements(a)); } function test_various_loads5(a, value_5, value_6, value_7) { assertTrue(%HasFastDoubleElements(a)); + if (value_5 != undefined) { + assertEquals(value_5, a[5]); + }; + if (value_6 != undefined) { + assertEquals(value_6, a[6]); + assertEquals(value_6, a[computed_6()]); // Test non-constant key + } + assertEquals(value_7, a[7]); + assertEquals(large_array_size, a.length); + assertTrue(%HasFastDoubleElements(a)); + } + + function test_various_loads6(a, value_5, value_6, value_7) { + assertTrue(%HasFastDoubleElements(a)); assertEquals(value_5, a[5]); assertEquals(value_6, a[6]); assertEquals(value_6, a[computed_6()]); // Test non-constant key assertEquals(value_7, a[7]); - assertEquals(undefined, a[large_array_size-1]); - assertEquals(undefined, a[-1]); assertEquals(large_array_size, a.length); assertTrue(%HasFastDoubleElements(a)); } - function test_various_loads6(a, value_5, value_6, value_7) { + function test_various_loads7(a, value_5, value_6, value_7) { assertTrue(%HasFastDoubleElements(a)); assertEquals(value_5, a[5]); assertEquals(value_6, a[6]); assertEquals(value_6, a[computed_6()]); // Test non-constant key assertEquals(value_7, a[7]); - assertEquals(undefined, a[large_array_size-1]); - assertEquals(undefined, a[-1]); assertEquals(large_array_size, a.length); assertTrue(%HasFastDoubleElements(a)); } @@ -248,6 +250,8 @@ function testOneArrayType(allocator) { expected_array_value(7)); // Make sure Crankshaft code handles the hole correctly (bailout) + var large_array = new allocator(large_array_size); + force_to_fast_double_array(large_array); test_various_stores(large_array, expected_array_value(5), expected_array_value(6), @@ -273,7 +277,12 @@ function testOneArrayType(allocator) { undefined, expected_array_value(7)); + %DeoptimizeFunction(test_various_loads6); + gc(); + // Test stores for non-NaN. + var large_array = new allocator(large_array_size); + force_to_fast_double_array(large_array); %OptimizeFunctionOnNextCall(test_various_stores); test_various_stores(large_array, expected_array_value(5), @@ -285,7 +294,19 @@ function testOneArrayType(allocator) { expected_array_value(6), expected_array_value(7)); - test_various_loads6(large_array, + test_various_loads7(large_array, + expected_array_value(5), + expected_array_value(6), + expected_array_value(7)); + + test_various_loads7(large_array, + expected_array_value(5), + expected_array_value(6), + expected_array_value(7)); + + %OptimizeFunctionOnNextCall(test_various_loads7); + + test_various_loads7(large_array, expected_array_value(5), expected_array_value(6), expected_array_value(7)); @@ -301,7 +322,7 @@ function testOneArrayType(allocator) { -NaN, expected_array_value(7)); - test_various_loads6(large_array, + test_various_loads7(large_array, NaN, -NaN, expected_array_value(7)); @@ -317,7 +338,7 @@ function testOneArrayType(allocator) { -Infinity, expected_array_value(7)); - test_various_loads6(large_array, + test_various_loads7(large_array, Infinity, -Infinity, expected_array_value(7)); @@ -434,7 +455,6 @@ large_array3[3] = Infinity; large_array3[4] = -Infinity; function call_apply() { - assertTrue(%HasFastDoubleElements(large_array3)); called_by_apply.apply({}, large_array3); } @@ -449,7 +469,6 @@ call_apply(); function test_for_in() { // Due to previous tests, keys 0..25 and 95 should be present. next_expected = 0; - assertTrue(%HasFastDoubleElements(large_array3)); for (x in large_array3) { assertTrue(next_expected++ == x); if (next_expected == 25) { diff --git a/test/mjsunit/undeletable-functions.js b/test/mjsunit/undeletable-functions.js index 04fd0606..635ea6fa 100644 --- a/test/mjsunit/undeletable-functions.js +++ b/test/mjsunit/undeletable-functions.js @@ -25,11 +25,8 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Test that we match JSC in making some functions undeletable. -// See http://code.google.com/p/chromium/issues/detail?id=1717 -// The functions on these prototypes are not just undeletable. It is -// possible to override them with new definitions, then get the old -// version back by deleting the new definition. +// Test that we match ECMAScript in making most builtin functions +// deletable and only specific ones undeletable or read-only. var array; @@ -37,7 +34,7 @@ array = [ "toString", "toLocaleString", "join", "pop", "push", "concat", "reverse", "shift", "unshift", "slice", "splice", "sort", "filter", "forEach", "some", "every", "map", "indexOf", "lastIndexOf", "reduce", "reduceRight"]; -CheckJSCSemantics(Array.prototype, array, "Array prototype"); +CheckEcmaSemantics(Array.prototype, array, "Array prototype"); var old_Array_prototype = Array.prototype; var new_Array_prototype = {}; @@ -57,12 +54,12 @@ array = [ "setUTCMinutes", "setHours", "setUTCHours", "setDate", "setUTCDate", "setMonth", "setUTCMonth", "setFullYear", "setUTCFullYear", "toGMTString", "toUTCString", "getYear", "setYear", "toISOString", "toJSON"]; -CheckJSCSemantics(Date.prototype, array, "Date prototype"); +CheckEcmaSemantics(Date.prototype, array, "Date prototype"); array = [ "random", "abs", "acos", "asin", "atan", "ceil", "cos", "exp", "floor", "log", "round", "sin", "sqrt", "tan", "atan2", "pow", "max", "min"]; -CheckJSCSemantics(Math, array, "Math1"); +CheckEcmaSemantics(Math, array, "Math1"); CheckEcmaSemantics(Date, ["UTC", "parse", "now"], "Date"); @@ -76,6 +73,8 @@ array = [ "execScript"]; CheckEcmaSemantics(this, array, "Global"); CheckReadOnlyAttr(this, "Infinity"); +CheckReadOnlyAttr(this, "NaN"); +CheckReadOnlyAttr(this, "undefined"); array = ["exec", "test", "toString", "compile"]; CheckEcmaSemantics(RegExp.prototype, array, "RegExp prototype"); @@ -112,7 +111,7 @@ array = [ "toUpperCase", "toLocaleUpperCase", "link", "anchor", "fontcolor", "fontsize", "big", "blink", "bold", "fixed", "italics", "small", "strike", "sub", "sup", "toJSON", "toString", "valueOf"]; -CheckJSCSemantics(String.prototype, array, "String prototype"); +CheckEcmaSemantics(String.prototype, array, "String prototype"); CheckEcmaSemantics(String, ["fromCharCode"], "String"); @@ -124,14 +123,6 @@ function CheckEcmaSemantics(type, props, name) { } -function CheckJSCSemantics(type, props, name) { - print(name); - for (var i = 0; i < props.length; i++) { - CheckNotDeletable(type, props[i]); - } -} - - function CheckDontDelete(type, props, name) { print(name); for (var i = 0; i < props.length; i++) { @@ -154,21 +145,6 @@ function CheckDeletable(type, prop) { } -function CheckNotDeletable(type, prop) { - var old = type[prop]; - if (!type[prop]) return; - assertTrue(type.hasOwnProperty(prop), "inherited: " + prop); - var deleted = delete type[prop]; - assertTrue(deleted, "delete operator returned false: " + prop); - assertTrue(type.hasOwnProperty(prop), "not there after delete: " + prop); - type[prop] = "foo"; - assertEquals("foo", type[prop], "not overwritable: " + prop); - deleted = delete type[prop]; - assertTrue(deleted, "delete operator returned false 2nd time: " + prop); - assertEquals(old.toString(), type[prop].toString(), "delete didn't restore the old value: " + prop); -} - - function CheckDontDeleteAttr(type, prop) { var old = type[prop]; if (!type[prop]) return; @@ -189,7 +165,7 @@ function CheckReadOnlyAttr(type, prop) { assertFalse(deleted, "delete operator returned true: " + prop); assertTrue(type.hasOwnProperty(prop), "not there after delete: " + prop); type[prop] = "foo"; - assertEquals("foo", type[prop], "overwritable: " + prop); + assertEquals(old, type[prop], "overwritable: " + prop); } print("OK"); diff --git a/test/mozilla/mozilla.status b/test/mozilla/mozilla.status index 3a271309..e31a630b 100644 --- a/test/mozilla/mozilla.status +++ b/test/mozilla/mozilla.status @@ -1,4 +1,4 @@ -# Copyright 2009 the V8 project authors. All rights reserved. +# Copyright 2011 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: @@ -69,7 +69,6 @@ js1_5/Array/regress-465980-02: SKIP ecma_3/Date/15.9.3.2-1: SKIP js1_2/function/Number: SKIP - ##################### SLOW TESTS ##################### # This takes a long time to run (~100 seconds). It should only be run @@ -227,7 +226,7 @@ ecma/String/15.5.4.12-4: FAIL_OK ecma/String/15.5.4.12-5: FAIL_OK # Creates a linked list of arrays until we run out of memory or timeout. -js1_5/Regress/regress-312588: FAIL || TIMEOUT +js1_5/Regress/regress-312588: SKIP # Runs out of memory because it compiles huge functions. @@ -301,6 +300,11 @@ js1_2/regexp/RegExp_multiline_as_array: FAIL_OK js1_2/regexp/beginLine: FAIL_OK js1_2/regexp/endLine: FAIL_OK +# We no longer let calls to test and exec with no argument implicitly +# use the previous input. +js1_2/regexp/RegExp_input: FAIL_OK +js1_2/regexp/RegExp_input_as_array: FAIL_OK + # To be compatible with safari typeof a regexp yields 'function'; # in firefox it yields 'object'. @@ -411,12 +415,6 @@ js1_5/extensions/regress-435345-01: FAIL_OK js1_5/extensions/regress-455413: FAIL_OK -# The spec specifies reverse evaluation order for < and >=. -# See section 11.8.2 and 11.8.5. -# We implement the spec here but the test tests the more straigtforward order. -ecma_3/Operators/order-01: FAIL_OK - - # Uses Mozilla-specific QName, XML, XMLList and Iterator. js1_5/Regress/regress-407323: FAIL_OK js1_5/Regress/regress-407957: FAIL_OK @@ -619,6 +617,10 @@ js1_5/Expressions/regress-394673: FAIL # We do not correctly handle assignments within "with" /ecma_3/Statements/12.10-01: FAIL +# We do not throw an exception when a const is redeclared. +# (We only fail section 1 of the test.) +js1_5/Regress/regress-103602: FAIL + ##################### MOZILLA EXTENSION TESTS ##################### ecma/extensions/15.1.2.1-1: FAIL_OK diff --git a/test/preparser/strict-identifiers.pyt b/test/preparser/strict-identifiers.pyt index 72808e25..aa3d5210 100644 --- a/test/preparser/strict-identifiers.pyt +++ b/test/preparser/strict-identifiers.pyt @@ -138,6 +138,38 @@ setter_arg = StrictTemplate("setter-param-$id", """ var x = {set foo($id) { }}; """) +label_normal = Template("label-normal-$id", """ + $id: ''; +""") + +label_strict = StrictTemplate("label-strict-$id", """ + $id: ''; +""") + +break_normal = Template("break-normal-$id", """ + for (;;) { + break $id; + } +""") + +break_strict = StrictTemplate("break-strict-$id", """ + for (;;) { + break $id; + } +""") + +continue_normal = Template("continue-normal-$id", """ + for (;;) { + continue $id; + } +""") + +continue_strict = StrictTemplate("continue-strict-$id", """ + for (;;) { + continue $id; + } +""") + non_strict_use = Template("nonstrict-$id", """ var $id = 42; $id++; @@ -162,6 +194,7 @@ non_strict_use = Template("nonstrict-$id", """ function $id($id) { } x = {$id: 42}; x = {get $id() {}, set $id(value) {}}; + $id: ''; """) identifier_name_source = """ @@ -197,6 +230,12 @@ for id in ["eval", "arguments"]: prefix_var({"id": id, "op":"--", "opname":"dec"}, "strict_lhs_prefix") postfix_var({"id": id, "op":"++", "opname":"inc"}, "strict_lhs_postfix") postfix_var({"id": id, "op":"--", "opname":"dec"}, "strict_lhs_postfix") + label_normal({"id": id}, None) + label_strict({"id": id}, None) + break_normal({"id": id}, None) + break_strict({"id": id}, None) + continue_normal({"id": id}, None) + continue_strict({"id": id}, None) non_strict_use({"id": id}, None) @@ -205,10 +244,13 @@ for id in ["eval", "arguments"]: for reserved_word in reserved_words + strict_reserved_words: if (reserved_word in strict_reserved_words): message = "strict_reserved_word" + label_message = None elif (reserved_word == "const"): message = "unexpected_token" + label_message = message else: message = "reserved_word" + label_message = message arg_name_own({"id":reserved_word}, message) arg_name_nested({"id":reserved_word}, message) setter_arg({"id": reserved_word}, message) @@ -225,6 +267,19 @@ for reserved_word in reserved_words + strict_reserved_words: read_var({"id": reserved_word}, message) identifier_name({"id": reserved_word}, None); identifier_name_strict({"id": reserved_word}, None); + label_normal({"id": reserved_word}, label_message) + break_normal({"id": reserved_word}, label_message) + continue_normal({"id": reserved_word}, label_message) + if (reserved_word == "const"): + # The error message for this case is different because + # ParseLabelledStatementOrExpression will try to parse this as an expression + # first, effectively disallowing the use in ParseVariableDeclarations, i.e. + # the preparser never sees that 'const' was intended to be a label. + label_strict({"id": reserved_word}, "strict_const") + else: + label_strict({"id": reserved_word}, message) + break_strict({"id": reserved_word}, message) + continue_strict({"id": reserved_word}, message) # Future reserved words in strict mode behave like normal identifiers diff --git a/test/sputnik/sputnik.status b/test/sputnik/sputnik.status index 868509d7..fb6d9513 100644 --- a/test/sputnik/sputnik.status +++ b/test/sputnik/sputnik.status @@ -30,10 +30,6 @@ def FAIL_OK = FAIL, OKAY ############################### BUGS ################################### -# A bound function should fail on access to 'caller' and 'arguments'. -S15.3.4.5_A1: FAIL -S15.3.4.5_A2: FAIL - # '__proto__' should be treated as a normal property in JSON. S15.12.2_A1: FAIL @@ -46,11 +42,8 @@ S15.8.2.16_A7: PASS || FAIL_OK S15.8.2.18_A7: PASS || FAIL_OK S15.8.2.13_A23: PASS || FAIL_OK -# We allow calls to regexp exec() with no arguments to fail for -# compatibility reasons. -S15.10.6.2_A1_T16: FAIL_OK -S15.10.6.2_A12: FAIL_OK -S15.10.6.3_A1_T16: FAIL_OK +# Sputnik tests (r97) assume RegExp.prototype is an Object, not a RegExp. +S15.10.6_A2: FAIL_OK # We are silent in some regexp cases where the spec wants us to give # errors, for compatibility. @@ -159,6 +152,10 @@ S11.1.5_A4.2: FAIL_OK S9.9_A1: FAIL_OK S9.9_A2: FAIL_OK +# The expected evaluation order of comparison operations changed. +S11.8.2_A2.3_T1: FAIL_OK +S11.8.3_A2.3_T1: FAIL_OK + # Calls builtins without an explicit receiver which means that # undefined is passed to the builtin. The tests expect the global # object to be passed which was true in ES3 but not in ES5. @@ -176,6 +173,23 @@ S15.5.4.13_A1_T3: FAIL_OK S15.5.4.14_A1_T3: FAIL_OK S15.5.4.15_A1_T3: FAIL_OK +# NaN, Infinity and undefined are read-only according to ES5. +S15.1.1.1_A2_T1: FAIL_OK # NaN +S15.1.1.1_A2_T2: FAIL_OK # NaN +S15.1.1.2_A2_T1: FAIL_OK # Infinity +# S15.1.1.2_A2_T2 would fail if it weren't bogus in r97. sputnik bug #45. +S15.1.1.3_A2_T1: FAIL_OK # undefined +S15.1.1.3_A2_T2: FAIL_OK # undefined + +# Function.prototype.apply can handle arbitrary object as argument list. +S15.3.4.3_A6_T1: FAIL_OK +S15.3.4.3_A6_T4: FAIL_OK + +# Array.prototype.to[Locale]String is generic in ES5. +S15.4.4.2_A2_T1: FAIL_OK +S15.4.4.3_A2_T1: FAIL_OK + + ##################### SKIPPED TESTS ##################### # These tests take a looong time to run in debug mode. @@ -194,53 +208,6 @@ S15.3_A3_T1: FAIL # Invalid test case (recent change adding var changes semantics) S15.3_A3_T3: FAIL -# These tests fail because we had to add bugs to be compatible with JSC. See -# http://code.google.com/p/chromium/issues/detail?id=1717 -S15.5.4.1_A1_T2: FAIL_OK -S15.5.4_A1: FAIL_OK -S15.5.4_A3: FAIL_OK -S15.9.5.10_A1_T2: FAIL_OK -S15.9.5.11_A1_T2: FAIL_OK -S15.9.5.12_A1_T2: FAIL_OK -S15.9.5.13_A1_T2: FAIL_OK -S15.9.5.14_A1_T2: FAIL_OK -S15.9.5.15_A1_T2: FAIL_OK -S15.9.5.16_A1_T2: FAIL_OK -S15.9.5.17_A1_T2: FAIL_OK -S15.9.5.18_A1_T2: FAIL_OK -S15.9.5.19_A1_T2: FAIL_OK -S15.9.5.20_A1_T2: FAIL_OK -S15.9.5.21_A1_T2: FAIL_OK -S15.9.5.22_A1_T2: FAIL_OK -S15.9.5.23_A1_T2: FAIL_OK -S15.9.5.24_A1_T2: FAIL_OK -S15.9.5.25_A1_T2: FAIL_OK -S15.9.5.26_A1_T2: FAIL_OK -S15.9.5.27_A1_T2: FAIL_OK -S15.9.5.28_A1_T2: FAIL_OK -S15.9.5.29_A1_T2: FAIL_OK -S15.9.5.2_A1_T2: FAIL_OK -S15.9.5.30_A1_T2: FAIL_OK -S15.9.5.31_A1_T2: FAIL_OK -S15.9.5.32_A1_T2: FAIL_OK -S15.9.5.33_A1_T2: FAIL_OK -S15.9.5.34_A1_T2: FAIL_OK -S15.9.5.35_A1_T2: FAIL_OK -S15.9.5.36_A1_T2: FAIL_OK -S15.9.5.37_A1_T2: FAIL_OK -S15.9.5.38_A1_T2: FAIL_OK -S15.9.5.39_A1_T2: FAIL_OK -S15.9.5.3_A1_T2: FAIL_OK -S15.9.5.40_A1_T2: FAIL_OK -S15.9.5.41_A1_T2: FAIL_OK -S15.9.5.42_A1_T2: FAIL_OK -S15.9.5.4_A1_T2: FAIL_OK -S15.9.5.5_A1_T2: FAIL_OK -S15.9.5.6_A1_T2: FAIL_OK -S15.9.5.7_A1_T2: FAIL_OK -S15.9.5.8_A1_T2: FAIL_OK -S15.9.5.9_A1_T2: FAIL_OK - [ $arch == arm ] # BUG(3251225): Tests that timeout with --nocrankshaft. diff --git a/test/test262/README b/test/test262/README index ea6b4a71..094356fc 100644 --- a/test/test262/README +++ b/test/test262/README @@ -4,11 +4,11 @@ tests from http://hg.ecmascript.org/tests/test262 -at revision 128 as 'data' in this directory. Using later version +at revision 271 as 'data' in this directory. Using later version may be possible but the tests are only known to pass (and indeed run) with that revision. -hg clone -r 128 http://hg.ecmascript.org/tests/test262 data +hg clone -r 271 http://hg.ecmascript.org/tests/test262 data If you do update to a newer revision you may have to change the test harness adapter code since it uses internal functionality from the diff --git a/test/test262/test262.status b/test/test262/test262.status index 8cee2107..2ad57464 100644 --- a/test/test262/test262.status +++ b/test/test262/test262.status @@ -25,1330 +25,418 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +prefix test262 +def FAIL_OK = FAIL, OKAY -# -# ietestcenter tests. -# +############################### BUGS ################################### -prefix ietestcenter +# '__proto__' should be treated as a normal property in JSON. +S15.12.2_A1: FAIL +# V8 Bug: http://code.google.com/p/v8/issues/detail?id=1196 +S8.7_A5_T2: FAIL -# -# Deliberate differences for compatibility with other browsers -# -# 15.9.5.43-0-9 and 15.9.5.43-0-10. V8 doesn't throw RangeError -# from Date.prototype.toISOString when string is not a finite number. -# This is compatible with Firefox and Safari. -15.9.5.43-0-9: PASS || FAIL -15.9.5.43-0-10: PASS || FAIL +# V8 Bug: http://code.google.com/p/v8/issues/detail?id=1624 +S10.4.2.1_A1: FAIL -# -# Unanalyzed failures which may be bugs or deliberate differences -# +# V8 Bug: http://code.google.com/p/v8/issues/detail?id=1530 +S15.3.3.1_A4: FAIL -# Bug? Strict Mode - TypeError is thrown when changing the value of a Value -# Property of the Global Object under strict mode (NaN) -10.2.1.1.3-4-16-s: FAIL -# Bug? Strict Mode - TypeError is thrown when changing the value of a Value -# Property of the Global Object under strict mode (undefined) -10.2.1.1.3-4-18-s: FAIL -# Invalid test: https://bugs.ecmascript.org/show_bug.cgi?id=76 -10.4.2-2-c-1: FAIL -# BUG: 11.8.2 Greater-than Operator - Partial left to right order enforced -# when using Greater-than operator: valueOf > valueOf -11.8.2-1: FAIL -# BUG: 11.8.2 Greater-than Operator - Partial left to right order enforced -# when using Greater-than operator: valueOf > toString -11.8.2-2: FAIL -# BUG: 11.8.2 Greater-than Operator - Partial left to right order enforced -# when using Greater-than operator: toString > valueOf -11.8.2-3: FAIL -# BUG: 11.8.2 Greater-than Operator - Partial left to right order enforced -# when using Greater-than operator: toString > toString -11.8.2-4: FAIL -# BUG: 11.8.3 Less-than-or-equal Operator - Partial left to right order -# enforced when using Less-than-or-equal operator: valueOf <= valueOf -11.8.3-1: FAIL -# BUG: 11.8.3 Less-than-or-equal Operator - Partial left to right order -# enforced when using Less-than-or-equal operator: valueOf <= toString -11.8.3-2: FAIL -# BUG: 11.8.3 Less-than-or-equal Operator - Partial left to right order -# enforced when using Less-than-or-equal operator: toString <= valueOf -11.8.3-3: FAIL -# BUG: 11.8.3 Less-than-or-equal Operator - Partial left to right order -# enforced when using Less-than-or-equal operator: toString <= toString -11.8.3-4: FAIL -# BUG: 11.8.3 Less-than-or-equal Operator - Partial left to right order -# enforced when using Less-than-or-equal operator: valueOf <= valueOf -11.8.3-5: FAIL -# Bug? simple assignment throws TypeError if LeftHandSide is a readonly property -# in strict mode (Global.undefined) -11.13.1-4-27-s: FAIL -# Bug? simple assignment throws TypeError if LeftHandSide is a readonly property -# in strict mode (Global.Infinity) -11.13.1-4-3-s: FAIL -# BUG: Global.NaN is a data property with default attribute values -15.1.1.1-0: FAIL -# BUG: Global.Infinity is a data property with default attribute values -15.1.1.2-0: FAIL -# BUG: Global.undefined is a data property with default attribute values -15.1.1.3-0: FAIL -# BUG: Object.getOwnPropertyDescriptor returns data desc (all false) -# for properties on built-ins (Global.NaN) -15.2.3.3-4-178: FAIL -# BUG: Object.getOwnPropertyDescriptor returns data desc (all false) -# for properties on built-ins (Global.Infinity) -15.2.3.3-4-179: FAIL -# BUG: Object.getOwnPropertyDescriptor returns data desc (all false) -# for properties on built-ins (Global.undefined) -15.2.3.3-4-180: FAIL -# BUG: Object.getOwnPropertyDescriptor returns data desc (all false) -# for properties on built-ins (RegExp.prototype.source) -# There is no RegExp.prototype.source -15.2.3.3-4-212: FAIL -# BUG: Object.getOwnPropertyDescriptor returns data desc (all false) -# for properties on built-ins (RegExp.prototype.global) -# There is no RegExp.prototype.global -15.2.3.3-4-213: FAIL -# BUG: Object.getOwnPropertyDescriptor returns data desc (all false) -# for properties on built-ins (RegExp.prototype.ignoreCase) -# There is no RegExp.prototype.ignoreCase -15.2.3.3-4-214: FAIL -# BUG: Object.getOwnPropertyDescriptor returns data desc (all false) -# for properties on built-ins (RegExp.prototype.multiline) -15.2.3.3-4-215: FAIL -# Bug? Object.defineProperty - Update [[Enumerable]] attribute of 'name' -# property to true successfully when [[Enumerable]] attribute of 'name' -# is false and [[Configurable]] attribute of 'name' is true, the 'desc' -# is a generic descriptor which only contains [[Enumerable]] attribute -# as true, 'name' property is an index data property (8.12.9 step 8) -15.2.3.6-4-82-18: FAIL -# Bug? Object.defineProperty - Update [[Enumerable]] attribute of 'name' -# property to false successfully when [[Enumerable]] and [[Configurable]] -# attributes of 'name' property are true, the 'desc' is a generic -# descriptor which only contains [Enumerable]] attribute as false and -# 'name' property is an index accessor property (8.12.9 step 8) -15.2.3.6-4-82-19: FAIL -# Bug? Object.defineProperty - Update [[Enumerable]] attribute of 'name' -# property to false successfully when [[Enumerable]] and [[Configurable]] -# attributes of 'name' property are true, the 'desc' is a generic -# descriptor which contains [Enumerable]] attribute as false and -# [[Configurable]] property is true, 'name' property is an index accessor -# property (8.12.9 step 8) -15.2.3.6-4-82-20: FAIL -# Bug? Object.defineProperty - Update [[Configurable]] attribute of 'name' -# property to false successfully when [[Enumerable]] and [[Configurable]] -# attributes of 'name' property are true, the 'desc' is a generic -# descriptor which only contains [[Configurable]] attribute as false, -# 'name' property is an index accessor property (8.12.9 step 8) -15.2.3.6-4-82-21: FAIL -# Bug? Object.defineProperty - Update [[Configurable]] attribute of 'name' -# property to false successfully when [[Enumerable]] and [[Configurable]] -# attributes of 'name' property are true, the 'desc' is a generic -# descriptor which contains [[Enumerable]] attribute as true and -# [[Configurable]] attribute is false, 'name' property is an index accessor -# property (8.12.9 step 8) -15.2.3.6-4-82-22: FAIL -# Bug? Object.defineProperty - Update [[Enumerable]] and [[Configurable]] -# attributes of 'name' property to false successfully when [[Enumerable]] -# and [[Configurable]] attributes of 'name' property are true, the 'desc' -# is a generic descriptor which contains [[Enumerable]] and -# [[Configurable]] attributes as false, 'name' property is an index -# accessor property (8.12.9 step 8) -15.2.3.6-4-82-23: FAIL -# Bug? Object.defineProperty - Update [[Enumerable]] attributes of 'name' -# property to true successfully when [[Enumerable]] attribute of 'name' is -# false and [[Configurable]] attribute of 'name' is true, the 'desc' is a -# generic descriptor which only contains [[Enumerable]] attribute as true, -# 'name' property is an index accessor property (8.12.9 step 8) -15.2.3.6-4-82-24: FAIL -# Bug? Object.defineProperty - 'O' is an Array, test the length property of 'O' -# is own data property (15.4.5.1 step 1) +# V8 Bug: http://code.google.com/p/v8/issues/detail?id=1756 15.2.3.6-4-116: FAIL -# Bug? Object.defineProperty - 'O' is an Array, test the length property of 'O' -# is own data property that overrides an inherited data property (15.4.5.1 -# step 1) 15.2.3.6-4-117: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test that RangeError exception is thrown when [[Value]] field of -# 'desc' is undefined (15.4.5.1 step 3.c) 15.2.3.6-4-125: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test the [[Value]] field of 'desc' is null (15.4.5.1 step 3.c) 15.2.3.6-4-126: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test the [[Value]] field of 'desc' is a boolean with value false -# (15.4.5.1 step 3.c) 15.2.3.6-4-127: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test the [[Value]] field of 'desc' is a boolean with value true -# (15.4.5.1 step 3.c) 15.2.3.6-4-128: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError exception is not thrown when the [[Value]] field of -# 'desc' is 0 (15.4.5.1 step 3.c) 15.2.3.6-4-129: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError exception is not thrown when the [[Value]] field of -# 'desc' is +0 (15.4.5.1 step 3.c) 15.2.3.6-4-130: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError exception is not thrown when the [[Value]] field of -# 'desc' is -0 (15.4.5.1 step 3.c) 15.2.3.6-4-131: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError exception is not thrown when the [[Value]] field of -# 'desc' is a positive number (15.4.5.1 step 3.c) 15.2.3.6-4-132: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError exception is thrown when the [[Value]] field of -# 'desc' is a negative number (15.4.5.1 step 3.c) 15.2.3.6-4-133: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError exception is thrown when the [[Value]] field of -# 'desc' is +Infinity (15.4.5.1 step 3.c) 15.2.3.6-4-134: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError exception is thrown when the [[Value]] field of -# 'desc' is -Infinity (15.4.5.1 step 3.c) 15.2.3.6-4-135: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError exception is thrown when the [[Value]] field of -# 'desc' is NaN (15.4.5.1 step 3.c) 15.2.3.6-4-136: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError exception is not thrown when the [[Value]] field of -# 'desc' is a string containing a positive number (15.4.5.1 step 3.c) 15.2.3.6-4-137: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError exception is thrown when the [[Value]] field of -# 'desc' is a string containing a negative number (15.4.5.1 step 3.c) 15.2.3.6-4-138: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError exception is thrown when the [[Value]] field of -# 'desc' is a string containing a decimal number (15.4.5.1 step 3.c) 15.2.3.6-4-139: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError exception is thrown when the [[Value]] field of -# 'desc' is a string containing +Infinity (15.4.5.1 step 3.c) 15.2.3.6-4-140: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError exception is thrown when the [[Value]] field of -# 'desc' is a string containing -Infinity (15.4.5.1 step 3.c) 15.2.3.6-4-141: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test the [[Value]] field of 'desc' is a string containing an -# exponential number (15.4.5.1 step 3.c) 15.2.3.6-4-142: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test the [[Value]] field of 'desc' is a string containing a hex -# number (15.4.5.1 step 3.c) 15.2.3.6-4-143: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test the [[Value]] field of 'desc' is a string containing a number -# with leading zeros (15.4.5.1 step 3.c) 15.2.3.6-4-144: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError exception is thrown when the [[Value]] field of -# 'desc' is a string which doesn't convert to a number (15.4.5.1 step 3.c) 15.2.3.6-4-145: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test the [[Value]] field of 'desc' is an object which has an own -# toString method (15.4.5.1 step 3.c) 15.2.3.6-4-146: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test the [[Value]] field of 'desc' is an Object which has an own -# valueOf method (15.4.5.1 step 3.c) 15.2.3.6-4-147: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test the [[Value]] field of 'desc' is an Object which has an own -# valueOf method that returns an object and toString method that returns a -# string (15.4.5.1 step 3.c) 15.2.3.6-4-148: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test the [[Value]] field of 'desc' is an Object which has an own -# toString and valueOf method (15.4.5.1 step 3.c) 15.2.3.6-4-149: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test TypeError is thrown when the [[Value]] field of 'desc' is an -# Object that both toString and valueOf wouldn't return primitive value -# (15.4.5.1 step 3.c) 15.2.3.6-4-150: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', and the [[Value]] field of 'desc' is an Object with an own toString -# method and an inherited valueOf method (15.4.5.1 step 3.c), test that the -# inherited valueOf method is used 15.2.3.6-4-151: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError is thrown when the [[Value]] field of 'desc' is a -# positive non-integer values (15.4.5.1 step 3.c) 15.2.3.6-4-152: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length prosperty -# of 'O', test RangeError is thrown when the [[Value]] field of 'desc' is a -# negative non-integer values (15.4.5.1 step 3.c) 15.2.3.6-4-153: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test the [[Value]] field of 'desc' is boundary value 2^32 - 2 -# (15.4.5.1 step 3.c) 15.2.3.6-4-154: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test the [[Value]] field of 'desc' is boundary value 2^32 - 1 -# (15.4.5.1 step 3.c) 15.2.3.6-4-155: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError is thrown when the [[Value]] field of 'desc' is -# boundary value 2^32 (15.4.5.1 step 3.c) 15.2.3.6-4-156: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError is thrown when the [[Value]] field of 'desc' is -# boundary value 2^32 + 1 (15.4.5.1 step 3.c) 15.2.3.6-4-157: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', set the [[Value]] field of 'desc' to a value greater than the -# existing value of length (15.4.5.1 step 3.f) 15.2.3.6-4-159: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', set the [[Value]] field of 'desc' to a value lesser than the -# existing value of length and test that indexes beyond the new length are -# deleted(15.4.5.1 step 3.f) 15.2.3.6-4-161: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Writable]] attribute of the length property is set -# to true after deleting properties with large index named if the -# [[Writable]] field of 'desc' is absent (15.4.5.1 step 3.h) 15.2.3.6-4-165: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Writable]] attribute of the length property is set -# to true after deleting properties with large index named if the -# [[Writable]] field of 'desc' is true (15.4.5.1 step 3.h) 15.2.3.6-4-166: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Writable]] attribute of the length property is set -# to false after deleting properties with large index named if the -# [[Writable]] field of 'desc' is false (15.4.5.1 step 3.i.ii) 15.2.3.6-4-167: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', whose writable attribute is being changed to false and the [[Value]] -# field of 'desc' is less than value of the length property and also lesser -# than an index of the array which is set to configurable:false, test that -# new length is set to a value greater than the non-deletable index by 1, -# writable attribute of length is set to false and TypeError exception is -# thrown (15.4.5.1 step 3.i.iii) 15.2.3.6-4-168: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property and also lesser than an index of the array which is set to -# configurable: false, test that new length is set to a value greater than -# the non-deletable index by 1, and TypeError is thrown (15.4.5.1 step -# 3.l.i) 15.2.3.6-4-169: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property and also lesser than an index of the array which is set to -# configurable: false, test that new length is set to a value greater than -# the non-deletable index by 1, writable attribute of length is set to -# false and TypeError exception is thrown (15.4.5.1 step 3.l.ii) 15.2.3.6-4-170: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of an inherited data -# property with large index named in 'O' can't stop deleting index named -# properties (15.4.5.1 step 3.l.ii) 15.2.3.6-4-171: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of own data property with -# large index named in 'O' that overrides an inherited data property can -# stop deleting index named properties (15.4.5.1 step 3.l.ii) 15.2.3.6-4-172: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of own data property with -# large index named in 'O' that overrides an inherited accessor property -# can stop deleting index named properties (15.4.5.1 step 3.l.ii) 15.2.3.6-4-173: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of own accessor property -# with large index named in 'O' can stop deleting index named properties -# (15.4.5.1 step 3.l.ii) 15.2.3.6-4-174: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of an inherited accessor -# property with large index named in 'O' can't stop deleting index named -# properties (15.4.5.1 step 3.l.ii) 15.2.3.6-4-175: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of own accessor property -# with large index named in 'O' that overrides an inherited data property -# can stop deleting index named properties (15.4.5.1 step 3.l.ii) 15.2.3.6-4-176: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of own accessor property -# with large index named in 'O' that overrides an inherited accessor -# property can stop deleting index named properties (15.4.5.1 step 3.l.ii) 15.2.3.6-4-177: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the configurable large index named property of 'O' is -# deleted (15.4.5.1 step 3.l.ii) 15.2.3.6-4-178: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is greater than value of the length -# property, test value of the length property is same as [[Value]] -# (15.4.5.1 step 3.l.iii.1) 15.2.3.6-4-179-1: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Writable]] attribute of the length property is set -# to false at last when the [[Writable]] field of 'desc' is false and 'O' -# doesn't contain non-configurable large index named property (15.4.5.1 -# step 3.m) 15.2.3.6-4-181: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is an array index named -# property, 'name' is boundary value 2^32 - 2 (15.4.5.1 step 4.a) 15.2.3.6-4-183: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is an array index named -# property, test TypeError is thrown if the [[Writable]] attribute of the -# length property in 'O' is false and value of 'name' equals to value of -# the length property (15.4.5.1 step 4.b) 15.2.3.6-4-188: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is an array index named -# property, test TypeError is thrown if the [[Writable]] attribute of the -# length property in 'O' is false and value of 'name' is greater than value -# of the length property (15.4.5.1 step 4.b) 15.2.3.6-4-189: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is an array index named -# property, 'desc' is accessor descriptor, test updating all attribute -# values of 'name' (15.4.5.1 step 4.c) -15.2.3.6-4-209: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is an array index named -# property, name is accessor property and 'desc' is accessor descriptor, -# test updating the [[Enumerable]] attribute value of 'name' (15.4.5.1 step -# 4.c) -15.2.3.6-4-271: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is an array index named -# property, name is accessor property and 'desc' is accessor descriptor, -# test updating the [[Configurable]] attribute value of 'name' (15.4.5.1 -# step 4.c) -15.2.3.6-4-272: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is an array index named -# property, name is accessor property and 'desc' is accessor descriptor, -# test updating multiple attribute values of 'name' (15.4.5.1 step 4.c) -15.2.3.6-4-273: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is an array index named -# property, test the length property of 'O' is set as ToUint32('name') + 1 -# if ToUint32('name') equals to value of the length property in 'O' -# (15.4.5.1 step 4.e.ii) 15.2.3.6-4-275: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is an array index named -# property, test the length property of 'O' is set as ToUint32('name') + 1 -# if ToUint32('name') is greater than value of the length property in 'O' -# (15.4.5.1 step 4.e.ii) 15.2.3.6-4-276: FAIL -# Bug? Object.defineProperty - 'O' is an Arguments object of a function that has -# formal parameters, 'name' is own accessor property of 'O' which is also -# defined in [[ParameterMap]] of 'O', and 'desc' is accessor descriptor, -# test updating multiple attribute values of 'name' (10.6 -# [[DefineOwnProperty]] step 3 and 5.a.i) -15.2.3.6-4-291-1: FAIL -# Bug? Object.defineProperty - 'O' is an Arguments object, 'name' is own -# accessor property of 'O', and 'desc' is accessor descriptor, test -# updating multiple attribute values of 'name' (10.6 [[DefineOwnProperty]] -# step 3) -15.2.3.6-4-291: FAIL -# Bug? Object.defineProperty - 'O' is an Arguments object of a function that has -# formal parameters, 'name' is own property of 'O' which is also defined in -# [[ParameterMap]] of 'O', and 'desc' is data descriptor, test updating -# multiple attribute values of 'name' (10.6 [[DefineOwnProperty]] step 3 -# and 5.b) 15.2.3.6-4-292-1: FAIL -# Bug? Object.defineProperty - 'O' is an Arguments object of a function that has -# formal parameters, 'name' is own data property of 'O' which is also -# defined in [[ParameterMap]] of 'O', test TypeError is thrown when -# updating the [[Value]] attribute value of 'name' which is defined as -# unwritable and non-configurable (10.6 [[DefineOwnProperty]] step 4 and -# step 5b) 15.2.3.6-4-293-2: FAIL -# Bug? Object.defineProperty - 'O' is an Arguments object of a function that has -# formal parameters, 'name' is own data property of 'O' which is also -# defined in [[ParameterMap]] of 'O', test TypeError is not thrown when -# updating the [[Value]] attribute value of 'name' which is defined as -# non-writable and configurable (10.6 [[DefineOwnProperty]] step 3 and step -# 5.b) 15.2.3.6-4-293-3: FAIL -# Bug? Object.defineProperty - 'O' is an Arguments object of a function that has -# formal parameters, 'name' is own data property of 'O' which is also -# defined in [[ParameterMap]] of 'O', test TypeError is thrown when -# updating the [[Writable]] attribute value of 'name' which is defined as -# non-configurable (10.6 [[DefineOwnProperty]] step 4 and 5b) 15.2.3.6-4-294-1: FAIL -# Bug? Object.defineProperty - 'O' is an Arguments object of a function that has -# formal parameters, 'name' is own data property of 'O' which is also -# defined in [[ParameterMap]] of 'O', test TypeError is thrown when -# updating the [[Enumerable]] attribute value of 'name' which is defined as -# non-configurable (10.6 [[DefineOwnProperty]] step 4 and step 5b) 15.2.3.6-4-295-1: FAIL -# Bug? Object.defineProperty - 'O' is an Arguments object of a function that has -# formal parameters, 'name' is own data property of 'O' which is also -# defined in [[ParameterMap]] of 'O', test TypeError is thrown when -# updating the [[Configurable]] attribute value of 'name' which is defined -# as non-configurable (10.6 [[DefineOwnProperty]] step 4 and step 5b) 15.2.3.6-4-296-1: FAIL -# Bug? Object.defineProperty - 'O' is an Arguments object, 'name' is an index -# named accessor property of 'O' but not defined in [[ParameterMap]] of -# 'O', and 'desc' is accessor descriptor, test updating multiple attribute -# values of 'name' (10.6 [[DefineOwnProperty]] step 3) -15.2.3.6-4-303: FAIL -# Bug? ES5 Attributes - indexed property 'P' with attributes [[Writable]]: true, -# [[Enumerable]]: true, [[Configurable]]: false is writable using simple -# assignment, 'O' is an Arguments object 15.2.3.6-4-333-11: FAIL -# Bug? ES5 Attributes - Updating indexed data property 'P' whose attributes are -# [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: true to an -# accessor property, 'A' is an Array object (8.12.9 - step 9.b.i) 15.2.3.6-4-360-1: FAIL -# Bug? ES5 Attributes - Updating indexed data property 'P' whose attributes are -# [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: true to an -# accessor property, 'O' is an Arguments object (8.12.9 - step 9.b.i) 15.2.3.6-4-360-6: FAIL -# Bug? ES5 Attributes - Updating indexed data property 'P' whose attributes are -# [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: true to an -# accessor property, 'O' is the global object (8.12.9 - step 9.b.i) 15.2.3.6-4-360-7: FAIL -# Bug? ES5 Attributes - [[Value]] attribute of data property is the activex host -# object -15.2.3.6-4-401: FAIL -# Bug? ES5 Attributes - Failed to add a property to an object when the object's -# object has a property with same name and [[Writable]] attribute is set to -# false (Number instance) 15.2.3.6-4-405: FAIL -# Bug? ES5 Attributes - Failed to add a property to an object when the object's -# prototype has a property with the same name and [[Writable]] set to false -# (JSON) 15.2.3.6-4-410: FAIL -# Bug? ES5 Attributes - Failed to add properties to an object when the object's -# prototype has properties with the same name and [[Writable]] set to false -# (Object.create) 15.2.3.6-4-415: FAIL -# Bug? ES5 Attributes - Failed to add a property to an object when the object's -# prototype has a property with the same name and [[Writable]] set to -# false(Function.prototype.bind) 15.2.3.6-4-420: FAIL -# Bug? ES5 Attributes - all attributes in Array.prototype.indexOf are correct -15.2.3.6-4-612: FAIL -# Bug? ES5 Attributes - all attributes in Object.lastIndexOf are correct -15.2.3.6-4-613: FAIL -# Bug? ES5 Attributes - all attributes in Array.prototype.every are correct -15.2.3.6-4-614: FAIL -# Bug? ES5 Attributes - all attributes in Array.prototype.some are correct -15.2.3.6-4-615: FAIL -# Bug? ES5 Attributes - all attributes in Array.prototype.forEach are correct -15.2.3.6-4-616: FAIL -# Bug? ES5 Attributes - all attributes in Array.prototype.map are correct -15.2.3.6-4-617: FAIL -# Bug? ES5 Attributes - all attributes in Array.prototype.filter are correct -15.2.3.6-4-618: FAIL -# Bug? ES5 Attributes - all attributes in Array.prototype.reduce are correct -15.2.3.6-4-619: FAIL -# Bug? ES5 Attributes - all attributes in Array.prototype.reduceRight are -# correct -15.2.3.6-4-620: FAIL -# Bug? ES5 Attributes - all attributes in String.prototype.trim are correct -15.2.3.6-4-621: FAIL -# Bug? ES5 Attributes - all attributes in Date.prototype.toISOString are correct -15.2.3.6-4-623: FAIL -# Bug? ES5 Attributes - all attributes in Date.prototype.toJSON are correct -15.2.3.6-4-624: FAIL -# Bug? Object.defineProperties - 'O' is an Array, test the length property of -# 'O' is own data property (15.4.5.1 step 1) 15.2.3.7-6-a-112: FAIL -# Bug? Object.defineProperties - 'O' is an Array, test the length property of -# 'O' is own data property that overrides an inherited data property -# (15.4.5.1 step 1) 15.2.3.7-6-a-113: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', test RangeError is thrown when setting the [[Value]] field of 'desc' -# to undefined (15.4.5.1 step 3.c) -15.2.3.7-6-a-121: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', test setting the [[Value]] field of 'desc' to null actuall is set to -# 0 (15.4.5.1 step 3.c) 15.2.3.7-6-a-122: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is a boolean with value false -# (15.4.5.1 step 3.c) 15.2.3.7-6-a-123: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is a boolean with value true -# (15.4.5.1 step 3.c) 15.2.3.7-6-a-124: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is 0 (15.4.5.1 step 3.c) 15.2.3.7-6-a-125: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is +0 (15.4.5.1 step 3.c) 15.2.3.7-6-a-126: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is -0 (15.4.5.1 step 3.c) 15.2.3.7-6-a-127: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is positive number (15.4.5.1 -# step 3.c) 15.2.3.7-6-a-128: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is negative number (15.4.5.1 -# step 3.c) -15.2.3.7-6-a-129: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is +Infinity (15.4.5.1 step -# 3.c) -15.2.3.7-6-a-130: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is -Infinity (15.4.5.1 step -# 3.c) -15.2.3.7-6-a-131: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is NaN (15.4.5.1 step 3.c) -15.2.3.7-6-a-132: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is a string containing a -# positive number (15.4.5.1 step 3.c) 15.2.3.7-6-a-133: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is a string containing a -# negative number (15.4.5.1 step 3.c) -15.2.3.7-6-a-134: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is a string containing a -# decimal number (15.4.5.1 step 3.c) -15.2.3.7-6-a-135: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is a string containing -# +Infinity (15.4.5.1 step 3.c) -15.2.3.7-6-a-136: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is a string containing -# -Infinity (15.4.5.1 step 3.c) -15.2.3.7-6-a-137: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is a string containing an -# exponential number (15.4.5.1 step 3.c) 15.2.3.7-6-a-138: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is a string containing an hex -# number (15.4.5.1 step 3.c) 15.2.3.7-6-a-139: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is a string containing an -# leading zero number (15.4.5.1 step 3.c) 15.2.3.7-6-a-140: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', test the [[Value]] field of 'desc' is a string which doesn't convert -# to a number (15.4.5.1 step 3.c) -15.2.3.7-6-a-141: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', test the [[Value]] field of 'desc' is an Object which has an own -# toString method (15.4.5.1 step 3.c) 15.2.3.7-6-a-142: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is an Object which has an own -# valueOf method (15.4.5.1 step 3.c) 15.2.3.7-6-a-143: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is an Object which has an own -# valueOf method that returns an object and toString method that returns a -# string (15.4.5.1 step 3.c) 15.2.3.7-6-a-144: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is an Object which has an own -# toString and valueOf method (15.4.5.1 step 3.c) 15.2.3.7-6-a-145: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test TypeError is thrown when the [[Value]] field of 'desc' is an -# Object that both toString and valueOf wouldn't return primitive value -# (15.4.5.1 step 3.c) -15.2.3.7-6-a-146: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test using inherited valueOf method when the [[Value]] field of -# 'desc' is an Objec with an own toString and inherited valueOf methods -# (15.4.5.1 step 3.c) 15.2.3.7-6-a-147: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test RangeError is thrown when the [[Value]] field of 'desc' is -# positive non-integer values (15.4.5.1 step 3.c) -15.2.3.7-6-a-148: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test RangeError is thrown when the [[Value]] field of 'desc' is -# negative non-integer values (15.4.5.1 step 3.c) -15.2.3.7-6-a-149: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is boundary value 2^32 - 2 -# (15.4.5.1 step 3.c) 15.2.3.7-6-a-150: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is boundary value 2^32 - 1 -# (15.4.5.1 step 3.c) 15.2.3.7-6-a-151: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test RangeError is thrown when the [[Value]] field of 'desc' is -# boundary value 2^32 (15.4.5.1 step 3.c) -15.2.3.7-6-a-152: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test RangeError is thrown when the [[Value]] field of 'desc' is -# boundary value 2^32 + 1 (15.4.5.1 step 3.c) -15.2.3.7-6-a-153: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', test the [[Value]] field of 'desc' which is greater than value of -# the length property is defined into 'O' without deleting any property -# with large index named (15.4.5.1 step 3.f) 15.2.3.7-6-a-155: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', test the [[Value]] field of 'desc' which is less than value of the -# length property is defined into 'O' with deleting properties with large -# index named (15.4.5.1 step 3.f) 15.2.3.7-6-a-157: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Writable]] attribute of the length property is set -# to true at last after deleting properties with large index named if the -# [[Writable]] field of 'desc' is absent (15.4.5.1 step 3.h) 15.2.3.7-6-a-161: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Writable]] attribute of the length property is set -# to true at last after deleting properties with large index named if the -# [[Writable]] field of 'desc' is true (15.4.5.1 step 3.h) 15.2.3.7-6-a-162: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Writable]] attribute of the length property is set -# to false at last after deleting properties with large index named if the -# [[Writable]] field of 'desc' is false (15.4.5.1 step 3.i.ii) 15.2.3.7-6-a-163: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Writable]] attribute of the length property in 'O' -# is set as true before deleting properties with large index named -# (15.4.5.1 step 3.i.iii) 15.2.3.7-6-a-164: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the length property is decreased by 1 (15.4.5.1 step -# 3.l.i) 15.2.3.7-6-a-165: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of own data property with -# large index named in 'O' can stop deleting index named properties -# (15.4.5.1 step 3.l.ii) 15.2.3.7-6-a-166: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of inherited data property -# with large index named in 'O' can't stop deleting index named properties -# (15.4.5.1 step 3.l.ii) 15.2.3.7-6-a-167: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of own data property with -# large index named in 'O' that overrides inherited data property can stop -# deleting index named properties (15.4.5.1 step 3.l.ii) 15.2.3.7-6-a-168: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of own data property with -# large index named in 'O' that overrides inherited accessor property can -# stop deleting index named properties (15.4.5.1 step 3.l.ii) 15.2.3.7-6-a-169: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of own accessor property -# with large index named in 'O' can stop deleting index named properties -# (15.4.5.1 step 3.l.ii) 15.2.3.7-6-a-170: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of inherited accessor -# property with large index named in 'O' can't stop deleting index named -# properties (15.4.5.1 step 3.l.ii) 15.2.3.7-6-a-171: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of own accessor property -# with large index named in 'O' that overrides inherited data property can -# stop deleting index named properties (15.4.5.1 step 3.l.ii) 15.2.3.7-6-a-172: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of own accessor property -# with large index named in 'O' that overrides inherited accessor property -# can stop deleting index named properties (15.4.5.1 step 3.l.ii) 15.2.3.7-6-a-173: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the configurable large index named property of 'O' can be -# deleted (15.4.5.1 step 3.l.ii) 15.2.3.7-6-a-174: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test value of the length property is set to the last -# non-configurable index named property of 'O' plus 1 (15.4.5.1 step -# 3.l.iii.1) 15.2.3.7-6-a-175: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Writable]] attribute of the length property is set -# to false at last when the [[Writable]] field of 'desc' is false and 'O' -# contains non-configurable large index named property (15.4.5.1 step -# 3.l.iii.2) 15.2.3.7-6-a-176: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Writable]] attribute of the length property is set -# to false at last when the [[Writable]] field of 'desc' is false and 'O' -# doesn't contain non-configurable large index named property (15.4.5.1 -# step 3.m) 15.2.3.7-6-a-177: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is an array index named -# property, 'P' is boundary value 2^32 - 2 (15.4.5.1 step 4.a) +15.2.3.7-6-a-121: FAIL +15.2.3.7-6-a-130: FAIL +15.2.3.7-6-a-129: FAIL +15.2.3.7-6-a-131: FAIL +15.2.3.7-6-a-132: FAIL +15.2.3.7-6-a-136: FAIL +15.2.3.7-6-a-135: FAIL +15.2.3.7-6-a-134: FAIL +15.2.3.7-6-a-137: FAIL +15.2.3.7-6-a-141: FAIL +15.2.3.7-6-a-146: FAIL +15.2.3.7-6-a-148: FAIL +15.2.3.7-6-a-149: FAIL +15.2.3.7-6-a-152: FAIL +15.2.3.7-6-a-153: FAIL 15.2.3.7-6-a-179: FAIL -# Bug? Object.defineProperties - TypeError is thrown if 'O' is an Array, 'P' is -# an array index named property,[[Writable]] attribute of the length -# property in 'O' is false, value of 'P' is equal to value of the length -# property in 'O' (15.4.5.1 step 4.b) 15.2.3.7-6-a-184: FAIL -# Bug? Object.defineProperties - TypeError is thrown if 'O' is an Array, 'P' is -# an array index named property,[[Writable]] attribute of the length -# property in 'O' is false, value of 'P' is bigger than value of the length -# property in 'O' (15.4.5.1 step 4.b) 15.2.3.7-6-a-185: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is an array index named -# property, 'desc' is accessor descriptor, test updating all attribute -# values of 'P' (15.4.5.1 step 4.c) -15.2.3.7-6-a-205: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is an array index named -# property that already exists on 'O' is accessor property and 'desc' is -# accessor descriptor, test updating the [[Enumerable]] attribute value of -# 'P' (15.4.5.1 step 4.c) -15.2.3.7-6-a-260: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is an array index named -# property that already exists on 'O' is accessor property and 'desc' is -# accessor descriptor, test updating the [[Configurable]] attribute value -# of 'P' (15.4.5.1 step 4.c) -15.2.3.7-6-a-261: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is an array index named -# property that already exists on 'O' is accessor property and 'desc' is -# accessor descriptor, test updating multiple attribute values of 'P' -# (15.4.5.1 step 4.c) -15.2.3.7-6-a-262: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is an array index named -# property, test the length property of 'O' is set as ToUint32('P') + 1 if -# ToUint32('P') equals to value of the length property in 'O' (15.4.5.1 -# step 4.e.ii) 15.2.3.7-6-a-264: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is an array index named -# property, test the length property of 'O' is set as ToUint32('P') + 1 if -# ToUint32('P') is greater than value of the length property in 'O' -# (15.4.5.1 step 4.e.ii) 15.2.3.7-6-a-265: FAIL -# Bug? Object.defineProperties - 'O' is an Arguments object, 'P' is own accessor -# property of 'O' which is also defined in [[ParameterMap]] of 'O', and -# 'desc' is accessor descriptor, test updating multiple attribute values of -# 'P' (10.6 [[DefineOwnProperty]] step 3) -15.2.3.7-6-a-280: FAIL -# Bug? Object.defineProperties - 'O' is an Arguments object, 'P' is own data -# property of 'O' which is also defined in [[ParameterMap]] of 'O', and -# 'desc' is data descriptor, test updating multiple attribute values of 'P' -# (10.6 [[DefineOwnProperty]] step 3) -15.2.3.7-6-a-281: FAIL -# Bug? Object.defineProperties - 'O' is an Arguments object, 'P' is own data -# property of 'O' which is also defined in [[ParameterMap]] of 'O', test -# TypeError is thrown when updating the [[Value]] attribute value of 'P' -# whose writable and configurable attributes are false (10.6 -# [[DefineOwnProperty]] step 4) -15.2.3.7-6-a-282: FAIL -# Bug? Object.defineProperties - 'O' is an Arguments object, 'P' is own data -# property of 'O' which is also defined in [[ParameterMap]] of 'O', test -# TypeError is thrown when updating the [[Writable]] attribute value of 'P' -# which is defined as non-configurable (10.6 [[DefineOwnProperty]] step 4) -15.2.3.7-6-a-283: FAIL -# Bug? Object.defineProperties - 'O' is an Arguments object, 'P' is own data -# property of 'O' which is also defined in [[ParameterMap]] of 'O', test -# TypeError is thrown when updating the [[Enumerable]] attribute value of -# 'P' which is defined as non-configurable (10.6 [[DefineOwnProperty]] step -# 4) -15.2.3.7-6-a-284: FAIL -# Bug? Object.defineProperties - 'O' is an Arguments object, 'P' is own data -# property of 'O' which is also defined in [[ParameterMap]] of 'O', test -# TypeError is thrown when updating the [[Configurable]] attribute value of -# 'P' which is defined as non-configurable (10.6 [[DefineOwnProperty]] step -# 4) -15.2.3.7-6-a-285: FAIL -# Bug? Object.defineProperties - 'O' is an Arguments object, 'P' is an array -# index named accessor property of 'O' but not defined in [[ParameterMap]] -# of 'O', and 'desc' is accessor descriptor, test updating multiple -# attribute values of 'P' (10.6 [[DefineOwnProperty]] step 3) -15.2.3.7-6-a-292: FAIL -# Bug? Strict Mode - 'this' value is a string which cannot be converted to -# wrapper objects when the function is called with an array of arguments -15.3.4.3-1-s: FAIL -# Bug? Strict Mode - 'this' value is a number which cannot be converted to -# wrapper objects when the function is called with an array of arguments -15.3.4.3-2-s: FAIL -# Bug? Strict Mode - 'this' value is a boolean which cannot be converted to -# wrapper objects when the function is called with an array of arguments -15.3.4.3-3-s: FAIL -# Bug? Function.prototype.bind - [[Get]] attribute of 'caller' property in 'F' -# is thrower -15.3.4.5-20-2: FAIL -# Bug? Function.prototype.bind - [[Set]] attribute of 'caller' property in 'F' -# is thrower -15.3.4.5-20-3: FAIL -# Bug? Function.prototype.bind - [[Get]] attribute of 'arguments' property in -# 'F' is thrower -15.3.4.5-21-2: FAIL -# Bug? Function.prototype.bind - [[Set]] attribute of 'arguments' property in -# 'F' is thrower -15.3.4.5-21-3: FAIL -# Bug? Array.prototype.indexOf - decreasing length of array does not delete -# non-configurable properties -15.4.4.14-9-a-19: FAIL -# Bug? Array.prototype.indexOf - element to be retrieved is own accessor -# property that overrides an inherited data property on an Array 15.4.4.14-9-b-i-11: FAIL -# Bug? Array.prototype.indexOf - element to be retrieved is own accessor -# property that overrides an inherited accessor property on an Array 15.4.4.14-9-b-i-13: FAIL -# Bug? Array.prototype.indexOf - element to be retrieved is own accessor -# property without a get function on an Array 15.4.4.14-9-b-i-17: FAIL -# Bug? Array.prototype.indexOf - element to be retrieved is own accessor -# property without a get function that overrides an inherited accessor -# property on an Array 15.4.4.14-9-b-i-19: FAIL -# Bug? Array.prototype.indexOf - side-effects are visible in subsequent -# iterations on an Array 15.4.4.14-9-b-i-28: FAIL -# Bug? Array.prototype.indexOf - terminates iteration on unhandled exception on -# an Array 15.4.4.14-9-b-i-30: FAIL -# Bug? Array.prototype.lastIndexOf - deleting property of prototype causes -# prototype index property not to be visited on an Array 15.4.4.15-8-a-14: FAIL -# Bug? Array.prototype.lastIndexOf - decreasing length of array does not delete -# non-configurable properties -15.4.4.15-8-a-19: FAIL -# Bug? Array.prototype.lastIndexOf - element to be retrieved is own accessor -# property that overrides an inherited data property on an Array 15.4.4.15-8-b-i-11: FAIL -# Bug? Array.prototype.lastIndexOf - element to be retrieved is own accessor -# property that overrides an inherited accessor property on an Array 15.4.4.15-8-b-i-13: FAIL -# Bug? Array.prototype.lastIndexOf - element to be retrieved is own accessor -# property without a get function on an Array 15.4.4.15-8-b-i-17: FAIL -# Bug? Array.prototype.lastIndexOf - side-effects are visible in subsequent -# iterations on an Array 15.4.4.15-8-b-i-28: FAIL -# Bug? Array.prototype.lastIndexOf terminates iteration on unhandled exception -# on an Array 15.4.4.15-8-b-i-30: FAIL -# Bug? Array.prototype.every applied to boolean primitive -15.4.4.16-1-3: FAIL -# Bug? Array.prototype.every applied to number primitive -15.4.4.16-1-5: FAIL -# Bug? Array.prototype.every applied to string primitive -15.4.4.16-1-7: FAIL -# Bug? Array.prototype.every - side effects produced by step 2 are visible when -# an exception occurs -15.4.4.16-4-8: FAIL -# Bug? Array.prototype.every - side effects produced by step 3 are visible when -# an exception occurs -15.4.4.16-4-9: FAIL -# Bug? Array.prototype.every - the exception is not thrown if exception was -# thrown by step 2 -15.4.4.16-4-10: FAIL -# Bug? Array.prototype.every - the exception is not thrown if exception was -# thrown by step 3 -15.4.4.16-4-11: FAIL -# Bug? Array.prototype.every - calling with no callbackfn is the same as passing -# undefined for callbackfn -15.4.4.16-4-15: FAIL -# Bug? Array.prototype.every - decreasing length of array does not delete -# non-configurable properties -15.4.4.16-7-b-16: FAIL -# Bug? Array.prototype.every - element to be retrieved is own accessor property -# on an Array 15.4.4.16-7-c-i-10: FAIL -# Bug? Array.prototype.every - element to be retrieved is own accessor property -# that overrides an inherited data property on an Array 15.4.4.16-7-c-i-12: FAIL -# Bug? Array.prototype.every - element to be retrieved is own accessor property -# that overrides an inherited accessor property on an Array 15.4.4.16-7-c-i-14: FAIL -# Bug? Array.prototype.every - element to be retrieved is own accessor property -# without a get function on an Array 15.4.4.16-7-c-i-18: FAIL -# Bug? Array.prototype.every - element to be retrieved is own accessor property -# without a get function that overrides an inherited accessor property on -# an Array 15.4.4.16-7-c-i-20: FAIL -# Bug? Array.prototype.every - element changed by getter on previous iterations -# is observed on an Array 15.4.4.16-7-c-i-28: FAIL -# Bug? Array.prototype.some applied to boolean primitive -15.4.4.17-1-3: FAIL -# Bug? Array.prototype.some applied to number primitive -15.4.4.17-1-5: FAIL -# Bug? Array.prototype.some applied to applied to string primitive -15.4.4.17-1-7: FAIL -# Bug? Array.prototype.some - side effects produced by step 2 are visible when -# an exception occurs -15.4.4.17-4-8: FAIL -# Bug? Array.prototype.some - side effects produced by step 3 are visible when -# an exception occurs -15.4.4.17-4-9: FAIL -# Bug? Array.prototype.some - the exception is not thrown if exception was -# thrown by step 2 -15.4.4.17-4-10: FAIL -# Bug? Array.prototype.some - the exception is not thrown if exception was -# thrown by step 3 -15.4.4.17-4-11: FAIL -# Bug? Array.prototype.some - calling with no callbackfn is the same as passing -# undefined for callbackfn -15.4.4.17-4-15: FAIL -# Bug? Array.prototype.some - decreasing length of array does not delete -# non-configurable properties -15.4.4.17-7-b-16: FAIL -# Bug? Array.prototype.some - element to be retrieved is own accessor property -# on an Array 15.4.4.17-7-c-i-10: FAIL -# Bug? Array.prototype.some - element to be retrieved is own accessor property -# that overrides an inherited data property on an Array 15.4.4.17-7-c-i-12: FAIL -# Bug? Array.prototype.some - element to be retrieved is own accessor property -# that overrides an inherited accessor property on an Array 15.4.4.17-7-c-i-14: FAIL -# Bug? Array.prototype.some - element to be retrieved is own accessor property -# without a get function on an Array 15.4.4.17-7-c-i-18: FAIL -# Bug? Array.prototype.some - element to be retrieved is own accessor property -# without a get function that overrides an inherited accessor property on -# an Array 15.4.4.17-7-c-i-20: FAIL -# Bug? Array.prototype.some - element changed by getter on previous iterations -# is observed on an Array 15.4.4.17-7-c-i-28: FAIL -# Bug? Array.prototype.forEach applied to boolean primitive -15.4.4.18-1-3: FAIL -# Bug? Array.prototype.forEach applied to number primitive -15.4.4.18-1-5: FAIL -# Bug? Array.prototype.forEach applied to string primitive -15.4.4.18-1-7: FAIL -# Bug? Array.prototype.forEach - side effects produced by step 2 are visible -# when an exception occurs -15.4.4.18-4-8: FAIL -# Bug? Array.prototype.forEach - side effects produced by step 3 are visible -# when an exception occurs -15.4.4.18-4-9: FAIL -# Bug? Array.prototype.forEach - the exception is not thrown if exception was -# thrown by step 2 -15.4.4.18-4-10: FAIL -# Bug? Array.prototype.forEach - the exception is not thrown if exception was -# thrown by step 3 -15.4.4.18-4-11: FAIL -# Bug? Array.prototype.forEach - calling with no callbackfn is the same as -# passing undefined for callbackfn -15.4.4.18-4-15: FAIL -# Bug? Array.prototype.forEach - decreasing length of array does not delete -# non-configurable properties -15.4.4.18-7-b-16: FAIL -# Bug? Array.prototype.forEach - element to be retrieved is own accessor -# property on an Array 15.4.4.18-7-c-i-10: FAIL -# Bug? Array.prototype.forEach - element to be retrieved is own accessor -# property that overrides an inherited data property on an Array 15.4.4.18-7-c-i-12: FAIL -# Bug? Array.prototype.forEach - element to be retrieved is own accessor -# property that overrides an inherited accessor property on an Array 15.4.4.18-7-c-i-14: FAIL -# Bug? Array.prototype.forEach - element to be retrieved is own accessor -# property without a get function on an Array 15.4.4.18-7-c-i-18: FAIL -# Bug? Array.prototype.forEach - element to be retrieved is own accessor -# property without a get function that overrides an inherited accessor -# property on an Array 15.4.4.18-7-c-i-20: FAIL -# Bug? Array.prototype.forEach - element changed by getter on previous -# iterations is observed on an Array 15.4.4.18-7-c-i-28: FAIL -# Bug? Array.prototype.map - applied to boolean primitive -15.4.4.19-1-3: FAIL -# Bug? Array.prototype.map - applied to number primitive -15.4.4.19-1-5: FAIL -# Bug? Array.prototype.map - applied to string primitive -15.4.4.19-1-7: FAIL -# Bug? Array.prototype.map - Side effects produced by step 2 are visible when an -# exception occurs -15.4.4.19-4-8: FAIL -# Bug? Array.prototype.map - Side effects produced by step 3 are visible when an -# exception occurs -15.4.4.19-4-9: FAIL -# Bug? Array.prototype.map - the exception is not thrown if exception was thrown -# by step 2 -15.4.4.19-4-10: FAIL -# Bug? Array.prototype.map - the exception is not thrown if exception was thrown -# by step 3 -15.4.4.19-4-11: FAIL -# Bug? Array.prototype.map - calling with no callbackfn is the same as passing -# undefined for callbackfn -15.4.4.19-4-15: FAIL -# Bug? Array.prototype.map - decreasing length of array does not delete -# non-configurable properties -15.4.4.19-8-b-16: FAIL -# Bug? Array.prototype.map - element to be retrieved is own accessor property on -# an Array 15.4.4.19-8-c-i-10: FAIL -# Bug? Array.prototype.map - element to be retrieved is own accessor property -# that overrides an inherited data property on an Array -15.4.4.19-8-c-i-12: FAIL -# Bug? Array.prototype.map - element to be retrieved is own accessor property -# that overrides an inherited accessor property on an Array 15.4.4.19-8-c-i-14: FAIL -# Bug? Array.prototype.map - element to be retrieved is own accessor property -# without a get function on an Array +15.4.4.19-8-c-i-12: FAIL 15.4.4.19-8-c-i-18: FAIL -# Bug? Array.prototype.map - element to be retrieved is own accessor property -# without a get function that overrides an inherited accessor property on -# an Array 15.4.4.19-8-c-i-19: FAIL -# Bug? Array.prototype.map - element changed by getter on previous iterations is -# observed on an Array 15.4.4.19-8-c-i-28: FAIL -# Bug? Array.prototype.filter applied to boolean primitive -15.4.4.20-1-3: FAIL -# Bug? Array.prototype.filter applied to number primitive -15.4.4.20-1-5: FAIL -# Bug? Array.prototype.filter applied to string primitive -15.4.4.20-1-7: FAIL -# Bug? Array.prototype.filter - side effects produced by step 2 are visible when -# an exception occurs -15.4.4.20-4-8: FAIL -# Bug? Array.prototype.filter - side effects produced by step 3 are visible when -# an exception occurs -15.4.4.20-4-9: FAIL -# Bug? Array.prototype.filter - the exception is not thrown if exception was -# thrown by step 2 -15.4.4.20-4-10: FAIL -# Bug? Array.prototype.filter - the exception is not thrown if exception was -# thrown by step 3 -15.4.4.20-4-11: FAIL -# Bug? Array.prototype.filter - calling with no callbackfn is the same as -# passing undefined for callbackfn -15.4.4.20-4-15: FAIL -# Bug? Array.prototype.filter - properties can be added to prototype after -# current position are visited on an Array-like object -15.4.4.20-9-b-6: FAIL -# Bug? Array.prototype.filter - decreasing length of array does not delete -# non-configurable properties -15.4.4.20-9-b-16: FAIL -# Bug? Array.prototype.filter - element to be retrieved is own data property -# that overrides an inherited accessor property on an Array -15.4.4.20-9-c-i-6: FAIL -# Bug? Array.prototype.filter - element to be retrieved is own accessor property -# on an Array 15.4.4.20-9-c-i-10: FAIL -# Bug? Array.prototype.filter - element to be retrieved is own accessor property -# that overrides an inherited data property on an Array 15.4.4.20-9-c-i-12: FAIL -# Bug? Array.prototype.filter - element to be retrieved is own accessor property -# that overrides an inherited accessor property on an Array 15.4.4.20-9-c-i-14: FAIL -# Bug? Array.prototype.filter - element to be retrieved is inherited accessor -# property on an Array -15.4.4.20-9-c-i-16: FAIL -# Bug? Array.prototype.filter - element to be retrieved is own accessor property -# without a get function on an Array 15.4.4.20-9-c-i-18: FAIL -# Bug? Array.prototype.filter - element to be retrieved is own accessor property -# without a get function that overrides an inherited accessor property on -# an Array 15.4.4.20-9-c-i-20: FAIL -# Bug? Array.prototype.filter - element to be retrieved is inherited accessor -# property without a get function on an Array -15.4.4.20-9-c-i-22: FAIL -# Bug? Array.prototype.filter - element changed by getter on previous iterations -# is observed on an Array 15.4.4.20-9-c-i-28: FAIL -# Bug? Array.prototype.reduce applied to boolean primitive -15.4.4.21-1-3: FAIL -# Bug? Array.prototype.reduce applied to number primitive -15.4.4.21-1-5: FAIL -# Bug? Array.prototype.reduce applied to string primitive -15.4.4.21-1-7: FAIL -# Bug? Array.prototype.reduce - side effects produced by step 2 are visible when -# an exception occurs -15.4.4.21-4-8: FAIL -# Bug? Array.prototype.reduce - side effects produced by step 3 are visible when -# an exception occurs -15.4.4.21-4-9: FAIL -# Bug? Array.prototype.reduce - the exception is not thrown if exception was -# thrown by step 2 -15.4.4.21-4-10: FAIL -# Bug? Array.prototype.reduce - the exception is not thrown if exception was -# thrown by step 3 -15.4.4.21-4-11: FAIL -# Bug? Array.prototype.reduce - calling with no callbackfn is the same as -# passing undefined for callbackfn -15.4.4.21-4-15: FAIL -# Bug? Array.prototype.reduce - decreasing length of array in step 8 does not -# delete non-configurable properties -15.4.4.21-9-b-16: FAIL -# Bug? Array.prototype.reduce - decreasing length of array does not delete -# non-configurable properties -15.4.4.21-9-b-29: FAIL -# Bug? Array.prototype.reduceRight applied to boolean primitive -15.4.4.22-1-3: FAIL -# Bug? Array.prototype.reduceRight applied to number primitive -15.4.4.22-1-5: FAIL -# Bug? Array.prototype.reduceRight applied to string primitive -15.4.4.22-1-7: FAIL -# Bug? Array.prototype.reduceRight - side effects produced by step 2 are visible -# when an exception occurs -15.4.4.22-4-8: FAIL -# Bug? Array.prototype.reduceRight - side effects produced by step 3 are visible -# when an exception occurs -15.4.4.22-4-9: FAIL -# Bug? Array.prototype.reduceRight - the exception is not thrown if exception -# was thrown by step 2 -15.4.4.22-4-10: FAIL -# Bug? Array.prototype.reduceRight - the exception is not thrown if exception -# was thrown by step 3 -15.4.4.22-4-11: FAIL -# Bug? Array.prototype.reduceRight - calling with no callbackfn is the same as -# passing undefined for callbackfn -15.4.4.22-4-15: FAIL -# Bug? Array.prototype.reduceRight - element to be retrieved is own accessor -# property that overrides an inherited data property on an Array +15.4.4.22-8-b-2: FAIL 15.4.4.22-8-b-iii-1-12: FAIL -# Bug? Array.prototype.reduceRight - element to be retrieved is own accessor -# property without a get function on an Array 15.4.4.22-8-b-iii-1-18: FAIL -# Bug? Array.prototype.reduceRight - element to be retrieved is own accessor -# property without a get function that overrides an inherited accessor -# property on an Array 15.4.4.22-8-b-iii-1-20: FAIL -# Bug? Array.prototype.reduceRight - element changed by getter on current -# iteration is observed in subsequent iterations on an Array -15.4.4.22-8-b-iii-1-30: FAIL -# Bug? Array.prototype.reduceRight - Exception in getter terminate iteration on -# an Array 15.4.4.22-8-b-iii-1-33: FAIL -# Bug? Array.prototype.reduceRight - modifications to length don't change number -# of iterations in step 9 -15.4.4.22-8-b-2: FAIL -# Bug? Array.prototype.reduceRight - deleting own property in step 8 causes -# deleted index property not to be visited on an Array -15.4.4.22-9-b-9: FAIL -# Bug? Array.prototype.reduceRight - deleting own property with prototype -# property in step 8 causes prototype index property to be visited on an -# Array +15.4.4.22-8-b-iii-1-30: FAIL 15.4.4.22-9-b-13: FAIL -# Bug? Array.prototype.reduceRight - decreasing length of array in step 8 does -# not delete non-configurable properties -15.4.4.22-9-b-16: FAIL -# Bug? Array.prototype.reduceRight - deleting property of prototype causes -# deleted index property not to be visited on an Array 15.4.4.22-9-b-24: FAIL -# Bug? Array.prototype.reduceRight - deleting own property with prototype -# property causes prototype index property to be visited on an Array 15.4.4.22-9-b-26: FAIL -# Bug? Array.prototype.reduceRight - decreasing length of array does not delete -# non-configurable properties -15.4.4.22-9-b-29: FAIL -# Bug? Array.prototype.reduceRight - element changed by getter on previous -# iterations is observed on an Array +15.4.4.22-9-b-9: FAIL 15.4.4.22-9-c-i-30: FAIL -# Bug? Array.prototype.reduceRight - modifications to length will change number -# of iterations + +# V8 Bug: http://code.google.com/p/v8/issues/detail?id=1772 +15.2.3.6-4-292-1: FAIL +15.2.3.6-4-293-2: FAIL +15.2.3.6-4-293-3: FAIL +15.2.3.6-4-294-1: FAIL +15.2.3.6-4-295-1: FAIL +15.2.3.6-4-296-1: FAIL +15.2.3.6-4-333-11: FAIL +15.2.3.7-6-a-281: FAIL +15.2.3.7-6-a-282: FAIL +15.2.3.7-6-a-283: FAIL +15.2.3.7-6-a-284: FAIL +15.2.3.7-6-a-285: FAIL + +# V8 Bug: http://code.google.com/p/v8/issues/detail?id=1790 15.4.4.22-9-9: FAIL -# Bug? String.prototype.trim - 'S' is a string with all WhiteSpace -15.5.4.20-3-2: FAIL -# Bug? String.prototype.trim - 'S' is a string with all union of WhiteSpace and -# LineTerminator -15.5.4.20-3-3: FAIL -# Bug? String.prototype.trim - 'S' is a string start with union of all -# LineTerminator and all WhiteSpace -15.5.4.20-3-4: FAIL -# Bug? String.prototype.trim - 'S' is a string end with union of all -# LineTerminator and all WhiteSpace -15.5.4.20-3-5: FAIL -# Bug? String.prototype.trim - 'S' is a string start with union of all -# LineTerminator and all WhiteSpace and end with union of all -# LineTerminator and all WhiteSpace -15.5.4.20-3-6: FAIL -# Bug? String.prototype.trim handles whitepace and lineterminators (\\uFEFFabc) -15.5.4.20-4-10: FAIL -# Bug? String.prototype.trim handles whitepace and lineterminators (abc\\uFEFF) -15.5.4.20-4-18: FAIL -# Bug? String.prototype.trim handles whitepace and lineterminators -# (\\uFEFF\\uFEFF) -15.5.4.20-4-34: FAIL -# Bug? Date.prototype.toISOString - RangeError is thrown when value of date is -# Date(1970, 0, -99999999, 0, 0, 0, -1), the time zone is UTC(0) -15.9.5.43-0-8: FAIL -# Bug? Date.prototype.toISOString - RangeError is not thrown when value of date -# is Date(1970, 0, 100000001, 0, 0, 0, -1), the time zone is UTC(0) -15.9.5.43-0-11: FAIL -# Bug? Date.prototype.toISOString - RangeError is not thrown when value of date -# is Date(1970, 0, 100000001, 0, 0, 0, 0), the time zone is UTC(0) -15.9.5.43-0-12: FAIL -# Bug? Date.prototype.toISOString - RangeError is thrown when value of date is -# Date(1970, 0, 100000001, 0, 0, 0, 1), the time zone is UTC(0) -15.9.5.43-0-13: FAIL -# Bug? Date.prototype.toISOString - when value of year is -Infinity -# Date.prototype.toISOString throw the RangeError -15.9.5.43-0-14: FAIL -# Bug? Date.prototype.toISOString - value of year is Infinity -# Date.prototype.toISOString throw the RangeError -15.9.5.43-0-15: FAIL -# Bug? RegExp - the thrown error is SyntaxError instead of RegExpError when 'F' -# contains any character other than 'g', 'i', or 'm' -15.10.4.1-3: FAIL -# Bug? RegExp.prototype is itself a RegExp -15.10.6: FAIL -# Bug? RegExp.prototype.source is of type String -15.10.7.1-1: FAIL -# Bug? RegExp.prototype.source is a data property with default attribute values -# (false) -15.10.7.1-2: FAIL -# Bug? RegExp.prototype.global is of type Boolean -15.10.7.2-1: FAIL -# Bug? RegExp.prototype.global is a data property with default attribute values -# (false) -15.10.7.2-2: FAIL -# Bug? RegExp.prototype.ignoreCase is of type Boolean -15.10.7.3-1: FAIL -# Bug? RegExp.prototype.ignoreCase is a data property with default attribute -# values (false) -15.10.7.3-2: FAIL -# Bug? RegExp.prototype.multiline is of type Boolean -15.10.7.4-1: FAIL -# Bug? RegExp.prototype.multiline is a data property with default attribute -# values (false) -15.10.7.4-2: FAIL -# Bug? RegExp.prototype.lastIndex is of type Number -15.10.7.5-1: FAIL -# Bug? RegExp.prototype.lastIndex is a data property with specified attribute -# values -15.10.7.5-2: FAIL -# Bug? Error.prototype.toString return the value of 'msg' when 'name' is empty -# string and 'msg' isn't undefined -15.11.4.4-8-1: FAIL + +# Invalid test cases (recent change adding var changes semantics) +S8.3_A1_T1: FAIL +S15.3_A3_T1: FAIL +S15.3_A3_T3: FAIL + +##################### DELIBERATE INCOMPATIBILITIES ##################### + +# We deliberately treat arguments to parseInt() with a leading zero as +# octal numbers in order to not break the web. +S15.1.2.2_A5.1_T1: FAIL_OK + +# This tests precision of trignometric functions. We're slightly off +# from the implementation in libc (~ 1e-17) but it's not clear if we +# or they are closer to the right answer, or if it even matters. +S15.8.2.16_A7: PASS || FAIL_OK +S15.8.2.18_A7: PASS || FAIL_OK +S15.8.2.13_A23: PASS || FAIL_OK + +# Sputnik tests (r97) assume RegExp.prototype is an Object, not a RegExp. +S15.10.6_A2: 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 +S15.10.2.11_A1_T3: FAIL + +# We are more lenient in which string character escapes we allow than +# the spec (7.8.4 p. 19) wants us to be. This is for compatibility. +S7.8.4_A4.3_T3: FAIL_OK +S7.8.4_A4.3_T4: FAIL_OK +S7.8.4_A4.3_T5: FAIL_OK +S7.8.4_A4.3_T6: FAIL_OK +S7.8.4_A6.1_T4: FAIL_OK +S7.8.4_A6.2_T1: FAIL_OK +S7.8.4_A6.2_T2: FAIL_OK +S7.8.4_A6.4_T1: FAIL_OK +S7.8.4_A6.4_T2: FAIL_OK +S7.8.4_A7.1_T4: FAIL_OK +S7.8.4_A7.2_T1: FAIL_OK +S7.8.4_A7.2_T2: FAIL_OK +S7.8.4_A7.2_T3: FAIL_OK +S7.8.4_A7.2_T4: FAIL_OK +S7.8.4_A7.2_T5: FAIL_OK +S7.8.4_A7.2_T6: FAIL_OK +S7.8.4_A7.4_T1: FAIL_OK +S7.8.4_A7.4_T2: FAIL_OK + +# Sputnik expects unicode escape sequences in RegExp flags to be interpreted. +# The specification requires them to be passed uninterpreted to the RegExp +# constructor. We now implement that. +S7.8.5_A3.1_T7: FAIL_OK +S7.8.5_A3.1_T8: FAIL_OK +S7.8.5_A3.1_T9: FAIL_OK + +# We allow some keywords to be used as identifiers. +S7.5.3_A1.15: FAIL_OK +S7.5.3_A1.18: FAIL_OK +S7.5.3_A1.21: FAIL_OK +S7.5.3_A1.22: FAIL_OK +S7.5.3_A1.23: FAIL_OK +S7.5.3_A1.24: FAIL_OK +S7.5.3_A1.26: FAIL_OK + +# This checks for non-262 behavior +S7.6_D1: PASS || FAIL_OK +S7.6_D2: PASS || FAIL_OK +S8.4_D1.1: PASS || FAIL_OK +S8.4_D2.1: PASS || FAIL_OK +S8.4_D2.2: PASS || FAIL_OK +S8.4_D2.3: PASS || FAIL_OK +S8.4_D2.4: PASS || FAIL_OK +S8.4_D2.5: PASS || FAIL_OK +S8.4_D2.6: PASS || FAIL_OK +S8.4_D2.7: PASS || FAIL_OK +S11.4.3_D1.2: PASS || FAIL_OK +S12.6.4_A14_T1: PASS || FAIL_OK +S12.6.4_D1: PASS || FAIL_OK +S12.6.4_R1: PASS || FAIL_OK +S12.6.4_R2: PASS || FAIL_OK +S13.2_D1.2: PASS || FAIL_OK +S13_D1_T1: PASS || FAIL_OK +S14_D4_T3: PASS || FAIL_OK +S14_D7: PASS || FAIL_OK +S15.1.2.2_D1.2: PASS || FAIL_OK +S15.5.2_D2: PASS || FAIL_OK +S15.5.4.11_D1.1_T1: PASS || FAIL_OK +S15.5.4.11_D1.1_T2: PASS || FAIL_OK +S15.5.4.11_D1.1_T3: PASS || FAIL_OK +S15.5.4.11_D1.1_T4: PASS || FAIL_OK + +# We allow function declarations within statements +S12.6.2_A13_T1: FAIL_OK +S12.6.2_A13_T2: FAIL_OK +S12.6.4_A13_T1: FAIL_OK +S12.6.4_A13_T2: FAIL_OK +S15.3.4.2_A1_T1: FAIL_OK + +# Linux and Mac defaults to extended 80 bit floating point format in the FPU. +# We follow the other major JS engines by keeping this default. +S8.5_A2.2: PASS, FAIL if $system == linux, FAIL if $system == macos +S8.5_A2.1: PASS, FAIL if $system == linux, FAIL if $system == macos + +############################# ES3 TESTS ################################ +# These tests check for ES3 semantics, and differ from ES5. +# When we follow ES5 semantics, it's ok to fail the test. + +# Allow keywords as names of properties in object initialisers and +# in dot-notation property access. +S11.1.5_A4.1: FAIL_OK +S11.1.5_A4.2: FAIL_OK + +# Calls builtins without an explicit receiver which means that +# undefined is passed to the builtin. The tests expect the global +# object to be passed which was true in ES3 but not in ES5. +S11.1.1_A2: FAIL_OK +S15.5.4.4_A1_T3: FAIL_OK +S15.5.4.5_A1_T3: FAIL_OK +S15.5.4.6_A1_T3: FAIL_OK +S15.5.4.7_A1_T3: FAIL_OK +S15.5.4.8_A1_T3: FAIL_OK +S15.5.4.9_A1_T3: FAIL_OK +S15.5.4.10_A1_T3: FAIL_OK +S15.5.4.11_A1_T3: FAIL_OK +S15.5.4.12_A1_T3: FAIL_OK +S15.5.4.13_A1_T3: FAIL_OK +S15.5.4.14_A1_T3: FAIL_OK +S15.5.4.15_A1_T3: FAIL_OK + +# NaN, Infinity and undefined are read-only according to ES5. +S15.1.1.1_A2_T1: FAIL_OK # NaN +S15.1.1.1_A2_T2: FAIL_OK # NaN +S15.1.1.2_A2_T1: FAIL_OK # Infinity +# S15.1.1.2_A2_T2 would fail if it weren't bogus in r97. sputnik bug #45. +S15.1.1.3_A2_T1: FAIL_OK # undefined +S15.1.1.3_A2_T2: FAIL_OK # undefined + +# Array.prototype.to[Locale]String is generic in ES5. +S15.4.4.2_A2_T1: FAIL_OK +S15.4.4.3_A2_T1: FAIL_OK + +######################### UNANALYZED FAILURES ########################## + +# Bug? ES5 Attributes - Updating indexed data property 'P' whose attributes are +# [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: true to an +# accessor property, 'A' is an Array object (8.12.9 - step 9.b.i) +15.2.3.6-4-360-1: FAIL +# Bug? ES5 Attributes - Updating indexed data property 'P' whose attributes are +# [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: true to an +# accessor property, 'O' is an Arguments object (8.12.9 - step 9.b.i) +15.2.3.6-4-360-6: FAIL +# Bug? ES5 Attributes - Updating indexed data property 'P' whose attributes are +# [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: true to an +# accessor property, 'O' is the global object (8.12.9 - step 9.b.i) +15.2.3.6-4-360-7: FAIL +# Bug? ES5 Attributes - Failed to add a property to an object when the object's +# object has a property with same name and [[Writable]] attribute is set to +# false (Number instance) +15.2.3.6-4-405: FAIL +# Bug? ES5 Attributes - Failed to add a property to an object when the object's +# prototype has a property with the same name and [[Writable]] set to false +# (JSON) +15.2.3.6-4-410: FAIL +# Bug? ES5 Attributes - Failed to add properties to an object when the object's +# prototype has properties with the same name and [[Writable]] set to false +# (Object.create) +15.2.3.6-4-415: FAIL +# Bug? ES5 Attributes - Failed to add a property to an object when the object's +# prototype has a property with the same name and [[Writable]] set to +# false(Function.prototype.bind) +15.2.3.6-4-420: FAIL + +############################ SKIPPED TESTS ############################# + +# These tests take a looong time to run in debug mode. +S15.1.3.2_A2.5_T1: PASS, SKIP if $mode == debug +S15.1.3.1_A2.5_T1: PASS, SKIP if $mode == debug + +[ $arch == arm ] + +# BUG(3251225): Tests that timeout with --nocrankshaft. +S15.1.3.1_A2.5_T1: SKIP +S15.1.3.2_A2.5_T1: SKIP +S15.1.3.1_A2.4_T1: SKIP +S15.1.3.1_A2.5_T1: SKIP +S15.1.3.2_A2.4_T1: SKIP +S15.1.3.2_A2.5_T1: SKIP +S15.1.3.3_A2.3_T1: SKIP +S15.1.3.4_A2.3_T1: SKIP +S15.1.3.1_A2.5_T1: SKIP +S15.1.3.2_A2.5_T1: SKIP + +[ $arch == mips ] + +# Skip all tests on MIPS. +*: SKIP diff --git a/test/test262/testcfg.py b/test/test262/testcfg.py index 94820460..52127cdd 100644 --- a/test/test262/testcfg.py +++ b/test/test262/testcfg.py @@ -43,10 +43,10 @@ class Test262TestCase(test.TestCase): self.root = root def IsNegative(self): - return self.filename.endswith('-n.js') + return '@negative' in self.GetSource() def GetLabel(self): - return "%s test262 %s %s" % (self.mode, self.GetGroup(), self.GetName()) + return "%s test262 %s" % (self.mode, self.GetName()) def IsFailureOutput(self, output): if output.exit_code != 0: @@ -63,9 +63,6 @@ class Test262TestCase(test.TestCase): def GetName(self): return self.path[-1] - def GetGroup(self): - return self.path[0] - def GetSource(self): return open(self.filename).read() @@ -75,13 +72,14 @@ class Test262TestConfiguration(test.TestConfiguration): def __init__(self, context, root): super(Test262TestConfiguration, self).__init__(context, root) - def AddIETestCenter(self, tests, current_path, path, mode): - current_root = join(self.root, 'data', 'test', 'suite', 'ietestcenter') + def ListTests(self, current_path, path, mode, variant_flags): + testroot = join(self.root, 'data', 'test', 'suite') harness = [join(self.root, 'data', 'test', 'harness', f) for f in TEST_262_HARNESS] harness += [join(self.root, 'harness-adapt.js')] - for root, dirs, files in os.walk(current_root): - for dotted in [x for x in dirs if x.startswith('.')]: + tests = [] + for root, dirs, files in os.walk(testroot): + for dotted in [x for x in dirs if x.startswith('.')]: dirs.remove(dotted) dirs.sort() root_path = root[len(self.root):].split(os.path.sep) @@ -89,25 +87,11 @@ class Test262TestConfiguration(test.TestConfiguration): files.sort() for file in files: if file.endswith('.js'): - if self.Contains(path, root_path): - test_path = ['ietestcenter', file[:-3]] + test_path = ['test262', file[:-3]] + if self.Contains(path, test_path): test = Test262TestCase(join(root, file), test_path, self.context, self.root, mode, harness) tests.append(test) - - def AddSputnikConvertedTests(self, tests, current_path, path, mode): - # To be enabled - pass - - def AddSputnikTests(self, tests, current_path, path, mode): - # To be enabled - pass - - def ListTests(self, current_path, path, mode, variant_flags): - tests = [] - self.AddIETestCenter(tests, current_path, path, mode) - self.AddSputnikConvertedTests(tests, current_path, path, mode) - self.AddSputnikTests(tests, current_path, path, mode) return tests def GetBuildRequirements(self): |
