Merge V8 at 3.7.12.28
Bug: 5688872
Change-Id: Iddb40cae44d51a2b449f2858951e0472771f5981
diff --git a/test/cctest/SConscript b/test/cctest/SConscript
index 5c92671..621d8ec 100644
--- a/test/cctest/SConscript
+++ b/test/cctest/SConscript
@@ -73,7 +73,6 @@
'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 5d0cab3..3b8f4f6 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 5122da5..7161345 100644
--- a/test/cctest/cctest.status
+++ b/test/cctest/cctest.status
@@ -33,11 +33,22 @@
# 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 d95536d..b1900f9 100644
--- a/test/cctest/test-accessors.cc
+++ b/test/cctest/test-accessors.cc
@@ -241,7 +241,7 @@
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 9767192..cf9d488 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 @@
}
CHECK(!heap->AllocateRawAsciiString(100, TENURED)->IsFailure());
- // Large object space.
- while (!heap->OldGenerationAllocationLimitReached()) {
- CHECK(!heap->AllocateFixedArray(10000, 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(10000, TENURED)->IsFailure());
+ CHECK(!heap->AllocateFixedArray(kOldPointerSpaceFillerLength, TENURED)->
+ IsFailure());
+
+ // Large object space.
+ 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(kLargeObjectSpaceFillerLength, TENURED)->
+ IsFailure());
// Map space.
MapSpace* map_space = heap->map_space();
@@ -175,16 +193,16 @@
// 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 @@
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 c1c8aae..cc20b6f 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -80,6 +80,11 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
// 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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
}
-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 @@
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 @@
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 @@
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 @@
HandleScope scope;
LocalContext env;
- NumberOfWeakCalls = 0;
+ WeakCallCounter counter(1234);
Persistent<Object> g1s1;
Persistent<Object> g1s2;
@@ -2017,18 +2229,18 @@
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 @@
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 @@
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 @@
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 @@
}
+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 @@
"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 @@
"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 @@
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 InvokeMarkSweep() {
- HEAP->CollectAllGarbage(false);
+ HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
}
@@ -4898,7 +5151,7 @@
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 @@
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 @@
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 @@
// 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 @@
}
+// 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 @@
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 @@
" 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 @@
}
{ 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 @@
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 @@
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 @@
{
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 @@
Local<String> name,
const AccessorInfo& info) {
ApiTestFuzzer::Fuzz();
- HEAP->CollectAllGarbage(false);
+ HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
return v8::Handle<Value>();
}
@@ -8340,10 +8691,10 @@
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 @@
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 @@
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 @@
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 @@
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 @@
" 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 @@
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 @@
" 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 @@
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 @@
" 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 @@
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 @@
" 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 @@
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 @@
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 @@
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 @@
" 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 @@
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 @@
" 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 @@
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 @@
"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 @@
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 @@
"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 @@
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 @@
"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 @@
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 @@
" 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 @@
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 @@
"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 @@
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 @@
"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 @@
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 @@
// 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 @@
// 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 @@
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 @@
}
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 @@
}
handle2.MakeWeak(NULL, DisposingCallback);
handle3.MakeWeak(NULL, HandleCreatingCallback);
- HEAP->CollectAllGarbage(false);
+ HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
}
@@ -10141,7 +10492,7 @@
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(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 @@
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 @@
{
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
" }"
"}"
"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 @@
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 @@
"}\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 @@
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 @@
} 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 @@
} 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 @@
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 @@
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 @@
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 @@
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(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 @@
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 @@
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 @@
"})()",
"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 @@
// 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 839b7f5..cdab8f7 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 @@
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 @@
__ 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 @@
__ 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 @@
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 2d9b012..7f63ebc 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 @@
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 @@
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 45da6dc..a9e2836 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -409,11 +409,8 @@
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 @@
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 @@
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 @@
HEAP->CollectGarbage(v8::internal::NEW_SPACE);
} else {
// Mark sweep compact.
- HEAP->CollectAllGarbage(true);
+ HEAP->CollectAllGarbage(Heap::kNoGCFlags);
}
}
}
@@ -1417,8 +1414,7 @@
// 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 @@
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 @@
// 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 @@
}
-// 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 @@
}
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 @@
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 @@
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 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
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 6198391..aa733c7 100644
--- a/test/cctest/test-decls.cc
+++ b/test/cctest/test-decls.cc
@@ -232,7 +232,7 @@
context.Check("const x; x",
1, // access
2, // declaration + initialization
- 2, // declaration + initialization
+ 1, // declaration
EXPECT_RESULT, Undefined());
}
@@ -240,7 +240,7 @@
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 @@
{ 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 @@
context.Check("const x; x",
1, // access
2, // declaration + initialization
- 2, // declaration + initializetion
+ 1, // declaration
EXPECT_RESULT, Undefined());
}
@@ -349,7 +349,7 @@
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 @@
{ 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 @@
{ 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 056c981..c713b02 100644
--- a/test/cctest/test-deoptimization.cc
+++ b/test/cctest/test-deoptimization.cc
@@ -237,7 +237,7 @@
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 15a854b..793e228 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 @@
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 @@
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 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 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 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 9f7d0bb..1e38e4e 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 @@
// 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 @@
__ 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 @@
__ 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 @@
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 @@
__ 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 @@
__ 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 @@
__ 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 @@
{
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 a626510..9c342a9 100644
--- a/test/cctest/test-hashing.cc
+++ b/test/cctest/test-hashing.cc
@@ -46,108 +46,66 @@
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);
+ StringHelper::GenerateHashGetHash(assm, v0);
__ 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);
- __ jr(ra);
- __ nop();
#endif
}
@@ -155,19 +113,19 @@
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(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 @@
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 @@
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 6c2afd4..81b68a7 100644
--- a/test/cctest/test-heap-profiler.cc
+++ b/test/cctest/test-heap-profiler.cc
@@ -252,6 +252,28 @@
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 @@
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(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 @@
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 11b8813..2ea359d 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 @@
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 @@
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 @@
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 @@
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 @@
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(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 @@
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 @@
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 @@
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 @@
}
// 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 @@
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 @@
}
// Mark compact handles the weak references.
- HEAP->CollectAllGarbage(true);
+ HEAP->CollectAllGarbage(Heap::kNoGCFlags);
CHECK_EQ(kNumTestContexts - i - 1, CountGlobalContexts());
}
@@ -1161,7 +1110,7 @@
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 @@
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(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(HeapIteratorFilterUnreachable) {
+
+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(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);
- {
- HeapIteratorTestHelper helper(*a, *b);
- helper.IterateHeap(HeapIterator::kFilterUnreachable);
- CHECK(helper.a_found());
- CHECK(helper.b_found());
+ 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++;
}
- 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...
+ 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_saved, *b);
- helper.IterateHeap(HeapIterator::kNoFiltering);
- 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();
}
- // ...but is now unreachable.
+ 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::kFilterUnreachable);
- 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();
+ }
+ 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());
+
+ {
+ 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 7360da5..5035f87 100644
--- a/test/cctest/test-lockers.cc
+++ b/test/cctest/test-lockers.cc
@@ -204,7 +204,11 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
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 72e663c..6f2324d 100644
--- a/test/cctest/test-log.cc
+++ b/test/cctest/test-log.cc
@@ -494,7 +494,7 @@
" (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 dcb51a0..cd3c490 100644
--- a/test/cctest/test-mark-compact.cc
+++ b/test/cctest/test-mark-compact.cc
@@ -44,21 +44,21 @@
}
-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 @@
// 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 @@
// 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(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 @@
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 @@
}
+// 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 @@
// 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 d98b675..6f394b6 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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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(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 @@
"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 @@
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 @@
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 @@
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 @@
}
-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 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 @@
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 76fd244..def829c 100644
--- a/test/cctest/test-profile-generator.cc
+++ b/test/cctest/test-profile-generator.cc
@@ -52,7 +52,7 @@
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 89a9112..b778478 100644
--- a/test/cctest/test-regexp.cc
+++ b/test/cctest/test-regexp.cc
@@ -530,7 +530,7 @@
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 @@
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 5bdc4c3..e638201 100644
--- a/test/cctest/test-reloc-info.cc
+++ b/test/cctest/test-reloc-info.cc
@@ -34,7 +34,7 @@
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 8e85444..e426e7b 100644
--- a/test/cctest/test-serialize.cc
+++ b/test/cctest/test-serialize.cc
@@ -114,10 +114,6 @@
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 @@
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 @@
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 @@
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 @@
}
// 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 @@
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 @@
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 @@
}
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 @@
}
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 @@
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 0f22ce1..27f64b4 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 @@
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 @@
DeleteArray(mem);
}
+#endif
namespace v8 {
@@ -122,62 +129,46 @@
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);
- CHECK(first_page->is_valid());
- CHECK(allocated == requested || allocated == requested - 1);
- total_pages += allocated;
+ Page* first_page =
+ memory_allocator->AllocatePage(&faked_space, NOT_EXECUTABLE);
- 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;
+ first_page->InsertAfter(faked_space.anchor()->prev_page());
+ CHECK(first_page->is_valid());
+ CHECK(first_page->next_page() == faked_space.anchor());
+ total_pages++;
+
+ 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 @@
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 @@
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 @@
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 @@
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 55c2141..93f7588 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 @@
}
+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 985b9e5..713d1e8 100644
--- a/test/cctest/test-threads.cc
+++ b/test/cctest/test-threads.cc
@@ -63,7 +63,7 @@
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 ThreadB: public v8::internal::Thread {
+class ThreadB : public v8::internal::Thread {
public:
ThreadB() : Thread("ThreadB") { }
void Run() {
@@ -111,7 +111,7 @@
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 @@
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 db4db25..56d5936 100644
--- a/test/cctest/test-weakmaps.cc
+++ b/test/cctest/test-weakmaps.cc
@@ -50,7 +50,7 @@
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 @@
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 @@
// 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 @@
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 @@
}
// 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 d095a24..bf3ee8b 100644
--- a/test/es5conform/es5conform.status
+++ b/test/es5conform/es5conform.status
@@ -41,16 +41,6 @@
# 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 @@
# 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 @@
# 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 c166110..413ee93 100644
--- a/test/mjsunit/apply.js
+++ b/test/mjsunit/apply.js
@@ -190,3 +190,10 @@
"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 0000000..321340c
--- /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 0000000..6708657
--- /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 c9adb5b..51cb99a 100644
--- a/test/mjsunit/assert-opt-and-deopt.js
+++ b/test/mjsunit/assert-opt-and-deopt.js
@@ -150,11 +150,6 @@
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 @@
// 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 ae84326..0513f87 100644
--- a/test/mjsunit/bugs/bug-618.js
+++ b/test/mjsunit/bugs/bug-618.js
@@ -42,4 +42,4 @@
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 a407c53..fda32eb 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 3f96087..460b0ab 100644
--- a/test/mjsunit/compiler/compare.js
+++ b/test/mjsunit/compiler/compare.js
@@ -83,9 +83,9 @@
}
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/cyclic-error-to-string.js b/test/mjsunit/compiler/inline-context-slots.js
similarity index 78%
copy from test/mjsunit/cyclic-error-to-string.js
copy to test/mjsunit/compiler/inline-context-slots.js
index 2502b53..d0e907b 100644
--- a/test/mjsunit/cyclic-error-to-string.js
+++ b/test/mjsunit/compiler/inline-context-slots.js
@@ -25,22 +25,25 @@
// (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.
+// Test inlining of functions with context slots.
-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 + '');
-e = new Error();
-e.name = [ e ];
-e.message = [ e ];
-e.stack = [ e ];
-e.arguments = [ e ];
-assertEquals(': ', e + '');
+// 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
similarity index 85%
copy from test/mjsunit/regress/regress-221.js
copy to test/mjsunit/compiler/lazy-const-lookup.js
index d3f2e35..b4f15a1 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/regress/regress-221.js b/test/mjsunit/compiler/regress-96989.js
similarity index 81%
copy from test/mjsunit/regress/regress-221.js
copy to test/mjsunit/compiler/regress-96989.js
index d3f2e35..aedeb24 100644
--- a/test/mjsunit/regress/regress-221.js
+++ b/test/mjsunit/compiler/regress-96989.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,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 that direct eval calls handle the case where eval has been
-// deleted correctly.
-// See http://code.google.com/p/v8/issues/detail?id=221
+// Flags: --allow-natives-syntax
-assertThrows('eval(delete eval)');
+// Test correct handling of uninitialized const.
+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/cyclic-error-to-string.js b/test/mjsunit/compiler/regress-deopt-call-as-function.js
similarity index 66%
copy from test/mjsunit/cyclic-error-to-string.js
copy to test/mjsunit/compiler/regress-deopt-call-as-function.js
index 2502b53..c408096 100644
--- a/test/mjsunit/cyclic-error-to-string.js
+++ b/test/mjsunit/compiler/regress-deopt-call-as-function.js
@@ -25,22 +25,38 @@
// (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.
+// Test deoptimization after inlined call.
-var e = new Error();
-assertEquals('Error', e + '');
+function bar(a, b) {try { return a; } finally { } }
-e = new Error();
-e.name = e;
-e.message = e;
-e.stack = e;
-e.arguments = e;
-assertEquals(': ', e + '');
+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());
-e = new Error();
-e.name = [ e ];
-e.message = [ e ];
-e.stack = [ e ];
-e.arguments = [ e ];
-assertEquals(': ', e + '');
+
+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/cyclic-error-to-string.js b/test/mjsunit/compiler/regress-inline-callfunctionstub.js
similarity index 80%
rename from test/mjsunit/cyclic-error-to-string.js
rename to test/mjsunit/compiler/regress-inline-callfunctionstub.js
index 2502b53..a39d26d 100644
--- a/test/mjsunit/cyclic-error-to-string.js
+++ b/test/mjsunit/compiler/regress-inline-callfunctionstub.js
@@ -25,22 +25,22 @@
// (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.
+// Flags: --allow-natives-syntax
-var e = new Error();
-assertEquals('Error', e + '');
+// Test inlined of calls-as-function two levels deep.
+function f() { return 42; }
-e = new Error();
-e.name = e;
-e.message = e;
-e.stack = e;
-e.arguments = e;
-assertEquals(': ', e + '');
+var o = {g : function () { return f(); } }
+function main(func) {
+ var v=0;
+ for (var i=0; i<1; i++) {
+ if (func()) v = 42;
+ }
+}
-e = new Error();
-e.name = [ e ];
-e.message = [ e ];
-e.stack = [ e ];
-e.arguments = [ e ];
-assertEquals(': ', e + '');
+main(o.g);
+main(o.g);
+main(o.g);
+%OptimizeFunctionOnNextCall(main);
+main(o.g);
+
diff --git a/test/mjsunit/cyclic-error-to-string.js b/test/mjsunit/compiler/strict-recompile.js
similarity index 77%
copy from test/mjsunit/cyclic-error-to-string.js
copy to test/mjsunit/compiler/strict-recompile.js
index 2502b53..96e8bca 100644
--- a/test/mjsunit/cyclic-error-to-string.js
+++ b/test/mjsunit/compiler/strict-recompile.js
@@ -25,22 +25,27 @@
// (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.
+// Flags: --allow-natives-syntax
-var e = new Error();
-assertEquals('Error', e + '');
+function foo() {
+ try {
+ var o = {};
+ Object.defineProperty(o, 'x', {value: 12, writable: false});
+ o.x = 13;
+ } catch(e) {
+ return true;
+ }
+ return false;
+}
-e = new Error();
-e.name = e;
-e.message = e;
-e.stack = e;
-e.arguments = e;
-assertEquals(': ', e + '');
+assertFalse(foo());
-e = new Error();
-e.name = [ e ];
-e.message = [ e ];
-e.stack = [ e ];
-e.arguments = [ e ];
-assertEquals(': ', e + '');
+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 9459708..c0b97e6 100644
--- a/test/mjsunit/const-redecl.js
+++ b/test/mjsunit/const-redecl.js
@@ -98,7 +98,8 @@
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 @@
// 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 a7f6cfa..fa43cbb 100644
--- a/test/mjsunit/date.js
+++ b/test/mjsunit/date.js
@@ -157,7 +157,7 @@
// 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)));
-// 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 @@
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 0000000..4418fa8
--- /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 8447df5..9ed1dbb 100644
--- a/test/mjsunit/debug-evaluate-locals-optimized-double.js
+++ b/test/mjsunit/debug-evaluate-locals-optimized-double.js
@@ -50,12 +50,10 @@
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 c3cd5eb..683c139 100644
--- a/test/mjsunit/debug-evaluate-locals-optimized.js
+++ b/test/mjsunit/debug-evaluate-locals-optimized.js
@@ -50,12 +50,10 @@
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 @@
listenerComplete = true;
}
} catch (e) {
- exception = e.stack;
+ exception = e
};
};
diff --git a/test/mjsunit/debug-scopes.js b/test/mjsunit/debug-scopes.js
index 1c23b0b..942bd2b 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 @@
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 @@
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 0000000..9cac0f5
--- /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 0000000..9c040da
--- /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 48a029f..0000000
--- 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/cyclic-error-to-string.js b/test/mjsunit/elements-kind-depends.js
similarity index 68%
copy from test/mjsunit/cyclic-error-to-string.js
copy to test/mjsunit/elements-kind-depends.js
index 2502b53..82f188b 100644
--- a/test/mjsunit/cyclic-error-to-string.js
+++ b/test/mjsunit/elements-kind-depends.js
@@ -25,22 +25,50 @@
// (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.
+// Flags: --allow-natives-syntax --smi-only-arrays
-var e = new Error();
-assertEquals('Error', e + '');
+function burn() {
+ var a = new Array(3);
+ a[0] = 10;
+ a[1] = 15.5;
+ a[2] = 20;
+ return a;
+}
-e = new Error();
-e.name = e;
-e.message = e;
-e.stack = e;
-e.arguments = e;
-assertEquals(': ', e + '');
+function check(a) {
+ assertEquals(10, a[0]);
+ assertEquals(15.5, a[1]);
+ assertEquals(20, a[2]);
+}
-e = new Error();
-e.name = [ e ];
-e.message = [ e ];
-e.stack = [ e ];
-e.arguments = [ e ];
-assertEquals(': ', e + '');
+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 0000000..8a8a3c7
--- /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 0000000..5f6cc4f
--- /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 0000000..a285641
--- /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 b6284ba..100f216 100644
--- a/test/mjsunit/eval.js
+++ b/test/mjsunit/eval.js
@@ -39,7 +39,7 @@
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 @@
result =
(function() {
var foo = 2;
+ // Should be non-direct call.
return x.eval('foo');
})();
assertEquals(0, result);
@@ -115,12 +116,33 @@
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 @@
})();
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 @@
})();
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 e9d0221..4a8f2d2 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,65 +80,98 @@
// 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(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(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).bind(foo, 1, 1).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).bind(foo, 1, 1);
-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, 1).bind(foo, 1).bind(foo).bind(foo);
-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).bind(foo, 1).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).bind(foo, 1);
-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).bind(foo, 1).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);
+// 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.
function bar(x, y, z) {
@@ -171,13 +206,91 @@
// 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 ff6677e..c4d18d0 100644
--- a/test/mjsunit/fuzz-natives.js
+++ b/test/mjsunit/fuzz-natives.js
@@ -163,6 +163,9 @@
"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 d38d0ee..2fca96f 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 @@
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 8d3de6f..ee2d979 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 @@
"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/cyclic-error-to-string.js b/test/mjsunit/harmony/block-early-errors.js
similarity index 72%
copy from test/mjsunit/cyclic-error-to-string.js
copy to test/mjsunit/harmony/block-early-errors.js
index 2502b53..791f001 100644
--- a/test/mjsunit/cyclic-error-to-string.js
+++ b/test/mjsunit/harmony/block-early-errors.js
@@ -25,22 +25,31 @@
// (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.
+// Flags: --harmony-scoping
-var e = new Error();
-assertEquals('Error', e + '');
+function CheckException(e) {
+ var string = e.toString();
+ assertInstanceof(e, SyntaxError);
+ assertTrue(string.indexOf("Illegal let") >= 0);
+}
-e = new Error();
-e.name = e;
-e.message = e;
-e.stack = e;
-e.arguments = e;
-assertEquals(': ', e + '');
+function Check(str) {
+ try {
+ eval("(function () { " + str + " })");
+ assertUnreachable();
+ } catch (e) {
+ CheckException(e);
+ }
+ try {
+ eval("(function () { { " + str + " } })");
+ assertUnreachable();
+ } catch (e) {
+ CheckException(e);
+ }
+}
-e = new Error();
-e.name = [ e ];
-e.message = [ e ];
-e.stack = [ e ];
-e.arguments = [ e ];
-assertEquals(': ', 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 0000000..e84f0d2
--- /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 73eaf29..a7f6b69 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 @@
} 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 @@
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 @@
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 @@
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 @@
throw 0;
}
} finally {
- assertEquals('outer', x);
+ assertEquals('outer', eval('x'));
}
- }
+ })('outer');
} catch (e) {
if (e instanceof MjsUnitAssertionError) throw e;
}
@@ -179,47 +181,47 @@
// 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 c2fb96b..ba5bc0d 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 49b6348..480e033 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 198c3b4..d14e7cd 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++');
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; 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 @@
// 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 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 266e380..31194d9 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 @@
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 @@
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 @@
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 @@
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 @@
// Return from block.
function f6() {
let x = 1;
+ const u = 3;
{
let y = 2;
+ const v = 4;
return x + y;
}
}
@@ -120,13 +142,26 @@
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 @@
} 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 @@
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 @@
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 0000000..4b435c1
--- /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 0230e84..10aac2d 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 @@
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 @@
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,114 +332,6 @@
EndTest();
-// Single empty with block.
-BeginTest("With block 1");
-
-function with_block_1() {
- with({}) {
- debugger;
- }
-}
-
-listener_delegate = function(exec_state) {
- CheckScopeChain([debug.ScopeType.With,
- debug.ScopeType.Local,
- debug.ScopeType.Global], exec_state);
- CheckScopeContent({}, 0, exec_state);
- CheckScopeContent({}, 1, exec_state);
-};
-with_block_1();
-EndTest();
-
-
-// Nested empty with blocks.
-BeginTest("With block 2");
-
-function with_block_2() {
- with({}) {
- with({}) {
- debugger;
- }
- }
-}
-
-listener_delegate = function(exec_state) {
- CheckScopeChain([debug.ScopeType.With,
- debug.ScopeType.With,
- debug.ScopeType.Local,
- debug.ScopeType.Global], exec_state);
- CheckScopeContent({}, 0, exec_state);
- CheckScopeContent({}, 1, exec_state);
- CheckScopeContent({}, 2, exec_state);
-};
-with_block_2();
-EndTest();
-
-
-// With block using an in-place object literal.
-BeginTest("With block 3");
-
-function with_block_3() {
- with({a:1,b:2}) {
- debugger;
- }
-}
-
-listener_delegate = function(exec_state) {
- CheckScopeChain([debug.ScopeType.With,
- debug.ScopeType.Local,
- debug.ScopeType.Global], exec_state);
- CheckScopeContent({a:1,b:2}, 0, exec_state);
-};
-with_block_3();
-EndTest();
-
-
-// Nested with blocks using in-place object literals.
-BeginTest("With block 4");
-
-function with_block_4() {
- with({a:1,b:2}) {
- with({a:2,b:1}) {
- debugger;
- }
- }
-}
-
-listener_delegate = function(exec_state) {
- CheckScopeChain([debug.ScopeType.With,
- debug.ScopeType.With,
- debug.ScopeType.Local,
- debug.ScopeType.Global], exec_state);
- CheckScopeContent({a:2,b:1}, 0, exec_state);
- CheckScopeContent({a:1,b:2}, 1, exec_state);
-};
-with_block_4();
-EndTest();
-
-
-// With block and a block local variable.
-BeginTest("With block 5");
-
-function with_block_5() {
- with({a:1}) {
- let a = 2;
- debugger;
- }
-}
-
-listener_delegate = function(exec_state) {
- CheckScopeChain([debug.ScopeType.Block,
- debug.ScopeType.With,
- debug.ScopeType.Local,
- debug.ScopeType.Global], exec_state);
- CheckScopeContent({a:2}, 0, exec_state);
- CheckScopeContent({a:1}, 1, exec_state);
-};
-with_block_5();
-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");
@@ -464,3 +359,112 @@
};
closure_1(1)();
EndTest();
+
+
+// Simple for-in loop over the keys of an object.
+BeginTest("For loop 1");
+
+function for_loop_1() {
+ for (let x in {y:undefined}) {
+ debugger;
+ }
+}
+
+listener_delegate = function(exec_state) {
+ CheckScopeChain([debug.ScopeType.Block,
+ debug.ScopeType.Local,
+ debug.ScopeType.Global], exec_state);
+ CheckScopeContent({x:'y'}, 0, exec_state);
+ // The function scope contains a temporary iteration variable.
+ CheckScopeContent({x:'y'}, 1, exec_state);
+};
+for_loop_1();
+EndTest();
+
+
+// For-in loop over the keys of an object with a block scoped let variable
+// shadowing the iteration variable.
+BeginTest("For loop 2");
+
+function for_loop_2() {
+ for (let x in {y:undefined}) {
+ let x = 3;
+ debugger;
+ }
+}
+
+listener_delegate = function(exec_state) {
+ CheckScopeChain([debug.ScopeType.Block,
+ debug.ScopeType.Block,
+ debug.ScopeType.Local,
+ debug.ScopeType.Global], 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);
+};
+for_loop_2();
+EndTest();
+
+
+// Simple for loop.
+BeginTest("For loop 3");
+
+function for_loop_3() {
+ for (let x = 3; x < 4; ++x) {
+ debugger;
+ }
+}
+
+listener_delegate = function(exec_state) {
+ CheckScopeChain([debug.ScopeType.Block,
+ debug.ScopeType.Local,
+ debug.ScopeType.Global], exec_state);
+ CheckScopeContent({x:3}, 0, exec_state);
+ CheckScopeContent({}, 1, exec_state);
+};
+for_loop_3();
+EndTest();
+
+
+// For loop with a block scoped let variable shadowing the iteration variable.
+BeginTest("For loop 4");
+
+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.Block,
+ debug.ScopeType.Local,
+ debug.ScopeType.Global], exec_state);
+ CheckScopeContent({x:5}, 0, exec_state);
+ CheckScopeContent({x:3}, 1, exec_state);
+ CheckScopeContent({}, 2, exec_state);
+};
+for_loop_4();
+EndTest();
+
+
+// For loop with two variable declarations.
+BeginTest("For loop 5");
+
+function for_loop_5() {
+ for (let x = 3, y = 5; x < 4; ++x) {
+ debugger;
+ }
+}
+
+listener_delegate = function(exec_state) {
+ CheckScopeChain([debug.ScopeType.Block,
+ debug.ScopeType.Local,
+ debug.ScopeType.Global], exec_state);
+ CheckScopeContent({x:3,y:5}, 0, exec_state);
+ CheckScopeContent({}, 1, exec_state);
+};
+for_loop_5();
+EndTest();
diff --git a/test/mjsunit/harmony/debug-evaluate-blockscopes.js b/test/mjsunit/harmony/debug-evaluate-blockscopes.js
index 549960a..d6ce8b2 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 @@
};
// 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 0000000..c6e7f9f
--- /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 0000000..3d419c6
--- /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 0000000..3f5ace6
--- /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 0000000..abfc0f5
--- /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 3c4e5f6..50c8613 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, handler) {
- test(handler, Proxy.create)
- test(handler, function(h) {return Proxy.createFunction(h, function() {})})
+function TestWithProxies(test, x, y, z) {
+ test(Proxy.create, x, y, z)
+ test(function(h) {return Proxy.createFunction(h, function() {})}, x, y, z)
}
-// Getters.
+
+// 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 (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 @@
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 @@
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 @@
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 @@
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 @@
}))
-
-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 @@
}))
+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 @@
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 @@
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 @@
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 @@
TestWithProxies(TestDefineThrow2, handler)
}
-function TestDefineThrow2(handler, create) {
+function TestDefineThrow2(create, handler) {
var p = create(handler)
assertThrows(function(){ Object.defineProperty(p, "a", {value: 44})}, "myexn")
+ assertThrows(function(){ Object.defineProperty(p, 0, {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")
+ 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 @@
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 @@
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 @@
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 @@
TestWithProxies(TestDescriptor2, handler)
}
-function TestDescriptor2(handler, create) {
+function TestDescriptor2(create, handler) {
var p = create(handler)
var descs = [
{configurable: true},
@@ -697,7 +975,7 @@
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 @@
TestWithProxies(TestComparison2, eq)
}
-function TestComparison2(eq, create) {
+function TestComparison2(create, eq) {
var p1 = create({})
var p2 = create({})
@@ -764,7 +1042,7 @@
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 @@
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({
- get: undefined,
+ has: undefined,
getPropertyDescriptor: function(k) {
key = k; return k < "z" ? {value: 42} : void 0
}
@@ -847,9 +1126,10 @@
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({
- get: undefined,
+ has: undefined,
getPropertyDescriptor: function(k) { throw "myexn" }
})
@@ -891,6 +1171,158 @@
}))
+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 @@
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 @@
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 @@
// 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
+ var f3 = function() {}
+ f3.prototype = o2
- assertTrue(o instanceof Object)
- assertFalse(o instanceof f0)
- assertFalse(o instanceof f1)
- assertFalse(o instanceof f2)
+ 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 @@
// 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 @@
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 @@
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(["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(["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 @@
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 @@
// 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 @@
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 @@
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 @@
})
+// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 7b5dcaf..0000000
--- 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 faa5a43..6f6e323 100644
--- a/test/mjsunit/mjsunit.js
+++ b/test/mjsunit/mjsunit.js
@@ -223,7 +223,7 @@
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 bae09b4..cdac99b 100644
--- a/test/mjsunit/mjsunit.status
+++ b/test/mjsunit/mjsunit.status
@@ -34,9 +34,13 @@
# 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 @@
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 128df69..6d5032e 100644
--- a/test/mjsunit/object-define-properties.js
+++ b/test/mjsunit/object-define-properties.js
@@ -54,3 +54,19 @@
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/cyclic-error-to-string.js b/test/mjsunit/optimized-typeof.js
similarity index 79%
copy from test/mjsunit/cyclic-error-to-string.js
copy to test/mjsunit/optimized-typeof.js
index 2502b53..b0c0725 100644
--- a/test/mjsunit/cyclic-error-to-string.js
+++ b/test/mjsunit/optimized-typeof.js
@@ -25,22 +25,23 @@
// (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.
+// Flags: --allow-natives-syntax
-var e = new Error();
-assertEquals('Error', e + '');
+function typeofDirectly() {
+ return typeof({}) === "undefined";
+}
-e = new Error();
-e.name = e;
-e.message = e;
-e.stack = e;
-e.arguments = e;
-assertEquals(': ', e + '');
+typeofDirectly();
+typeofDirectly();
+%OptimizeFunctionOnNextCall(typeofDirectly);
+typeofDirectly();
-e = new Error();
-e.name = [ e ];
-e.message = [ e ];
-e.stack = [ e ];
-e.arguments = [ e ];
-assertEquals(': ', e + '');
+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 0f84968..8f283f6 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 @@
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/cyclic-error-to-string.js b/test/mjsunit/regress/regress-100702.js
similarity index 79%
copy from test/mjsunit/cyclic-error-to-string.js
copy to test/mjsunit/regress/regress-100702.js
index 2502b53..46494ab 100644
--- a/test/mjsunit/cyclic-error-to-string.js
+++ b/test/mjsunit/regress/regress-100702.js
@@ -25,22 +25,20 @@
// (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.
+// Regression test for correct handling of non-object receiver values
+// passed to built-in array functions.
-var e = new Error();
-assertEquals('Error', e + '');
+String.prototype.isThatMe = function () {
+ assertFalse(this === str);
+};
-e = new Error();
-e.name = e;
-e.message = e;
-e.stack = e;
-e.arguments = e;
-assertEquals(': ', e + '');
+var str = "abc";
+str.isThatMe();
+str.isThatMe.call(str);
-e = new Error();
-e.name = [ e ];
-e.message = [ e ];
-e.stack = [ e ];
-e.arguments = [ e ];
-assertEquals(': ', e + '');
+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/cyclic-error-to-string.js b/test/mjsunit/regress/regress-109195.js
similarity index 66%
copy from test/mjsunit/cyclic-error-to-string.js
copy to test/mjsunit/regress/regress-109195.js
index 2502b53..97538aa 100644
--- a/test/mjsunit/cyclic-error-to-string.js
+++ b/test/mjsunit/regress/regress-109195.js
@@ -1,4 +1,4 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
+// 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:
@@ -25,22 +25,41 @@
// (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.
+// Flags: --expose-debug-as debug
+var Debug = debug.Debug;
-var e = new Error();
-assertEquals('Error', e + '');
+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);
+}
-e = new Error();
-e.name = e;
-e.message = e;
-e.stack = e;
-e.arguments = e;
-assertEquals(': ', e + '');
+Debug.setListener(listener);
-e = new Error();
-e.name = [ e ];
-e.message = [ e ];
-e.stack = [ e ];
-e.arguments = [ e ];
-assertEquals(': ', e + '');
+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 43b8d77..124f520 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 95684c5..66ed9f2 100644
--- a/test/mjsunit/regress/regress-1170.js
+++ b/test/mjsunit/regress/regress-1170.js
@@ -49,7 +49,7 @@
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 9d82064..f3a11db 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/cyclic-error-to-string.js b/test/mjsunit/regress/regress-1217.js
similarity index 68%
copy from test/mjsunit/cyclic-error-to-string.js
copy to test/mjsunit/regress/regress-1217.js
index 2502b53..6530549 100644
--- a/test/mjsunit/cyclic-error-to-string.js
+++ b/test/mjsunit/regress/regress-1217.js
@@ -25,22 +25,26 @@
// (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.
+// Check that RegExp.prototype is itself a RegExp object.
-var e = new Error();
-assertEquals('Error', e + '');
+var proto = RegExp.prototype;
+assertEquals("[object RegExp]", Object.prototype.toString.call(proto));
-e = new Error();
-e.name = e;
-e.message = e;
-e.stack = e;
-e.arguments = e;
-assertEquals(': ', e + '');
+assertEquals("", proto.source);
+assertEquals(false, proto.global);
+assertEquals(false, proto.multiline);
+assertEquals(false, proto.ignoreCase);
+assertEquals(0, proto.lastIndex);
-e = new Error();
-e.name = [ e ];
-e.message = [ e ];
-e.stack = [ e ];
-e.arguments = [ e ];
-assertEquals(': ', e + '');
+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 e16d278..c0dcba9 100644
--- a/test/mjsunit/regress/regress-1229.js
+++ b/test/mjsunit/regress/regress-1229.js
@@ -35,10 +35,10 @@
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/cyclic-error-to-string.js b/test/mjsunit/regress/regress-1415.js
similarity index 73%
copy from test/mjsunit/cyclic-error-to-string.js
copy to test/mjsunit/regress/regress-1415.js
index 2502b53..f993e9b 100644
--- a/test/mjsunit/cyclic-error-to-string.js
+++ b/test/mjsunit/regress/regress-1415.js
@@ -25,22 +25,18 @@
// (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.
+// 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);
-var e = new Error();
-assertEquals('Error', e + '');
-
-e = new Error();
-e.name = e;
-e.message = e;
-e.stack = e;
-e.arguments = e;
-assertEquals(': ', e + '');
-
-e = new Error();
-e.name = [ e ];
-e.message = [ e ];
-e.stack = [ e ];
-e.arguments = [ e ];
-assertEquals(': ', e + '');
+// 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 0000000..c439dd8
--- /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 0000000..06bd66c
--- /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 0000000..ab50e07
--- /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/cyclic-error-to-string.js b/test/mjsunit/regress/regress-1711.js
similarity index 80%
copy from test/mjsunit/cyclic-error-to-string.js
copy to test/mjsunit/regress/regress-1711.js
index 2502b53..15591b1 100644
--- a/test/mjsunit/cyclic-error-to-string.js
+++ b/test/mjsunit/regress/regress-1711.js
@@ -25,22 +25,14 @@
// (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.
+// string.split needs to evaluate the separator's toString even if limit
+// is 0 because toString may have side effects.
-var e = new Error();
-assertEquals('Error', e + '');
-
-e = new Error();
-e.name = e;
-e.message = e;
-e.stack = e;
-e.arguments = e;
-assertEquals(': ', e + '');
-
-e = new Error();
-e.name = [ e ];
-e.message = [ e ];
-e.stack = [ e ];
-e.arguments = [ e ];
-assertEquals(': ', e + '');
+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 0000000..0af1144
--- /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/cyclic-error-to-string.js b/test/mjsunit/regress/regress-1748.js
similarity index 80%
copy from test/mjsunit/cyclic-error-to-string.js
copy to test/mjsunit/regress/regress-1748.js
index 2502b53..e287e55 100644
--- a/test/mjsunit/cyclic-error-to-string.js
+++ b/test/mjsunit/regress/regress-1748.js
@@ -25,22 +25,11 @@
// (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.
+// 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 e = new Error();
-assertEquals('Error', e + '');
-
-e = new Error();
-e.name = e;
-e.message = e;
-e.stack = e;
-e.arguments = e;
-assertEquals(': ', e + '');
-
-e = new Error();
-e.name = [ e ];
-e.message = [ e ];
-e.stack = [ e ];
-e.arguments = [ e ];
-assertEquals(': ', e + '');
+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-221.js b/test/mjsunit/regress/regress-1757.js
similarity index 85%
rename from test/mjsunit/regress/regress-221.js
rename to test/mjsunit/regress/regress-1757.js
index d3f2e35..f7a5516 100644
--- a/test/mjsunit/regress/regress-221.js
+++ b/test/mjsunit/regress/regress-1757.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,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 direct eval calls handle the case where eval has been
-// deleted correctly.
+// Flags: --string-slices --expose-externalize-string
-// See http://code.google.com/p/v8/issues/detail?id=221
-
-assertThrows('eval(delete eval)');
-
+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-221.js b/test/mjsunit/regress/regress-1945.js
similarity index 85%
copy from test/mjsunit/regress/regress-221.js
copy to test/mjsunit/regress/regress-1945.js
index d3f2e35..bffc775 100644
--- a/test/mjsunit/regress/regress-221.js
+++ b/test/mjsunit/regress/regress-1945.js
@@ -1,4 +1,4 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
+// 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:
@@ -25,10 +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.
-// 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
-
-assertThrows('eval(delete eval)');
-
+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 d35aba6..bec5a4d 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 68a768c..0000000
--- 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 0000000..41ca992
--- /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/cyclic-error-to-string.js b/test/mjsunit/regress/regress-98773.js
similarity index 80%
copy from test/mjsunit/cyclic-error-to-string.js
copy to test/mjsunit/regress/regress-98773.js
index 2502b53..eb24eb5 100644
--- a/test/mjsunit/cyclic-error-to-string.js
+++ b/test/mjsunit/regress/regress-98773.js
@@ -25,22 +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.
-// Test printing of cyclic errors which return the empty string for
-// compatibility with Safari and Firefox.
+// Calling Array.sort on an external array is not supposed to crash.
-var e = new Error();
-assertEquals('Error', e + '');
+var array = new Int16Array(23);
+array[7] = 7; array[9] = 9;
+assertEquals(23, array.length);
+assertEquals(7, array[7]);
+assertEquals(9, array[9]);
-e = new Error();
-e.name = e;
-e.message = e;
-e.stack = e;
-e.arguments = e;
-assertEquals(': ', e + '');
-
-e = new Error();
-e.name = [ e ];
-e.message = [ e ];
-e.stack = [ e ];
-e.arguments = [ e ];
-assertEquals(': ', e + '');
+Array.prototype.sort.call(array);
+assertEquals(23, array.length);
+assertEquals(7, array[21]);
+assertEquals(9, array[22]);
diff --git a/test/mjsunit/regress/regress-221.js b/test/mjsunit/regress/regress-99167.js
similarity index 85%
copy from test/mjsunit/regress/regress-221.js
copy to test/mjsunit/regress/regress-99167.js
index d3f2e35..5053ae5 100644
--- a/test/mjsunit/regress/regress-221.js
+++ b/test/mjsunit/regress/regress-99167.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,9 @@
// (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: --expose-gc --max-new-space-size=1024
-// See http://code.google.com/p/v8/issues/detail?id=221
-
-assertThrows('eval(delete eval)');
-
+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/cyclic-error-to-string.js b/test/mjsunit/regress/regress-crbug-107996.js
similarity index 64%
copy from test/mjsunit/cyclic-error-to-string.js
copy to test/mjsunit/regress/regress-crbug-107996.js
index 2502b53..dfe07e5 100644
--- a/test/mjsunit/cyclic-error-to-string.js
+++ b/test/mjsunit/regress/regress-crbug-107996.js
@@ -1,4 +1,4 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
+// 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:
@@ -25,22 +25,40 @@
// (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.
+// Flags: --expose-debug-as debug
-var e = new Error();
-assertEquals('Error', e + '');
+Debug = debug.Debug;
-e = new Error();
-e.name = e;
-e.message = e;
-e.stack = e;
-e.arguments = e;
-assertEquals(': ', e + '');
+Debug.setListener(listener);
-e = new Error();
-e.name = [ e ];
-e.message = [ e ];
-e.stack = [ e ];
-e.arguments = [ e ];
-assertEquals(': ', e + '');
+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 7b7c29a..a74e2c5 100644
--- a/test/mjsunit/regress/regress-deopt-gc.js
+++ b/test/mjsunit/regress/regress-deopt-gc.js
@@ -42,7 +42,7 @@
// 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/regress-221.js b/test/mjsunit/regress/short-circuit.js
similarity index 85%
copy from test/mjsunit/regress/regress-221.js
copy to test/mjsunit/regress/short-circuit.js
index d3f2e35..25363d6 100644
--- a/test/mjsunit/regress/regress-221.js
+++ b/test/mjsunit/regress/short-circuit.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,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 direct eval calls handle the case where eval has been
-// deleted correctly.
+var arr = [];
-// See http://code.google.com/p/v8/issues/detail?id=221
-
-assertThrows('eval(delete eval)');
-
+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 0000000..165c4df
--- /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 47a5cc5..536e71b 100644
--- a/test/mjsunit/stack-traces.js
+++ b/test/mjsunit/stack-traces.js
@@ -194,6 +194,46 @@
}
+// 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 @@
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 338f6d1..8284edd 100644
--- a/test/mjsunit/strict-mode-implicit-receiver.js
+++ b/test/mjsunit/strict-mode-implicit-receiver.js
@@ -168,12 +168,7 @@
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 30234ba..9c9bdfd 100644
--- a/test/mjsunit/strict-mode.js
+++ b/test/mjsunit/strict-mode.js
@@ -1051,14 +1051,20 @@
}
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 0000000..12312ac
--- /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 da89786..d52a7e2 100644
--- a/test/mjsunit/string-externalize.js
+++ b/test/mjsunit/string-externalize.js
@@ -44,7 +44,7 @@
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 a8cadae..98b8ef9 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 8cc1f81..3eb30f1 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 @@
// 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 @@
// 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("\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 180f994..6a61fe5 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(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 = 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 d17e600..50e4bc7 100644
--- a/test/mjsunit/to_number_order.js
+++ b/test/mjsunit/to_number_order.js
@@ -161,7 +161,7 @@
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 @@
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 feecaec..fd7db28 100644
--- a/test/mjsunit/unbox-double-arrays.js
+++ b/test/mjsunit/unbox-double-arrays.js
@@ -77,8 +77,6 @@
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 @@
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 @@
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,20 +107,20 @@
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));
- assertEquals(value_5, a[5]);
- assertEquals(value_6, a[6]);
- assertEquals(value_6, a[computed_6()]); // Test non-constant key
+ 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(undefined, a[large_array_size-1]);
- assertEquals(undefined, a[-1]);
assertEquals(large_array_size, a.length);
assertTrue(%HasFastDoubleElements(a));
}
@@ -137,8 +131,16 @@
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_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(large_array_size, a.length);
assertTrue(%HasFastDoubleElements(a));
}
@@ -248,6 +250,8 @@
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 @@
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 @@
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 @@
-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 @@
-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[4] = -Infinity;
function call_apply() {
- assertTrue(%HasFastDoubleElements(large_array3));
called_by_apply.apply({}, large_array3);
}
@@ -449,7 +469,6 @@
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 04fd060..635ea6f 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 @@
"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 @@
"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 @@
"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 @@
"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 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 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 @@
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 3a27130..e31a630 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 @@
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-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/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-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 @@
# 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 72808e2..aa3d521 100644
--- a/test/preparser/strict-identifiers.pyt
+++ b/test/preparser/strict-identifiers.pyt
@@ -138,6 +138,38 @@
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 @@
function $id($id) { }
x = {$id: 42};
x = {get $id() {}, set $id(value) {}};
+ $id: '';
""")
identifier_name_source = """
@@ -197,6 +230,12 @@
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 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 @@
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 868509d..fb6d951 100644
--- a/test/sputnik/sputnik.status
+++ b/test/sputnik/sputnik.status
@@ -30,10 +30,6 @@
############################### 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.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 @@
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.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 @@
# 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 ea6b4a7..094356f 100644
--- a/test/test262/README
+++ b/test/test262/README
@@ -4,11 +4,11 @@
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 8cee210..2ad5746 100644
--- a/test/test262/test262.status
+++ b/test/test262/test262.status
@@ -25,491 +25,368 @@
# (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
+15.2.3.6-4-360-1: FAIL
+15.2.3.6-4-360-6: FAIL
+15.2.3.6-4-360-7: FAIL
+15.2.3.6-4-405: FAIL
+15.2.3.6-4-410: FAIL
+15.2.3.6-4-415: FAIL
+15.2.3.6-4-420: FAIL
+15.2.3.7-6-a-112: FAIL
+15.2.3.7-6-a-113: FAIL
+15.2.3.7-6-a-122: FAIL
+15.2.3.7-6-a-123: FAIL
+15.2.3.7-6-a-124: FAIL
+15.2.3.7-6-a-125: FAIL
+15.2.3.7-6-a-126: FAIL
+15.2.3.7-6-a-127: FAIL
+15.2.3.7-6-a-128: FAIL
+15.2.3.7-6-a-133: FAIL
+15.2.3.7-6-a-138: FAIL
+15.2.3.7-6-a-139: FAIL
+15.2.3.7-6-a-140: FAIL
+15.2.3.7-6-a-142: FAIL
+15.2.3.7-6-a-143: FAIL
+15.2.3.7-6-a-144: FAIL
+15.2.3.7-6-a-145: FAIL
+15.2.3.7-6-a-147: FAIL
+15.2.3.7-6-a-150: FAIL
+15.2.3.7-6-a-151: FAIL
+15.2.3.7-6-a-155: FAIL
+15.2.3.7-6-a-157: FAIL
+15.2.3.7-6-a-161: FAIL
+15.2.3.7-6-a-162: FAIL
+15.2.3.7-6-a-163: FAIL
+15.2.3.7-6-a-164: FAIL
+15.2.3.7-6-a-165: FAIL
+15.2.3.7-6-a-166: FAIL
+15.2.3.7-6-a-167: FAIL
+15.2.3.7-6-a-168: FAIL
+15.2.3.7-6-a-169: FAIL
+15.2.3.7-6-a-170: FAIL
+15.2.3.7-6-a-171: FAIL
+15.2.3.7-6-a-172: FAIL
+15.2.3.7-6-a-173: FAIL
+15.2.3.7-6-a-174: FAIL
+15.2.3.7-6-a-175: FAIL
+15.2.3.7-6-a-176: FAIL
+15.2.3.7-6-a-177: FAIL
+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
+15.2.3.7-6-a-184: FAIL
+15.2.3.7-6-a-185: FAIL
+15.2.3.7-6-a-264: FAIL
+15.2.3.7-6-a-265: FAIL
+15.4.4.14-9-b-i-11: FAIL
+15.4.4.14-9-b-i-13: FAIL
+15.4.4.14-9-b-i-17: FAIL
+15.4.4.14-9-b-i-19: FAIL
+15.4.4.14-9-b-i-28: FAIL
+15.4.4.14-9-b-i-30: FAIL
+15.4.4.15-8-a-14: FAIL
+15.4.4.15-8-b-i-11: FAIL
+15.4.4.15-8-b-i-13: FAIL
+15.4.4.15-8-b-i-17: FAIL
+15.4.4.15-8-b-i-28: FAIL
+15.4.4.15-8-b-i-30: FAIL
+15.4.4.16-7-c-i-10: FAIL
+15.4.4.16-7-c-i-12: FAIL
+15.4.4.16-7-c-i-14: FAIL
+15.4.4.16-7-c-i-18: FAIL
+15.4.4.16-7-c-i-20: FAIL
+15.4.4.16-7-c-i-28: FAIL
+15.4.4.17-7-c-i-10: FAIL
+15.4.4.17-7-c-i-12: FAIL
+15.4.4.17-7-c-i-14: FAIL
+15.4.4.17-7-c-i-18: FAIL
+15.4.4.17-7-c-i-20: FAIL
+15.4.4.17-7-c-i-28: FAIL
+15.4.4.18-7-c-i-10: FAIL
+15.4.4.18-7-c-i-12: FAIL
+15.4.4.18-7-c-i-14: FAIL
+15.4.4.18-7-c-i-18: FAIL
+15.4.4.18-7-c-i-20: FAIL
+15.4.4.18-7-c-i-28: FAIL
+15.4.4.19-8-c-i-10: FAIL
+15.4.4.19-8-c-i-14: FAIL
+15.4.4.19-8-c-i-12: FAIL
+15.4.4.19-8-c-i-18: FAIL
+15.4.4.19-8-c-i-19: FAIL
+15.4.4.19-8-c-i-28: FAIL
+15.4.4.20-9-c-i-10: FAIL
+15.4.4.20-9-c-i-12: FAIL
+15.4.4.20-9-c-i-14: FAIL
+15.4.4.20-9-c-i-18: FAIL
+15.4.4.20-9-c-i-20: FAIL
+15.4.4.20-9-c-i-28: FAIL
+15.4.4.22-8-b-2: FAIL
+15.4.4.22-8-b-iii-1-12: FAIL
+15.4.4.22-8-b-iii-1-18: FAIL
+15.4.4.22-8-b-iii-1-20: FAIL
+15.4.4.22-8-b-iii-1-33: FAIL
+15.4.4.22-8-b-iii-1-30: FAIL
+15.4.4.22-9-b-13: FAIL
+15.4.4.22-9-b-24: FAIL
+15.4.4.22-9-b-26: FAIL
+15.4.4.22-9-b-9: FAIL
+15.4.4.22-9-c-i-30: FAIL
+
+# 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
+
+# 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)
@@ -522,9 +399,6 @@
# [[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)
@@ -541,814 +415,28 @@
# 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-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-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-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-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-c-i-30: FAIL
-# Bug? Array.prototype.reduceRight - modifications to length will change number
-# of iterations
-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
+
+############################ 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 9482046..52127cd 100644
--- a/test/test262/testcfg.py
+++ b/test/test262/testcfg.py
@@ -43,10 +43,10 @@
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 @@
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 @@
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 @@
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):