Upgrade to V8 3.5
Merge V8 3.5.10.24
Simple merge required updates to makefiles only.
Bug: 5688872
Change-Id: I0acdb9a1a53919d84e9a7525308e8371739d2f06
diff --git a/test/benchmarks/testcfg.py b/test/benchmarks/testcfg.py
index 51d8520..ab9d40f 100644
--- a/test/benchmarks/testcfg.py
+++ b/test/benchmarks/testcfg.py
@@ -91,7 +91,7 @@
return [test]
def GetBuildRequirements(self):
- return ['sample', 'sample=shell']
+ return ['d8']
def GetTestStatus(self, sections, defs):
pass
diff --git a/test/cctest/SConscript b/test/cctest/SConscript
index b0a7166..621d8ec 100644
--- a/test/cctest/SConscript
+++ b/test/cctest/SConscript
@@ -65,6 +65,7 @@
'test-debug.cc',
'test-decls.cc',
'test-deoptimization.cc',
+ 'test-dictionary.cc',
'test-diy-fp.cc',
'test-double.cc',
'test-dtoa.cc',
@@ -95,7 +96,8 @@
'test-threads.cc',
'test-unbound-queue.cc',
'test-utils.cc',
- 'test-version.cc'
+ 'test-version.cc',
+ 'test-weakmaps.cc'
],
'arch:arm': [
'test-assembler-arm.cc',
diff --git a/test/cctest/cctest.gyp b/test/cctest/cctest.gyp
index 9cbcb9c..c0b5316 100644
--- a/test/cctest/cctest.gyp
+++ b/test/cctest/cctest.gyp
@@ -26,10 +26,10 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
+ 'includes': ['../../build/common.gypi'],
'variables': {
'generated_file': '<(SHARED_INTERMEDIATE_DIR)/resources.cc',
},
- 'includes': [ '../../build/v8-features.gypi' ],
'targets': [
{
'target_name': 'cctest',
@@ -61,6 +61,7 @@
'test-debug.cc',
'test-decls.cc',
'test-deoptimization.cc',
+ 'test-dictionary.cc',
'test-diy-fp.cc',
'test-double.cc',
'test-dtoa.cc',
@@ -78,6 +79,7 @@
'test-log.cc',
'test-mark-compact.cc',
'test-parsing.cc',
+ 'test-platform-tls.cc',
'test-profile-generator.cc',
'test-regexp.cc',
'test-reloc-info.cc',
diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status
index 6e7824f..78f3756 100644
--- a/test/cctest/cctest.status
+++ b/test/cctest/cctest.status
@@ -38,6 +38,9 @@
test-serialize/TestThatAlwaysFails: FAIL
test-serialize/DependentTestThatAlwaysFails: FAIL
+# We do not yet shrink weak maps after they have been emptied by the GC
+test-weakmaps/Shrinking: FAIL
+
##############################################################################
[ $arch == arm ]
diff --git a/test/cctest/test-accessors.cc b/test/cctest/test-accessors.cc
index 028f82f..d95536d 100644
--- a/test/cctest/test-accessors.cc
+++ b/test/cctest/test-accessors.cc
@@ -44,8 +44,6 @@
using ::v8::AccessorInfo;
using ::v8::Extension;
-namespace i = ::v8::internal;
-
static v8::Handle<Value> handle_property(Local<String> name,
const AccessorInfo&) {
ApiTestFuzzer::Fuzz();
diff --git a/test/cctest/test-alloc.cc b/test/cctest/test-alloc.cc
index 4d9c218..9767192 100644
--- a/test/cctest/test-alloc.cc
+++ b/test/cctest/test-alloc.cc
@@ -186,7 +186,9 @@
TEST(CodeRange) {
const int code_range_size = 16*MB;
OS::Setup();
- Isolate::Current()->code_range()->Setup(code_range_size);
+ Isolate::Current()->InitializeLoggingAndCounters();
+ CodeRange* code_range = new CodeRange(Isolate::Current());
+ code_range->Setup(code_range_size);
int current_allocated = 0;
int total_allocated = 0;
List<Block> blocks(1000);
@@ -198,8 +200,7 @@
size_t requested = (Page::kPageSize << (Pseudorandom() % 6)) +
Pseudorandom() % 5000 + 1;
size_t allocated = 0;
- void* base = Isolate::Current()->code_range()->
- AllocateRawMemory(requested, &allocated);
+ void* base = code_range->AllocateRawMemory(requested, &allocated);
CHECK(base != NULL);
blocks.Add(Block(base, static_cast<int>(allocated)));
current_allocated += static_cast<int>(allocated);
@@ -207,8 +208,7 @@
} else {
// Free a block.
int index = Pseudorandom() % blocks.length();
- Isolate::Current()->code_range()->FreeRawMemory(
- blocks[index].base, blocks[index].size);
+ code_range->FreeRawMemory(blocks[index].base, blocks[index].size);
current_allocated -= blocks[index].size;
if (index < blocks.length() - 1) {
blocks[index] = blocks.RemoveLast();
@@ -218,5 +218,6 @@
}
}
- Isolate::Current()->code_range()->TearDown();
+ code_range->TearDown();
+ delete code_range;
}
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 5d197be..3d40a73 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -72,8 +72,6 @@
using ::v8::V8;
using ::v8::Value;
-namespace i = ::i;
-
static void ExpectString(const char* code, const char* expected) {
Local<Value> result = CompileRun(code);
@@ -331,16 +329,14 @@
class TestResource: public String::ExternalStringResource {
public:
- static int dispose_count;
-
- explicit TestResource(uint16_t* data)
- : data_(data), length_(0) {
+ explicit TestResource(uint16_t* data, int* counter = NULL)
+ : data_(data), length_(0), counter_(counter) {
while (data[length_]) ++length_;
}
~TestResource() {
i::DeleteArray(data_);
- ++dispose_count;
+ if (counter_ != NULL) ++*counter_;
}
const uint16_t* data() const {
@@ -353,23 +349,18 @@
private:
uint16_t* data_;
size_t length_;
+ int* counter_;
};
-int TestResource::dispose_count = 0;
-
-
class TestAsciiResource: public String::ExternalAsciiStringResource {
public:
- static int dispose_count;
-
- explicit TestAsciiResource(const char* data)
- : data_(data),
- length_(strlen(data)) { }
+ explicit TestAsciiResource(const char* data, int* counter = NULL)
+ : data_(data), length_(strlen(data)), counter_(counter) { }
~TestAsciiResource() {
i::DeleteArray(data_);
- ++dispose_count;
+ if (counter_ != NULL) ++*counter_;
}
const char* data() const {
@@ -382,20 +373,18 @@
private:
const char* data_;
size_t length_;
+ int* counter_;
};
-int TestAsciiResource::dispose_count = 0;
-
-
THREADED_TEST(ScriptUsingStringResource) {
- TestResource::dispose_count = 0;
+ int dispose_count = 0;
const char* c_source = "1 + 2 * 3";
uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
{
v8::HandleScope scope;
LocalContext env;
- TestResource* resource = new TestResource(two_byte_source);
+ TestResource* resource = new TestResource(two_byte_source, &dispose_count);
Local<String> source = String::NewExternal(resource);
Local<Script> script = Script::Compile(source);
Local<Value> value = script->Run();
@@ -405,37 +394,38 @@
CHECK_EQ(resource,
static_cast<TestResource*>(source->GetExternalStringResource()));
HEAP->CollectAllGarbage(false);
- CHECK_EQ(0, TestResource::dispose_count);
+ CHECK_EQ(0, dispose_count);
}
v8::internal::Isolate::Current()->compilation_cache()->Clear();
HEAP->CollectAllGarbage(false);
- CHECK_EQ(1, TestResource::dispose_count);
+ CHECK_EQ(1, dispose_count);
}
THREADED_TEST(ScriptUsingAsciiStringResource) {
- TestAsciiResource::dispose_count = 0;
+ int dispose_count = 0;
const char* c_source = "1 + 2 * 3";
{
v8::HandleScope scope;
LocalContext env;
Local<String> source =
- String::NewExternal(new TestAsciiResource(i::StrDup(c_source)));
+ String::NewExternal(new TestAsciiResource(i::StrDup(c_source),
+ &dispose_count));
Local<Script> script = Script::Compile(source);
Local<Value> value = script->Run();
CHECK(value->IsNumber());
CHECK_EQ(7, value->Int32Value());
HEAP->CollectAllGarbage(false);
- CHECK_EQ(0, TestAsciiResource::dispose_count);
+ CHECK_EQ(0, dispose_count);
}
i::Isolate::Current()->compilation_cache()->Clear();
HEAP->CollectAllGarbage(false);
- CHECK_EQ(1, TestAsciiResource::dispose_count);
+ CHECK_EQ(1, dispose_count);
}
THREADED_TEST(ScriptMakingExternalString) {
- TestResource::dispose_count = 0;
+ int dispose_count = 0;
uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
{
v8::HandleScope scope;
@@ -444,23 +434,24 @@
// Trigger GCs so that the newly allocated string moves to old gen.
HEAP->CollectGarbage(i::NEW_SPACE); // in survivor space now
HEAP->CollectGarbage(i::NEW_SPACE); // in old gen now
- bool success = source->MakeExternal(new TestResource(two_byte_source));
+ bool success = source->MakeExternal(new TestResource(two_byte_source,
+ &dispose_count));
CHECK(success);
Local<Script> script = Script::Compile(source);
Local<Value> value = script->Run();
CHECK(value->IsNumber());
CHECK_EQ(7, value->Int32Value());
HEAP->CollectAllGarbage(false);
- CHECK_EQ(0, TestResource::dispose_count);
+ CHECK_EQ(0, dispose_count);
}
i::Isolate::Current()->compilation_cache()->Clear();
HEAP->CollectAllGarbage(false);
- CHECK_EQ(1, TestResource::dispose_count);
+ CHECK_EQ(1, dispose_count);
}
THREADED_TEST(ScriptMakingExternalAsciiString) {
- TestAsciiResource::dispose_count = 0;
+ int dispose_count = 0;
const char* c_source = "1 + 2 * 3";
{
v8::HandleScope scope;
@@ -470,18 +461,18 @@
HEAP->CollectGarbage(i::NEW_SPACE); // in survivor space now
HEAP->CollectGarbage(i::NEW_SPACE); // in old gen now
bool success = source->MakeExternal(
- new TestAsciiResource(i::StrDup(c_source)));
+ new TestAsciiResource(i::StrDup(c_source), &dispose_count));
CHECK(success);
Local<Script> script = Script::Compile(source);
Local<Value> value = script->Run();
CHECK(value->IsNumber());
CHECK_EQ(7, value->Int32Value());
HEAP->CollectAllGarbage(false);
- CHECK_EQ(0, TestAsciiResource::dispose_count);
+ CHECK_EQ(0, dispose_count);
}
i::Isolate::Current()->compilation_cache()->Clear();
HEAP->CollectAllGarbage(false);
- CHECK_EQ(1, TestAsciiResource::dispose_count);
+ CHECK_EQ(1, dispose_count);
}
@@ -605,49 +596,52 @@
THREADED_TEST(ScavengeExternalString) {
- TestResource::dispose_count = 0;
+ int dispose_count = 0;
bool in_new_space = false;
{
v8::HandleScope scope;
uint16_t* two_byte_string = AsciiToTwoByteString("test string");
Local<String> string =
- String::NewExternal(new TestResource(two_byte_string));
+ String::NewExternal(new TestResource(two_byte_string,
+ &dispose_count));
i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
HEAP->CollectGarbage(i::NEW_SPACE);
in_new_space = HEAP->InNewSpace(*istring);
CHECK(in_new_space || HEAP->old_data_space()->Contains(*istring));
- CHECK_EQ(0, TestResource::dispose_count);
+ CHECK_EQ(0, dispose_count);
}
HEAP->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
- CHECK_EQ(1, TestResource::dispose_count);
+ CHECK_EQ(1, dispose_count);
}
THREADED_TEST(ScavengeExternalAsciiString) {
- TestAsciiResource::dispose_count = 0;
+ int dispose_count = 0;
bool in_new_space = false;
{
v8::HandleScope scope;
const char* one_byte_string = "test string";
Local<String> string = String::NewExternal(
- new TestAsciiResource(i::StrDup(one_byte_string)));
+ new TestAsciiResource(i::StrDup(one_byte_string), &dispose_count));
i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
HEAP->CollectGarbage(i::NEW_SPACE);
in_new_space = HEAP->InNewSpace(*istring);
CHECK(in_new_space || HEAP->old_data_space()->Contains(*istring));
- CHECK_EQ(0, TestAsciiResource::dispose_count);
+ CHECK_EQ(0, dispose_count);
}
HEAP->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
- CHECK_EQ(1, TestAsciiResource::dispose_count);
+ CHECK_EQ(1, dispose_count);
}
class TestAsciiResourceWithDisposeControl: public TestAsciiResource {
public:
+ // Only used by non-threaded tests, so it can use static fields.
static int dispose_calls;
+ static int dispose_count;
TestAsciiResourceWithDisposeControl(const char* data, bool dispose)
- : TestAsciiResource(data),
+ : TestAsciiResource(data, &dispose_count),
dispose_(dispose) { }
void Dispose() {
@@ -659,6 +653,7 @@
};
+int TestAsciiResourceWithDisposeControl::dispose_count = 0;
int TestAsciiResourceWithDisposeControl::dispose_calls = 0;
@@ -666,7 +661,7 @@
const char* c_source = "1 + 2 * 3";
// Use a stack allocated external string resource allocated object.
- TestAsciiResource::dispose_count = 0;
+ TestAsciiResourceWithDisposeControl::dispose_count = 0;
TestAsciiResourceWithDisposeControl::dispose_calls = 0;
TestAsciiResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
{
@@ -678,15 +673,15 @@
CHECK(value->IsNumber());
CHECK_EQ(7, value->Int32Value());
HEAP->CollectAllGarbage(false);
- CHECK_EQ(0, TestAsciiResource::dispose_count);
+ CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
}
i::Isolate::Current()->compilation_cache()->Clear();
HEAP->CollectAllGarbage(false);
CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
- CHECK_EQ(0, TestAsciiResource::dispose_count);
+ CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
// Use a heap allocated external string resource allocated object.
- TestAsciiResource::dispose_count = 0;
+ TestAsciiResourceWithDisposeControl::dispose_count = 0;
TestAsciiResourceWithDisposeControl::dispose_calls = 0;
TestAsciiResource* res_heap =
new TestAsciiResourceWithDisposeControl(i::StrDup(c_source), true);
@@ -699,12 +694,12 @@
CHECK(value->IsNumber());
CHECK_EQ(7, value->Int32Value());
HEAP->CollectAllGarbage(false);
- CHECK_EQ(0, TestAsciiResource::dispose_count);
+ CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
}
i::Isolate::Current()->compilation_cache()->Clear();
HEAP->CollectAllGarbage(false);
CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
- CHECK_EQ(1, TestAsciiResource::dispose_count);
+ CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_count);
}
@@ -828,7 +823,7 @@
static v8::Handle<v8::Value> callback(const v8::Arguments& args) {
void* ptr = v8::External::Unwrap(args.Data());
CHECK_EQ(expected_ptr, ptr);
- return v8::Boolean::New(true);
+ return v8::True();
}
@@ -2642,7 +2637,7 @@
v8::Handle<Value> CCatcher(const v8::Arguments& args) {
- if (args.Length() < 1) return v8::Boolean::New(false);
+ if (args.Length() < 1) return v8::False();
v8::HandleScope scope;
v8::TryCatch try_catch;
Local<Value> result = v8::Script::Compile(args[0]->ToString())->Run();
@@ -3588,6 +3583,114 @@
}
+static v8::Handle<Value> UnboxedDoubleIndexedPropertyGetter(
+ uint32_t index,
+ const AccessorInfo& info) {
+ ApiTestFuzzer::Fuzz();
+ if (index < 25) {
+ return v8::Handle<Value>(v8_num(index));
+ }
+ return v8::Handle<Value>();
+}
+
+
+static v8::Handle<Value> UnboxedDoubleIndexedPropertySetter(
+ uint32_t index,
+ Local<Value> value,
+ const AccessorInfo& info) {
+ ApiTestFuzzer::Fuzz();
+ if (index < 25) {
+ return v8::Handle<Value>(v8_num(index));
+ }
+ return v8::Handle<Value>();
+}
+
+
+Handle<v8::Array> UnboxedDoubleIndexedPropertyEnumerator(
+ const AccessorInfo& info) {
+ // Force the list of returned keys to be stored in a FastDoubleArray.
+ Local<Script> indexed_property_names_script = Script::Compile(v8_str(
+ "keys = new Array(); keys[125000] = 1;"
+ "for(i = 0; i < 80000; i++) { keys[i] = i; };"
+ "keys.length = 25; keys;"));
+ Local<Value> result = indexed_property_names_script->Run();
+ return Local<v8::Array>(::v8::Array::Cast(*result));
+}
+
+
+// Make sure that the the interceptor code in the runtime properly handles
+// merging property name lists for double-array-backed arrays.
+THREADED_TEST(IndexedInterceptorUnboxedDoubleWithIndexedAccessor) {
+ v8::HandleScope scope;
+ Local<ObjectTemplate> templ = ObjectTemplate::New();
+ templ->SetIndexedPropertyHandler(UnboxedDoubleIndexedPropertyGetter,
+ UnboxedDoubleIndexedPropertySetter,
+ 0,
+ 0,
+ UnboxedDoubleIndexedPropertyEnumerator);
+ LocalContext context;
+ context->Global()->Set(v8_str("obj"), templ->NewInstance());
+ // When obj is created, force it to be Stored in a FastDoubleArray.
+ Local<Script> create_unboxed_double_script = Script::Compile(v8_str(
+ "obj[125000] = 1; for(i = 0; i < 80000; i+=2) { obj[i] = i; } "
+ "key_count = 0; "
+ "for (x in obj) {key_count++;};"
+ "obj;"));
+ Local<Value> result = create_unboxed_double_script->Run();
+ CHECK(result->ToObject()->HasRealIndexedProperty(2000));
+ Local<Script> key_count_check = Script::Compile(v8_str(
+ "key_count;"));
+ result = key_count_check->Run();
+ CHECK_EQ(v8_num(40013), result);
+}
+
+
+Handle<v8::Array> NonStrictArgsIndexedPropertyEnumerator(
+ const AccessorInfo& info) {
+ // Force the list of returned keys to be stored in a Arguments object.
+ Local<Script> indexed_property_names_script = Script::Compile(v8_str(
+ "function f(w,x) {"
+ " return arguments;"
+ "}"
+ "keys = f(0, 1, 2, 3);"
+ "keys;"));
+ Local<Value> result = indexed_property_names_script->Run();
+ return Local<v8::Array>(static_cast<v8::Array*>(::v8::Object::Cast(*result)));
+}
+
+
+static v8::Handle<Value> NonStrictIndexedPropertyGetter(
+ uint32_t index,
+ const AccessorInfo& info) {
+ ApiTestFuzzer::Fuzz();
+ if (index < 4) {
+ return v8::Handle<Value>(v8_num(index));
+ }
+ return v8::Handle<Value>();
+}
+
+
+// Make sure that the the interceptor code in the runtime properly handles
+// merging property name lists for non-string arguments arrays.
+THREADED_TEST(IndexedInterceptorNonStrictArgsWithIndexedAccessor) {
+ v8::HandleScope scope;
+ Local<ObjectTemplate> templ = ObjectTemplate::New();
+ templ->SetIndexedPropertyHandler(NonStrictIndexedPropertyGetter,
+ 0,
+ 0,
+ 0,
+ NonStrictArgsIndexedPropertyEnumerator);
+ LocalContext context;
+ context->Global()->Set(v8_str("obj"), templ->NewInstance());
+ Local<Script> create_args_script =
+ Script::Compile(v8_str(
+ "var key_count = 0;"
+ "for (x in obj) {key_count++;} key_count;"));
+ Local<Value> result = create_args_script->Run();
+ CHECK_EQ(v8_num(4), result);
+}
+
+
static v8::Handle<Value> IdentityIndexedPropertyGetter(
uint32_t index,
const AccessorInfo& info) {
@@ -5221,6 +5324,40 @@
CHECK_EQ(0, strncmp("d\1", buf, 2));
uint16_t answer7[] = {'d', 0x101};
CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
+
+ memset(wbuf, 0x1, sizeof(wbuf));
+ wbuf[5] = 'X';
+ len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION);
+ CHECK_EQ(5, len);
+ CHECK_EQ('X', wbuf[5]);
+ uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
+ uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
+ CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
+ CHECK_NE(0, StrCmp16(answer8b, wbuf));
+ wbuf[5] = '\0';
+ CHECK_EQ(0, StrCmp16(answer8b, wbuf));
+
+ memset(buf, 0x1, sizeof(buf));
+ buf[5] = 'X';
+ len = str->WriteAscii(buf, 0, 6, String::NO_NULL_TERMINATION);
+ CHECK_EQ(5, len);
+ CHECK_EQ('X', buf[5]);
+ CHECK_EQ(0, strncmp("abcde", buf, 5));
+ CHECK_NE(0, strcmp("abcde", buf));
+ buf[5] = '\0';
+ CHECK_EQ(0, strcmp("abcde", buf));
+
+ memset(utf8buf, 0x1, sizeof(utf8buf));
+ utf8buf[8] = 'X';
+ len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
+ String::NO_NULL_TERMINATION);
+ CHECK_EQ(8, len);
+ CHECK_EQ('X', utf8buf[8]);
+ CHECK_EQ(5, charlen);
+ CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
+ CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
+ utf8buf[8] = '\0';
+ CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
}
@@ -7021,53 +7158,34 @@
}
-THREADED_TEST(SetPrototypeProperties) {
+THREADED_TEST(FunctionReadOnlyPrototype) {
v8::HandleScope handle_scope;
LocalContext context;
Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
- t1->SetPrototypeAttributes(v8::DontDelete);
+ t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(42));
+ t1->ReadOnlyPrototype();
context->Global()->Set(v8_str("func1"), t1->GetFunction());
+ // Configured value of ReadOnly flag.
CHECK(CompileRun(
"(function() {"
" descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
- " return (descriptor['writable'] == true) &&"
- " (descriptor['enumerable'] == true) &&"
- " (descriptor['configurable'] == false);"
+ " return (descriptor['writable'] == false);"
"})()")->BooleanValue());
+ CHECK_EQ(42, CompileRun("func1.prototype.x")->Int32Value());
+ CHECK_EQ(42,
+ CompileRun("func1.prototype = {}; func1.prototype.x")->Int32Value());
Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
- t2->SetPrototypeAttributes(v8::DontEnum);
+ t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(42));
context->Global()->Set(v8_str("func2"), t2->GetFunction());
+ // Default value of ReadOnly flag.
CHECK(CompileRun(
"(function() {"
" descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
- " return (descriptor['writable'] == true) &&"
- " (descriptor['enumerable'] == false) &&"
- " (descriptor['configurable'] == true);"
+ " return (descriptor['writable'] == true);"
"})()")->BooleanValue());
-
- Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
- t3->SetPrototypeAttributes(v8::ReadOnly);
- context->Global()->Set(v8_str("func3"), t3->GetFunction());
- CHECK(CompileRun(
- "(function() {"
- " descriptor = Object.getOwnPropertyDescriptor(func3, 'prototype');"
- " return (descriptor['writable'] == false) &&"
- " (descriptor['enumerable'] == true) &&"
- " (descriptor['configurable'] == true);"
- "})()")->BooleanValue());
-
- Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New();
- t4->SetPrototypeAttributes(v8::ReadOnly | v8::DontEnum | v8::DontDelete);
- context->Global()->Set(v8_str("func4"), t4->GetFunction());
- CHECK(CompileRun(
- "(function() {"
- " descriptor = Object.getOwnPropertyDescriptor(func4, 'prototype');"
- " return (descriptor['writable'] == false) &&"
- " (descriptor['enumerable'] == false) &&"
- " (descriptor['configurable'] == false);"
- "})()")->BooleanValue());
+ CHECK_EQ(42, CompileRun("func2.prototype.x")->Int32Value());
}
@@ -7206,7 +7324,7 @@
CHECK(value->IsBoolean());
CHECK_EQ(true, value->BooleanValue());
- Handle<Value> args3[] = { v8::Boolean::New(true) };
+ Handle<Value> args3[] = { v8::True() };
Local<Value> value_obj3 = instance->CallAsConstructor(1, args3);
CHECK(value_obj3->IsObject());
Local<Object> object3 = Local<Object>::Cast(value_obj3);
@@ -9477,10 +9595,7 @@
static v8::Handle<Value> IsConstructHandler(const v8::Arguments& args) {
ApiTestFuzzer::Fuzz();
- if (args.IsConstructCall()) {
- return v8::Boolean::New(true);
- }
- return v8::Boolean::New(false);
+ return v8::Boolean::New(args.IsConstructCall());
}
@@ -11646,7 +11761,7 @@
}
HEAP->CollectAllGarbage(false); // Force GC to trigger verification.
for (int i = 0; i < kElementCount; i++) {
- CHECK_EQ(i % 256, pixels->get(i));
+ CHECK_EQ(i % 256, pixels->get_scalar(i));
CHECK_EQ(i % 256, pixel_data[i]);
}
@@ -12119,7 +12234,8 @@
}
HEAP->CollectAllGarbage(false); // Force GC to trigger verification.
for (int i = 0; i < kElementCount; i++) {
- CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array->get(i)));
+ CHECK_EQ(static_cast<int64_t>(i),
+ static_cast<int64_t>(array->get_scalar(i)));
CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i]));
}
@@ -13636,6 +13752,9 @@
"str2;";
Local<Value> result = CompileRun(init_code);
+ Local<Value> indexof = CompileRun("str2.indexOf('els')");
+ Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
+
CHECK(result->IsString());
i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
int length = string->length();
@@ -13701,6 +13820,10 @@
ExpectString("str2.charAt(2);", "e");
+ ExpectObject("str2.indexOf('els');", indexof);
+
+ ExpectObject("str2.lastIndexOf('dab');", lastindexof);
+
reresult = CompileRun("str2.charCodeAt(2);");
CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value());
}
@@ -14354,34 +14477,34 @@
v8::Handle<v8::RegExp> re = v8::RegExp::New(v8_str("foo"), v8::RegExp::kNone);
CHECK(re->IsRegExp());
CHECK(re->GetSource()->Equals(v8_str("foo")));
- CHECK_EQ(re->GetFlags(), v8::RegExp::kNone);
+ CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
re = v8::RegExp::New(v8_str("bar"),
static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
v8::RegExp::kGlobal));
CHECK(re->IsRegExp());
CHECK(re->GetSource()->Equals(v8_str("bar")));
- CHECK_EQ(static_cast<int>(re->GetFlags()),
- v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal);
+ CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
+ static_cast<int>(re->GetFlags()));
re = v8::RegExp::New(v8_str("baz"),
static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
v8::RegExp::kMultiline));
CHECK(re->IsRegExp());
CHECK(re->GetSource()->Equals(v8_str("baz")));
- CHECK_EQ(static_cast<int>(re->GetFlags()),
- v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline);
+ CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
+ static_cast<int>(re->GetFlags()));
re = CompileRun("/quux/").As<v8::RegExp>();
CHECK(re->IsRegExp());
CHECK(re->GetSource()->Equals(v8_str("quux")));
- CHECK_EQ(re->GetFlags(), v8::RegExp::kNone);
+ CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
re = CompileRun("/quux/gm").As<v8::RegExp>();
CHECK(re->IsRegExp());
CHECK(re->GetSource()->Equals(v8_str("quux")));
- CHECK_EQ(static_cast<int>(re->GetFlags()),
- v8::RegExp::kGlobal | v8::RegExp::kMultiline);
+ CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
+ static_cast<int>(re->GetFlags()));
// Override the RegExp constructor and check the API constructor
// still works.
@@ -14390,15 +14513,15 @@
re = v8::RegExp::New(v8_str("foobar"), v8::RegExp::kNone);
CHECK(re->IsRegExp());
CHECK(re->GetSource()->Equals(v8_str("foobar")));
- CHECK_EQ(re->GetFlags(), v8::RegExp::kNone);
+ CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
re = v8::RegExp::New(v8_str("foobarbaz"),
static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
v8::RegExp::kMultiline));
CHECK(re->IsRegExp());
CHECK(re->GetSource()->Equals(v8_str("foobarbaz")));
- CHECK_EQ(static_cast<int>(re->GetFlags()),
- v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline);
+ CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
+ static_cast<int>(re->GetFlags()));
context->Global()->Set(v8_str("re"), re);
ExpectTrue("re.test('FoobarbaZ')");
@@ -14579,6 +14702,24 @@
}
+THREADED_TEST(CreationContextOfJsFunction) {
+ HandleScope handle_scope;
+ Persistent<Context> context = Context::New();
+ InstallContextId(context, 1);
+
+ Local<Object> function;
+ {
+ Context::Scope scope(context);
+ function = CompileRun("function foo() {}; foo").As<Object>();
+ }
+
+ CHECK(function->CreationContext() == context);
+ CheckContextId(function, 1);
+
+ context.Dispose();
+}
+
+
Handle<Value> HasOwnPropertyIndexedPropertyGetter(uint32_t index,
const AccessorInfo& info) {
if (index == 42) return v8_str("yes");
@@ -14930,3 +15071,107 @@
context.Dispose();
}
+
+
+static void TestReceiver(Local<Value> expected_result,
+ Local<Value> expected_receiver,
+ const char* code) {
+ Local<Value> result = CompileRun(code);
+ CHECK(result->IsObject());
+ CHECK(expected_receiver->Equals(result->ToObject()->Get(1)));
+ CHECK(expected_result->Equals(result->ToObject()->Get(0)));
+}
+
+
+THREADED_TEST(ForeignFunctionReceiver) {
+ HandleScope scope;
+
+ // Create two contexts with different "id" properties ('i' and 'o').
+ // Call a function both from its own context and from a the foreign
+ // context, and see what "this" is bound to (returning both "this"
+ // and "this.id" for comparison).
+
+ Persistent<Context> foreign_context = v8::Context::New();
+ foreign_context->Enter();
+ Local<Value> foreign_function =
+ CompileRun("function func() { return { 0: this.id, "
+ " 1: this, "
+ " toString: function() { "
+ " return this[0];"
+ " }"
+ " };"
+ "}"
+ "var id = 'i';"
+ "func;");
+ CHECK(foreign_function->IsFunction());
+ foreign_context->Exit();
+
+ LocalContext context;
+
+ Local<String> password = v8_str("Password");
+ // Don't get hit by security checks when accessing foreign_context's
+ // global receiver (aka. global proxy).
+ context->SetSecurityToken(password);
+ foreign_context->SetSecurityToken(password);
+
+ Local<String> i = v8_str("i");
+ Local<String> o = v8_str("o");
+ Local<String> id = v8_str("id");
+
+ CompileRun("function ownfunc() { return { 0: this.id, "
+ " 1: this, "
+ " toString: function() { "
+ " return this[0];"
+ " }"
+ " };"
+ "}"
+ "var id = 'o';"
+ "ownfunc");
+ context->Global()->Set(v8_str("func"), foreign_function);
+
+ // Sanity check the contexts.
+ CHECK(i->Equals(foreign_context->Global()->Get(id)));
+ CHECK(o->Equals(context->Global()->Get(id)));
+
+ // Checking local function's receiver.
+ // Calling function using its call/apply methods.
+ TestReceiver(o, context->Global(), "ownfunc.call()");
+ TestReceiver(o, context->Global(), "ownfunc.apply()");
+ // Making calls through built-in functions.
+ TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
+ CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/,ownfunc)[1]")));
+ CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]")));
+ CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]")));
+ // Calling with environment record as base.
+ TestReceiver(o, context->Global(), "ownfunc()");
+ // Calling with no base.
+ TestReceiver(o, context->Global(), "(1,ownfunc)()");
+
+ // Checking foreign function return value.
+ // Calling function using its call/apply methods.
+ TestReceiver(i, foreign_context->Global(), "func.call()");
+ TestReceiver(i, foreign_context->Global(), "func.apply()");
+ // Calling function using another context's call/apply methods.
+ TestReceiver(i, foreign_context->Global(),
+ "Function.prototype.call.call(func)");
+ TestReceiver(i, foreign_context->Global(),
+ "Function.prototype.call.apply(func)");
+ TestReceiver(i, foreign_context->Global(),
+ "Function.prototype.apply.call(func)");
+ TestReceiver(i, foreign_context->Global(),
+ "Function.prototype.apply.apply(func)");
+ // Making calls through built-in functions.
+ TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
+ // ToString(func()) is func()[0], i.e., the returned this.id.
+ CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/,func)[1]")));
+ CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[1]")));
+ CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]")));
+
+ // TODO(1547): Make the following also return "i".
+ // Calling with environment record as base.
+ TestReceiver(o, context->Global(), "func()");
+ // Calling with no base.
+ TestReceiver(o, context->Global(), "(1,func)()");
+
+ foreign_context.Dispose();
+}
diff --git a/test/cctest/test-assembler-arm.cc b/test/cctest/test-assembler-arm.cc
index 1703203..ecbf956 100644
--- a/test/cctest/test-assembler-arm.cc
+++ b/test/cctest/test-assembler-arm.cc
@@ -1010,4 +1010,18 @@
CHECK_EQ(0xffffffff, i.d);
}
+
+TEST(12) {
+ // Test chaining of label usages within instructions (issue 1644).
+ InitializeVM();
+ v8::HandleScope scope;
+ Assembler assm(Isolate::Current(), NULL, 0);
+
+ Label target;
+ __ b(eq, &target);
+ __ b(ne, &target);
+ __ bind(&target);
+ __ nop();
+}
+
#undef __
diff --git a/test/cctest/test-assembler-ia32.cc b/test/cctest/test-assembler-ia32.cc
index e9d799b..839b7f5 100644
--- a/test/cctest/test-assembler-ia32.cc
+++ b/test/cctest/test-assembler-ia32.cc
@@ -394,4 +394,18 @@
CHECK_EQ(kNaN, f(OS::nan_value(), 1.1));
}
+
+TEST(AssemblerIa3210) {
+ // Test chaining of label usages within instructions (issue 1644).
+ InitializeVM();
+ v8::HandleScope scope;
+ Assembler assm(Isolate::Current(), NULL, 0);
+
+ Label target;
+ __ j(equal, &target);
+ __ j(not_equal, &target);
+ __ bind(&target);
+ __ nop();
+}
+
#undef __
diff --git a/test/cctest/test-assembler-mips.cc b/test/cctest/test-assembler-mips.cc
index 8ac89f6..ca11a2a 100644
--- a/test/cctest/test-assembler-mips.cc
+++ b/test/cctest/test-assembler-mips.cc
@@ -1083,17 +1083,17 @@
CpuFeatures::Scope scope(FPU);
__ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_small_in)));
- __ Cvt_d_uw(f10, t0);
+ __ Cvt_d_uw(f10, t0, f22);
__ sdc1(f10, MemOperand(a0, OFFSET_OF(T, cvt_small_out)));
- __ Trunc_uw_d(f10, f10);
+ __ Trunc_uw_d(f10, f10, f22);
__ swc1(f10, MemOperand(a0, OFFSET_OF(T, trunc_small_out)));
__ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_big_in)));
- __ Cvt_d_uw(f8, t0);
+ __ Cvt_d_uw(f8, t0, f22);
__ sdc1(f8, MemOperand(a0, OFFSET_OF(T, cvt_big_out)));
- __ Trunc_uw_d(f8, f8);
+ __ Trunc_uw_d(f8, f8, f22);
__ swc1(f8, MemOperand(a0, OFFSET_OF(T, trunc_big_out)));
__ jr(ra);
@@ -1259,4 +1259,18 @@
}
}
+
+TEST(MIPS15) {
+ // Test chaining of label usages within instructions (issue 1644).
+ InitializeVM();
+ v8::HandleScope scope;
+ Assembler assm(Isolate::Current(), NULL, 0);
+
+ Label target;
+ __ beq(v0, v1, &target);
+ __ bne(v0, v1, &target);
+ __ bind(&target);
+ __ nop();
+}
+
#undef __
diff --git a/test/cctest/test-assembler-x64.cc b/test/cctest/test-assembler-x64.cc
index ea70f54..28f7c9b 100644
--- a/test/cctest/test-assembler-x64.cc
+++ b/test/cctest/test-assembler-x64.cc
@@ -46,6 +46,7 @@
using v8::internal::byte;
using v8::internal::greater;
using v8::internal::less_equal;
+using v8::internal::equal;
using v8::internal::not_equal;
using v8::internal::r13;
using v8::internal::r15;
@@ -345,4 +346,17 @@
}
}
+
+TEST(AssemblerX64LabelChaining) {
+ // Test chaining of label usages within instructions (issue 1644).
+ v8::HandleScope scope;
+ Assembler assm(Isolate::Current(), NULL, 0);
+
+ Label target;
+ __ j(equal, &target);
+ __ j(not_equal, &target);
+ __ bind(&target);
+ __ nop();
+}
+
#undef __
diff --git a/test/cctest/test-ast.cc b/test/cctest/test-ast.cc
index 786a54a..2aa7207 100644
--- a/test/cctest/test-ast.cc
+++ b/test/cctest/test-ast.cc
@@ -56,14 +56,3 @@
CHECK_EQ(0, list->length());
delete list;
}
-
-
-TEST(DeleteEmpty) {
- {
- List<int>* list = new List<int>(0);
- delete list;
- }
- {
- List<int> list(0);
- }
-}
diff --git a/test/cctest/test-circular-queue.cc b/test/cctest/test-circular-queue.cc
index c4e5c4c..2861b1f 100644
--- a/test/cctest/test-circular-queue.cc
+++ b/test/cctest/test-circular-queue.cc
@@ -6,8 +6,6 @@
#include "circular-queue-inl.h"
#include "cctest.h"
-namespace i = v8::internal;
-
using i::SamplingCircularQueue;
diff --git a/test/cctest/test-cpu-profiler.cc b/test/cctest/test-cpu-profiler.cc
index 9ff2a17..81c487d 100644
--- a/test/cctest/test-cpu-profiler.cc
+++ b/test/cctest/test-cpu-profiler.cc
@@ -7,8 +7,6 @@
#include "cctest.h"
#include "../include/v8-profiler.h"
-namespace i = v8::internal;
-
using i::CodeEntry;
using i::CpuProfile;
using i::CpuProfiler;
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index 73b84b7..b7962de 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -2174,7 +2174,7 @@
f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
g = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("g")));
- // Chesk that a break point was hit when the script was run.
+ // Check that a break point was hit when the script was run.
CHECK_EQ(1, break_point_hit_count);
CHECK_EQ(0, StrLength(last_function_hit));
@@ -5844,6 +5844,7 @@
TEST(DebuggerAgent) {
+ v8::V8::Initialize();
i::Debugger* debugger = i::Isolate::Current()->debugger();
// Make sure these ports is not used by other tests to allow tests to run in
// parallel.
diff --git a/test/cctest/test-dictionary.cc b/test/cctest/test-dictionary.cc
new file mode 100644
index 0000000..15a854b
--- /dev/null
+++ b/test/cctest/test-dictionary.cc
@@ -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.
+
+#include "v8.h"
+
+#include "api.h"
+#include "debug.h"
+#include "execution.h"
+#include "factory.h"
+#include "macro-assembler.h"
+#include "objects.h"
+#include "global-handles.h"
+#include "cctest.h"
+
+using namespace v8::internal;
+
+TEST(ObjectHashTable) {
+ v8::HandleScope scope;
+ LocalContext context;
+ Handle<ObjectHashTable> table = FACTORY->NewObjectHashTable(23);
+ Handle<JSObject> a = FACTORY->NewJSArray(7);
+ Handle<JSObject> b = FACTORY->NewJSArray(11);
+ table = PutIntoObjectHashTable(table, a, b);
+ CHECK_EQ(table->NumberOfElements(), 1);
+ CHECK_EQ(table->Lookup(*a), *b);
+ CHECK_EQ(table->Lookup(*b), HEAP->undefined_value());
+
+ // Keys still have to be valid after objects were moved.
+ HEAP->CollectGarbage(NEW_SPACE);
+ CHECK_EQ(table->NumberOfElements(), 1);
+ CHECK_EQ(table->Lookup(*a), *b);
+ CHECK_EQ(table->Lookup(*b), HEAP->undefined_value());
+
+ // Keys that are overwritten should not change number of elements.
+ table = PutIntoObjectHashTable(table, a, FACTORY->NewJSArray(13));
+ CHECK_EQ(table->NumberOfElements(), 1);
+ CHECK_NE(table->Lookup(*a), *b);
+
+ // Keys mapped to undefined should be removed permanently.
+ table = PutIntoObjectHashTable(table, a, FACTORY->undefined_value());
+ CHECK_EQ(table->NumberOfElements(), 0);
+ CHECK_EQ(table->NumberOfDeletedElements(), 1);
+ CHECK_EQ(table->Lookup(*a), HEAP->undefined_value());
+
+ // Keys should map back to their respective values.
+ for (int i = 0; i < 100; i++) {
+ Handle<JSObject> key = FACTORY->NewJSArray(7);
+ Handle<JSObject> value = FACTORY->NewJSArray(11);
+ table = PutIntoObjectHashTable(table, key, value);
+ CHECK_EQ(table->NumberOfElements(), i + 1);
+ CHECK_NE(table->FindEntry(*key), ObjectHashTable::kNotFound);
+ CHECK_EQ(table->Lookup(*key), *value);
+ }
+
+ // 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());
+ }
+}
diff --git a/test/cctest/test-func-name-inference.cc b/test/cctest/test-func-name-inference.cc
index 4d993af..bb930c8 100644
--- a/test/cctest/test-func-name-inference.cc
+++ b/test/cctest/test-func-name-inference.cc
@@ -361,3 +361,42 @@
// Can't infer the function name statically.
CheckFunctionName(script, "return 1", "obj.(anonymous function)");
}
+
+
+TEST(GlobalAssignmentAndCall) {
+ InitializeVM();
+ v8::HandleScope scope;
+
+ v8::Handle<v8::Script> script = Compile(
+ "var Foo = function() {\n"
+ " return 1;\n"
+ "}();\n"
+ "var Baz = Bar = function() {\n"
+ " return 2;\n"
+ "}");
+ // The inferred name is empty, because this is an assignment of a result.
+ CheckFunctionName(script, "return 1", "");
+ // See MultipleAssignments test.
+ CheckFunctionName(script, "return 2", "Bar");
+}
+
+
+TEST(AssignmentAndCall) {
+ InitializeVM();
+ v8::HandleScope scope;
+
+ v8::Handle<v8::Script> script = Compile(
+ "(function Enclosing() {\n"
+ " var Foo;\n"
+ " Foo = function() {\n"
+ " return 1;\n"
+ " }();\n"
+ " var Baz = Bar = function() {\n"
+ " return 2;\n"
+ " }\n"
+ "})();");
+ // The inferred name is empty, because this is an assignment of a result.
+ CheckFunctionName(script, "return 1", "");
+ // See MultipleAssignments test.
+ CheckFunctionName(script, "return 2", "Enclosing.Bar");
+}
diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc
index 8675a01..143a23c 100644
--- a/test/cctest/test-heap-profiler.cc
+++ b/test/cctest/test-heap-profiler.cc
@@ -10,8 +10,6 @@
#include "utils-inl.h"
#include "../include/v8-profiler.h"
-namespace i = v8::internal;
-
namespace {
class NamedEntriesDetector {
@@ -87,7 +85,7 @@
"var b2_1 = new B2(a2), b2_2 = new B2(a2);\n"
"var c2 = new C2(a2);");
const v8::HeapSnapshot* snapshot_env2 =
- v8::HeapProfiler::TakeSnapshot(v8::String::New("env2"));
+ v8::HeapProfiler::TakeSnapshot(v8_str("env2"));
i::HeapSnapshot* i_snapshot_env2 =
const_cast<i::HeapSnapshot*>(
reinterpret_cast<const i::HeapSnapshot*>(snapshot_env2));
@@ -126,7 +124,7 @@
"x = new X(new X(), new X());\n"
"(function() { x.a.a = x.b; })();");
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8::String::New("sizes"));
+ v8::HeapProfiler::TakeSnapshot(v8_str("sizes"));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* x =
GetProperty(global, v8::HeapGraphEdge::kShortcut, "x");
@@ -157,7 +155,7 @@
"function A() { }\n"
"a = new A;");
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8::String::New("children"));
+ v8::HeapProfiler::TakeSnapshot(v8_str("children"));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
for (int i = 0, count = global->GetChildrenCount(); i < count; ++i) {
const v8::HeapGraphEdge* prop = global->GetChild(i);
@@ -183,7 +181,7 @@
"var anonymous = (function() { return function() { return 0; } })();\n"
"compiled(1)");
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8::String::New("code"));
+ v8::HeapProfiler::TakeSnapshot(v8_str("code"));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* compiled =
@@ -245,7 +243,7 @@
"a = 1; // a is Smi\n"
"b = 2.5; // b is HeapNumber");
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8::String::New("numbers"));
+ v8::HeapProfiler::TakeSnapshot(v8_str("numbers"));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
CHECK_EQ(NULL, GetProperty(global, v8::HeapGraphEdge::kShortcut, "a"));
const v8::HeapGraphNode* b =
@@ -267,7 +265,7 @@
global->SetInternalField(0, v8_num(17));
global->SetInternalField(1, obj);
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8::String::New("internals"));
+ v8::HeapProfiler::TakeSnapshot(v8_str("internals"));
const v8::HeapGraphNode* global_node = GetGlobalObject(snapshot);
// The first reference will not present, because it's a Smi.
CHECK_EQ(NULL, GetProperty(global_node, v8::HeapGraphEdge::kInternal, "0"));
@@ -294,12 +292,12 @@
"var a = new A();\n"
"var b = new B(a);");
const v8::HeapSnapshot* snapshot1 =
- v8::HeapProfiler::TakeSnapshot(v8::String::New("s1"));
+ v8::HeapProfiler::TakeSnapshot(v8_str("s1"));
HEAP->CollectAllGarbage(true); // Enforce compaction.
const v8::HeapSnapshot* snapshot2 =
- v8::HeapProfiler::TakeSnapshot(v8::String::New("s2"));
+ v8::HeapProfiler::TakeSnapshot(v8_str("s2"));
const v8::HeapGraphNode* global1 = GetGlobalObject(snapshot1);
const v8::HeapGraphNode* global2 = GetGlobalObject(snapshot2);
@@ -344,7 +342,7 @@
v8::HandleScope scope;
LocalContext env;
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8::String::New("s"));
+ v8::HeapProfiler::TakeSnapshot(v8_str("s"));
const v8::HeapGraphNode* root1 = snapshot->GetRoot();
const_cast<i::HeapSnapshot*>(reinterpret_cast<const i::HeapSnapshot*>(
snapshot))->GetSortedEntriesList();
@@ -382,7 +380,7 @@
"})();");
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8::String::New("dominators"));
+ v8::HeapProfiler::TakeSnapshot(v8_str("dominators"));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
CHECK_NE(NULL, global);
@@ -465,7 +463,7 @@
"var a = new A(" STRING_LITERAL_FOR_TEST ");\n"
"var b = new B(a);");
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8::String::New("json"));
+ v8::HeapProfiler::TakeSnapshot(v8_str("json"));
TestJSONStream stream;
snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON);
CHECK_GT(stream.size(), 0);
@@ -476,17 +474,17 @@
// Verify that snapshot string is valid JSON.
AsciiResource json_res(json);
v8::Local<v8::String> json_string = v8::String::NewExternal(&json_res);
- env->Global()->Set(v8::String::New("json_snapshot"), json_string);
+ env->Global()->Set(v8_str("json_snapshot"), json_string);
v8::Local<v8::Value> snapshot_parse_result = CompileRun(
"var parsed = JSON.parse(json_snapshot); true;");
CHECK(!snapshot_parse_result.IsEmpty());
// Verify that snapshot object has required fields.
v8::Local<v8::Object> parsed_snapshot =
- env->Global()->Get(v8::String::New("parsed"))->ToObject();
- CHECK(parsed_snapshot->Has(v8::String::New("snapshot")));
- CHECK(parsed_snapshot->Has(v8::String::New("nodes")));
- CHECK(parsed_snapshot->Has(v8::String::New("strings")));
+ env->Global()->Get(v8_str("parsed"))->ToObject();
+ CHECK(parsed_snapshot->Has(v8_str("snapshot")));
+ CHECK(parsed_snapshot->Has(v8_str("nodes")));
+ CHECK(parsed_snapshot->Has(v8_str("strings")));
// Get node and edge "member" offsets.
v8::Local<v8::Value> meta_analysis_result = CompileRun(
@@ -538,12 +536,12 @@
int string_obj_pos =
static_cast<int>(string_obj_pos_val->ToNumber()->Value());
v8::Local<v8::Object> nodes_array =
- parsed_snapshot->Get(v8::String::New("nodes"))->ToObject();
+ parsed_snapshot->Get(v8_str("nodes"))->ToObject();
int string_index = static_cast<int>(
nodes_array->Get(string_obj_pos + 1)->ToNumber()->Value());
CHECK_GT(string_index, 0);
v8::Local<v8::Object> strings_array =
- parsed_snapshot->Get(v8::String::New("strings"))->ToObject();
+ parsed_snapshot->Get(v8_str("strings"))->ToObject();
v8::Local<v8::String> string = strings_array->Get(string_index)->ToString();
v8::Local<v8::String> ref_string =
CompileRun(STRING_LITERAL_FOR_TEST)->ToString();
@@ -557,7 +555,7 @@
v8::HandleScope scope;
LocalContext env;
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8::String::New("abort"));
+ v8::HeapProfiler::TakeSnapshot(v8_str("abort"));
TestJSONStream stream(5);
snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON);
CHECK_GT(stream.size(), 0);
@@ -570,7 +568,7 @@
LocalContext env;
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8::String::New("id"));
+ v8::HeapProfiler::TakeSnapshot(v8_str("id"));
const v8::HeapGraphNode* root = snapshot->GetRoot();
CHECK_EQ(root, snapshot->GetNodeById(root->GetId()));
for (int i = 0, count = root->GetChildrenCount(); i < count; ++i) {
@@ -611,7 +609,7 @@
const int snapshots_count = v8::HeapProfiler::GetSnapshotsCount();
TestActivityControl aborting_control(3);
const v8::HeapSnapshot* no_snapshot =
- v8::HeapProfiler::TakeSnapshot(v8::String::New("abort"),
+ v8::HeapProfiler::TakeSnapshot(v8_str("abort"),
v8::HeapSnapshot::kFull,
&aborting_control);
CHECK_EQ(NULL, no_snapshot);
@@ -620,7 +618,7 @@
TestActivityControl control(-1); // Don't abort.
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8::String::New("full"),
+ v8::HeapProfiler::TakeSnapshot(v8_str("full"),
v8::HeapSnapshot::kFull,
&control);
CHECK_NE(NULL, snapshot);
@@ -730,7 +728,7 @@
p_CCC.SetWrapperClassId(2);
CHECK_EQ(0, TestRetainedObjectInfo::instances.length());
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8::String::New("retained"));
+ v8::HeapProfiler::TakeSnapshot(v8_str("retained"));
CHECK_EQ(3, TestRetainedObjectInfo::instances.length());
for (int i = 0; i < TestRetainedObjectInfo::instances.length(); ++i) {
@@ -774,12 +772,12 @@
CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
v8::HeapProfiler::DeleteAllSnapshots();
CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
- CHECK_NE(NULL, v8::HeapProfiler::TakeSnapshot(v8::String::New("1")));
+ CHECK_NE(NULL, v8::HeapProfiler::TakeSnapshot(v8_str("1")));
CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount());
v8::HeapProfiler::DeleteAllSnapshots();
CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
- CHECK_NE(NULL, v8::HeapProfiler::TakeSnapshot(v8::String::New("1")));
- CHECK_NE(NULL, v8::HeapProfiler::TakeSnapshot(v8::String::New("2")));
+ CHECK_NE(NULL, v8::HeapProfiler::TakeSnapshot(v8_str("1")));
+ CHECK_NE(NULL, v8::HeapProfiler::TakeSnapshot(v8_str("2")));
CHECK_EQ(2, v8::HeapProfiler::GetSnapshotsCount());
v8::HeapProfiler::DeleteAllSnapshots();
CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
@@ -792,7 +790,7 @@
CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
const v8::HeapSnapshot* s1 =
- v8::HeapProfiler::TakeSnapshot(v8::String::New("1"));
+ v8::HeapProfiler::TakeSnapshot(v8_str("1"));
CHECK_NE(NULL, s1);
CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount());
unsigned uid1 = s1->GetUid();
@@ -802,14 +800,14 @@
CHECK_EQ(NULL, v8::HeapProfiler::FindSnapshot(uid1));
const v8::HeapSnapshot* s2 =
- v8::HeapProfiler::TakeSnapshot(v8::String::New("2"));
+ v8::HeapProfiler::TakeSnapshot(v8_str("2"));
CHECK_NE(NULL, s2);
CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount());
unsigned uid2 = s2->GetUid();
CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid2));
CHECK_EQ(s2, v8::HeapProfiler::FindSnapshot(uid2));
const v8::HeapSnapshot* s3 =
- v8::HeapProfiler::TakeSnapshot(v8::String::New("3"));
+ v8::HeapProfiler::TakeSnapshot(v8_str("3"));
CHECK_NE(NULL, s3);
CHECK_EQ(2, v8::HeapProfiler::GetSnapshotsCount());
unsigned uid3 = s3->GetUid();
@@ -832,7 +830,7 @@
CompileRun("document = { URL:\"abcdefgh\" };");
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8::String::New("document"));
+ v8::HeapProfiler::TakeSnapshot(v8_str("document"));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
CHECK_NE(NULL, global);
CHECK_EQ("Object / abcdefgh",
@@ -848,7 +846,7 @@
CompileRun(
"this.__defineGetter__(\"document\", function() { throw new Error(); })");
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8::String::New("document"));
+ v8::HeapProfiler::TakeSnapshot(v8_str("document"));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
CHECK_NE(NULL, global);
CHECK_EQ("Object",
@@ -866,7 +864,7 @@
"URLWithException.prototype = { get URL() { throw new Error(); } };\n"
"document = { URL: new URLWithException() };");
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8::String::New("document"));
+ v8::HeapProfiler::TakeSnapshot(v8_str("document"));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
CHECK_NE(NULL, global);
CHECK_EQ("Object",
@@ -879,7 +877,7 @@
v8::HandleScope scope;
LocalContext env;
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8::String::New("iteration"));
+ v8::HeapProfiler::TakeSnapshot(v8_str("iteration"));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
CHECK_NE(NULL, global);
// Verify that we can find this object by iteration.
@@ -891,3 +889,115 @@
}
CHECK_EQ(1, count);
}
+
+
+TEST(GetHeapValue) {
+ v8::HandleScope scope;
+ LocalContext env;
+
+ CompileRun("a = { s_prop: \'value\', n_prop: 0.1 };");
+ const v8::HeapSnapshot* snapshot =
+ v8::HeapProfiler::TakeSnapshot(v8_str("value"));
+ const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
+ CHECK(global->GetHeapValue()->IsObject());
+ v8::Local<v8::Object> js_global =
+ env->Global()->GetPrototype().As<v8::Object>();
+ CHECK(js_global == global->GetHeapValue());
+ const v8::HeapGraphNode* obj = GetProperty(
+ global, v8::HeapGraphEdge::kShortcut, "a");
+ CHECK(obj->GetHeapValue()->IsObject());
+ v8::Local<v8::Object> js_obj = js_global->Get(v8_str("a")).As<v8::Object>();
+ CHECK(js_obj == obj->GetHeapValue());
+ const v8::HeapGraphNode* s_prop =
+ GetProperty(obj, v8::HeapGraphEdge::kProperty, "s_prop");
+ v8::Local<v8::String> js_s_prop =
+ js_obj->Get(v8_str("s_prop")).As<v8::String>();
+ CHECK(js_s_prop == s_prop->GetHeapValue());
+ const v8::HeapGraphNode* n_prop =
+ GetProperty(obj, v8::HeapGraphEdge::kProperty, "n_prop");
+ v8::Local<v8::Number> js_n_prop =
+ js_obj->Get(v8_str("n_prop")).As<v8::Number>();
+ CHECK(js_n_prop == n_prop->GetHeapValue());
+}
+
+
+TEST(GetHeapValueForDeletedObject) {
+ v8::HandleScope scope;
+ LocalContext env;
+
+ // It is impossible to delete a global property, so we are about to delete a
+ // property of the "a" object. Also, the "p" object can't be an empty one
+ // because the empty object is static and isn't actually deleted.
+ CompileRun("a = { p: { r: {} } };");
+ const v8::HeapSnapshot* snapshot =
+ v8::HeapProfiler::TakeSnapshot(v8_str("snapshot"));
+ const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
+ const v8::HeapGraphNode* obj = GetProperty(
+ global, v8::HeapGraphEdge::kShortcut, "a");
+ const v8::HeapGraphNode* prop = GetProperty(
+ obj, v8::HeapGraphEdge::kProperty, "p");
+ {
+ // Perform the check inside a nested local scope to avoid creating a
+ // reference to the object we are deleting.
+ v8::HandleScope scope;
+ CHECK(prop->GetHeapValue()->IsObject());
+ }
+ CompileRun("delete a.p;");
+ CHECK(prop->GetHeapValue()->IsUndefined());
+}
+
+
+static int StringCmp(const char* ref, i::String* act) {
+ i::SmartPointer<char> s_act = act->ToCString();
+ int result = strcmp(ref, *s_act);
+ if (result != 0)
+ fprintf(stderr, "Expected: \"%s\", Actual: \"%s\"\n", ref, *s_act);
+ return result;
+}
+
+
+TEST(GetConstructorName) {
+ v8::HandleScope scope;
+ LocalContext env;
+
+ CompileRun(
+ "function Constructor1() {};\n"
+ "var obj1 = new Constructor1();\n"
+ "var Constructor2 = function() {};\n"
+ "var obj2 = new Constructor2();\n"
+ "var obj3 = {};\n"
+ "obj3.constructor = function Constructor3() {};\n"
+ "var obj4 = {};\n"
+ "// Slow properties\n"
+ "for (var i=0; i<2000; ++i) obj4[\"p\" + i] = i;\n"
+ "obj4.constructor = function Constructor4() {};\n"
+ "var obj5 = {};\n"
+ "var obj6 = {};\n"
+ "obj6.constructor = 6;");
+ v8::Local<v8::Object> js_global =
+ env->Global()->GetPrototype().As<v8::Object>();
+ v8::Local<v8::Object> obj1 = js_global->Get(v8_str("obj1")).As<v8::Object>();
+ i::Handle<i::JSObject> js_obj1 = v8::Utils::OpenHandle(*obj1);
+ CHECK_EQ(0, StringCmp(
+ "Constructor1", i::V8HeapExplorer::GetConstructorName(*js_obj1)));
+ v8::Local<v8::Object> obj2 = js_global->Get(v8_str("obj2")).As<v8::Object>();
+ i::Handle<i::JSObject> js_obj2 = v8::Utils::OpenHandle(*obj2);
+ CHECK_EQ(0, StringCmp(
+ "Constructor2", i::V8HeapExplorer::GetConstructorName(*js_obj2)));
+ v8::Local<v8::Object> obj3 = js_global->Get(v8_str("obj3")).As<v8::Object>();
+ i::Handle<i::JSObject> js_obj3 = v8::Utils::OpenHandle(*obj3);
+ CHECK_EQ(0, StringCmp(
+ "Constructor3", i::V8HeapExplorer::GetConstructorName(*js_obj3)));
+ v8::Local<v8::Object> obj4 = js_global->Get(v8_str("obj4")).As<v8::Object>();
+ i::Handle<i::JSObject> js_obj4 = v8::Utils::OpenHandle(*obj4);
+ CHECK_EQ(0, StringCmp(
+ "Constructor4", i::V8HeapExplorer::GetConstructorName(*js_obj4)));
+ v8::Local<v8::Object> obj5 = js_global->Get(v8_str("obj5")).As<v8::Object>();
+ i::Handle<i::JSObject> js_obj5 = v8::Utils::OpenHandle(*obj5);
+ CHECK_EQ(0, StringCmp(
+ "Object", i::V8HeapExplorer::GetConstructorName(*js_obj5)));
+ v8::Local<v8::Object> obj6 = js_global->Get(v8_str("obj6")).As<v8::Object>();
+ i::Handle<i::JSObject> js_obj6 = v8::Utils::OpenHandle(*obj6);
+ CHECK_EQ(0, StringCmp(
+ "Object", i::V8HeapExplorer::GetConstructorName(*js_obj6)));
+}
diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
index fac9f0a..11b8813 100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -291,8 +291,8 @@
TEST(GlobalHandles) {
- GlobalHandles* global_handles = Isolate::Current()->global_handles();
InitializeVM();
+ GlobalHandles* global_handles = Isolate::Current()->global_handles();
Handle<Object> h1;
Handle<Object> h2;
@@ -339,8 +339,8 @@
TEST(WeakGlobalHandlesScavenge) {
- GlobalHandles* global_handles = Isolate::Current()->global_handles();
InitializeVM();
+ GlobalHandles* global_handles = Isolate::Current()->global_handles();
WeakPointerCleared = false;
@@ -377,8 +377,8 @@
TEST(WeakGlobalHandlesMark) {
- GlobalHandles* global_handles = Isolate::Current()->global_handles();
InitializeVM();
+ GlobalHandles* global_handles = Isolate::Current()->global_handles();
WeakPointerCleared = false;
@@ -416,8 +416,8 @@
}
TEST(DeleteWeakGlobalHandle) {
- GlobalHandles* global_handles = Isolate::Current()->global_handles();
InitializeVM();
+ GlobalHandles* global_handles = Isolate::Current()->global_handles();
WeakPointerCleared = false;
diff --git a/test/cctest/test-list.cc b/test/cctest/test-list.cc
index e20ee8a..7520b05 100644
--- a/test/cctest/test-list.cc
+++ b/test/cctest/test-list.cc
@@ -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:
@@ -138,3 +138,14 @@
list.Clear();
CHECK_EQ(0, list.length());
}
+
+
+TEST(DeleteEmpty) {
+ {
+ List<int>* list = new List<int>(0);
+ delete list;
+ }
+ {
+ List<int> list(0);
+ }
+}
diff --git a/test/cctest/test-lockers.cc b/test/cctest/test-lockers.cc
index 2b184e9..d61fde2 100644
--- a/test/cctest/test-lockers.cc
+++ b/test/cctest/test-lockers.cc
@@ -54,10 +54,6 @@
using ::v8::Value;
using ::v8::V8;
-namespace i = ::i;
-
-
-
// Migrating an isolate
class KangarooThread : public v8::internal::Thread {
diff --git a/test/cctest/test-log-stack-tracer.cc b/test/cctest/test-log-stack-tracer.cc
index 2bcb3fe..f536e6b 100644
--- a/test/cctest/test-log-stack-tracer.cc
+++ b/test/cctest/test-log-stack-tracer.cc
@@ -54,8 +54,6 @@
using v8::internal::StackTracer;
using v8::internal::TickSample;
-namespace i = v8::internal;
-
static v8::Persistent<v8::Context> env;
diff --git a/test/cctest/test-log.cc b/test/cctest/test-log.cc
index 262e7bb..dfbc733 100644
--- a/test/cctest/test-log.cc
+++ b/test/cctest/test-log.cc
@@ -23,8 +23,6 @@
using v8::internal::Logger;
using v8::internal::StrLength;
-namespace i = v8::internal;
-
namespace {
class ScopedLoggerInitializer {
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
index 96a181d..8b6afdc 100755
--- a/test/cctest/test-parsing.cc
+++ b/test/cctest/test-parsing.cc
@@ -40,9 +40,7 @@
#include "preparser.h"
#include "cctest.h"
-namespace i = ::v8::internal;
-
-TEST(KeywordMatcher) {
+TEST(ScanKeywords) {
struct KeywordToken {
const char* keyword;
i::Token::Value token;
@@ -50,90 +48,64 @@
static const KeywordToken keywords[] = {
#define KEYWORD(t, s, d) { s, i::Token::t },
-#define IGNORE(t, s, d) /* */
- TOKEN_LIST(IGNORE, KEYWORD, IGNORE)
+ TOKEN_LIST(IGNORE_TOKEN, KEYWORD)
#undef KEYWORD
{ NULL, i::Token::IDENTIFIER }
};
- static const char* future_keywords[] = {
-#define FUTURE(t, s, d) s,
- TOKEN_LIST(IGNORE, IGNORE, FUTURE)
-#undef FUTURE
-#undef IGNORE
- NULL
- };
-
KeywordToken key_token;
+ i::UnicodeCache unicode_cache;
+ i::byte buffer[32];
for (int i = 0; (key_token = keywords[i]).keyword != NULL; i++) {
- i::KeywordMatcher matcher;
- const char* keyword = key_token.keyword;
- int length = i::StrLength(keyword);
- for (int j = 0; j < length; j++) {
- if (key_token.token == i::Token::INSTANCEOF && j == 2) {
- // "in" is a prefix of "instanceof". It's the only keyword
- // that is a prefix of another.
- CHECK_EQ(i::Token::IN, matcher.token());
- } else {
- CHECK_EQ(i::Token::IDENTIFIER, matcher.token());
- }
- matcher.AddChar(keyword[j]);
+ const i::byte* keyword =
+ reinterpret_cast<const i::byte*>(key_token.keyword);
+ int length = i::StrLength(key_token.keyword);
+ CHECK(static_cast<int>(sizeof(buffer)) >= length);
+ {
+ i::Utf8ToUC16CharacterStream stream(keyword, length);
+ i::JavaScriptScanner scanner(&unicode_cache);
+ // The scanner should parse 'let' as Token::LET for this test.
+ scanner.SetHarmonyBlockScoping(true);
+ scanner.Initialize(&stream);
+ CHECK_EQ(key_token.token, scanner.Next());
+ CHECK_EQ(i::Token::EOS, scanner.Next());
}
- CHECK_EQ(key_token.token, matcher.token());
- // Adding more characters will make keyword matching fail.
- matcher.AddChar('z');
- CHECK_EQ(i::Token::IDENTIFIER, matcher.token());
- // Adding a keyword later will not make it match again.
- matcher.AddChar('i');
- matcher.AddChar('f');
- CHECK_EQ(i::Token::IDENTIFIER, matcher.token());
- }
-
- // Future keywords are not recognized.
- const char* future_keyword;
- for (int i = 0; (future_keyword = future_keywords[i]) != NULL; i++) {
- i::KeywordMatcher matcher;
- int length = i::StrLength(future_keyword);
- for (int j = 0; j < length; j++) {
- matcher.AddChar(future_keyword[j]);
+ // Removing characters will make keyword matching fail.
+ {
+ i::Utf8ToUC16CharacterStream stream(keyword, length - 1);
+ i::JavaScriptScanner scanner(&unicode_cache);
+ scanner.Initialize(&stream);
+ CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
+ CHECK_EQ(i::Token::EOS, scanner.Next());
}
- CHECK_EQ(i::Token::IDENTIFIER, matcher.token());
+ // Adding characters will make keyword matching fail.
+ static const char chars_to_append[] = { 'z', '0', '_' };
+ for (int j = 0; j < static_cast<int>(ARRAY_SIZE(chars_to_append)); ++j) {
+ memmove(buffer, keyword, length);
+ buffer[length] = chars_to_append[j];
+ i::Utf8ToUC16CharacterStream stream(buffer, length + 1);
+ i::JavaScriptScanner scanner(&unicode_cache);
+ scanner.Initialize(&stream);
+ CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
+ CHECK_EQ(i::Token::EOS, scanner.Next());
+ }
+ // Replacing characters will make keyword matching fail.
+ {
+ memmove(buffer, keyword, length);
+ buffer[length - 1] = '_';
+ i::Utf8ToUC16CharacterStream stream(buffer, length);
+ i::JavaScriptScanner scanner(&unicode_cache);
+ scanner.Initialize(&stream);
+ CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
+ CHECK_EQ(i::Token::EOS, scanner.Next());
+ }
}
-
- // Zero isn't ignored at first.
- i::KeywordMatcher bad_start;
- bad_start.AddChar(0);
- CHECK_EQ(i::Token::IDENTIFIER, bad_start.token());
- bad_start.AddChar('i');
- bad_start.AddChar('f');
- CHECK_EQ(i::Token::IDENTIFIER, bad_start.token());
-
- // Zero isn't ignored at end.
- i::KeywordMatcher bad_end;
- bad_end.AddChar('i');
- bad_end.AddChar('f');
- CHECK_EQ(i::Token::IF, bad_end.token());
- bad_end.AddChar(0);
- CHECK_EQ(i::Token::IDENTIFIER, bad_end.token());
-
- // Case isn't ignored.
- i::KeywordMatcher bad_case;
- bad_case.AddChar('i');
- bad_case.AddChar('F');
- CHECK_EQ(i::Token::IDENTIFIER, bad_case.token());
-
- // If we mark it as failure, continuing won't help.
- i::KeywordMatcher full_stop;
- full_stop.AddChar('i');
- CHECK_EQ(i::Token::IDENTIFIER, full_stop.token());
- full_stop.Fail();
- CHECK_EQ(i::Token::IDENTIFIER, full_stop.token());
- full_stop.AddChar('f');
- CHECK_EQ(i::Token::IDENTIFIER, full_stop.token());
}
TEST(ScanHTMLEndComments) {
+ v8::V8::Initialize();
+
// Regression test. See:
// http://code.google.com/p/chromium/issues/detail?id=53548
// Tests that --> is correctly interpreted as comment-to-end-of-line if there
@@ -263,6 +235,8 @@
TEST(StandAlonePreParser) {
+ v8::V8::Initialize();
+
int marker;
i::Isolate::Current()->stack_guard()->SetStackLimit(
reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
@@ -299,6 +273,8 @@
TEST(RegressChromium62639) {
+ v8::V8::Initialize();
+
int marker;
i::Isolate::Current()->stack_guard()->SetStackLimit(
reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
@@ -313,13 +289,15 @@
i::Utf8ToUC16CharacterStream stream(reinterpret_cast<const i::byte*>(program),
static_cast<unsigned>(strlen(program)));
i::ScriptDataImpl* data =
- i::ParserApi::PreParse(&stream, NULL);
+ i::ParserApi::PreParse(&stream, NULL, false);
CHECK(data->HasError());
delete data;
}
TEST(Regress928) {
+ v8::V8::Initialize();
+
// Preparsing didn't consider the catch clause of a try statement
// as with-content, which made it assume that a function inside
// the block could be lazily compiled, and an extra, unexpected,
@@ -335,7 +313,7 @@
i::Utf8ToUC16CharacterStream stream(reinterpret_cast<const i::byte*>(program),
static_cast<unsigned>(strlen(program)));
i::ScriptDataImpl* data =
- i::ParserApi::PartialPreParse(&stream, NULL);
+ i::ParserApi::PartialPreParse(&stream, NULL, false);
CHECK(!data->HasError());
data->Initialize();
@@ -360,6 +338,8 @@
TEST(PreParseOverflow) {
+ v8::V8::Initialize();
+
int marker;
i::Isolate::Current()->stack_guard()->SetStackLimit(
reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
@@ -610,6 +590,8 @@
}
TEST(StreamScanner) {
+ v8::V8::Initialize();
+
const char* str1 = "{ foo get for : */ <- \n\n /*foo*/ bib";
i::Utf8ToUC16CharacterStream stream1(reinterpret_cast<const i::byte*>(str1),
static_cast<unsigned>(strlen(str1)));
@@ -690,6 +672,8 @@
TEST(RegExpScanning) {
+ v8::V8::Initialize();
+
// RegExp token with added garbage at the end. The scanner should only
// scan the RegExp until the terminating slash just before "flipperwald".
TestScanRegExp("/b/flipperwald", "b");
diff --git a/test/cctest/test-profile-generator.cc b/test/cctest/test-profile-generator.cc
index 6d30443..250ebd4 100644
--- a/test/cctest/test-profile-generator.cc
+++ b/test/cctest/test-profile-generator.cc
@@ -7,8 +7,6 @@
#include "cctest.h"
#include "../include/v8-profiler.h"
-namespace i = v8::internal;
-
using i::CodeEntry;
using i::CodeMap;
using i::CpuProfile;
diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc
index 730d72a..8e85444 100644
--- a/test/cctest/test-serialize.cc
+++ b/test/cctest/test-serialize.cc
@@ -99,10 +99,10 @@
TEST(ExternalReferenceEncoder) {
- OS::Setup();
Isolate* isolate = i::Isolate::Current();
isolate->stats_table()->SetCounterFunction(counter_function);
- HEAP->Setup(false);
+ v8::V8::Initialize();
+
ExternalReferenceEncoder encoder;
CHECK_EQ(make_code(BUILTIN, Builtins::kArrayCode),
Encode(encoder, Builtins::kArrayCode));
@@ -139,10 +139,10 @@
TEST(ExternalReferenceDecoder) {
- OS::Setup();
Isolate* isolate = i::Isolate::Current();
isolate->stats_table()->SetCounterFunction(counter_function);
- HEAP->Setup(false);
+ v8::V8::Initialize();
+
ExternalReferenceDecoder decoder;
CHECK_EQ(AddressOf(Builtins::kArrayCode),
decoder.Decode(make_code(BUILTIN, Builtins::kArrayCode)));
@@ -459,7 +459,9 @@
CHECK(root->IsString());
}
v8::HandleScope handle_scope;
- Handle<Object>root_handle(root);
+ Handle<Object> root_handle(root);
+
+ ReserveSpaceForPartialSnapshot(file_name);
Object* root2;
{
@@ -542,7 +544,9 @@
CHECK(root->IsContext());
}
v8::HandleScope handle_scope;
- Handle<Object>root_handle(root);
+ Handle<Object> root_handle(root);
+
+ ReserveSpaceForPartialSnapshot(file_name);
Object* root2;
{
diff --git a/test/cctest/test-spaces.cc b/test/cctest/test-spaces.cc
index de0c41e..0f22ce1 100644
--- a/test/cctest/test-spaces.cc
+++ b/test/cctest/test-spaces.cc
@@ -91,46 +91,74 @@
}
+namespace v8 {
+namespace internal {
+
+// Temporarily sets a given allocator in an isolate.
+class TestMemoryAllocatorScope {
+ public:
+ TestMemoryAllocatorScope(Isolate* isolate, MemoryAllocator* allocator)
+ : isolate_(isolate),
+ old_allocator_(isolate->memory_allocator_) {
+ isolate->memory_allocator_ = allocator;
+ }
+
+ ~TestMemoryAllocatorScope() {
+ isolate_->memory_allocator_ = old_allocator_;
+ }
+
+ private:
+ Isolate* isolate_;
+ MemoryAllocator* old_allocator_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestMemoryAllocatorScope);
+};
+
+} } // namespace v8::internal
+
+
TEST(MemoryAllocator) {
OS::Setup();
Isolate* isolate = Isolate::Current();
- CHECK(HEAP->ConfigureHeapDefault());
- CHECK(isolate->memory_allocator()->Setup(HEAP->MaxReserved(),
- HEAP->MaxExecutableSize()));
+ isolate->InitializeLoggingAndCounters();
+ Heap* heap = isolate->heap();
+ CHECK(heap->ConfigureHeapDefault());
+ MemoryAllocator* memory_allocator = new MemoryAllocator(isolate);
+ CHECK(memory_allocator->Setup(heap->MaxReserved(),
+ heap->MaxExecutableSize()));
+ TestMemoryAllocatorScope test_scope(isolate, memory_allocator);
- OldSpace faked_space(HEAP,
- HEAP->MaxReserved(),
+ 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 =
- isolate->memory_allocator()->AllocatePages(
- requested, &allocated, &faked_space);
+ 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* last_page = first_page;
for (Page* p = first_page; p->is_valid(); p = p->next_page()) {
- CHECK(isolate->memory_allocator()->IsPageInSpace(p, &faked_space));
+ CHECK(memory_allocator->IsPageInSpace(p, &faked_space));
last_page = p;
}
// Again, we should get n or n - 1 pages.
- Page* others =
- isolate->memory_allocator()->AllocatePages(
- requested, &allocated, &faked_space);
+ Page* others = memory_allocator->AllocatePages(
+ requested, &allocated, &faked_space);
CHECK(others->is_valid());
CHECK(allocated == requested || allocated == requested - 1);
total_pages += allocated;
- isolate->memory_allocator()->SetNextPage(last_page, others);
+ memory_allocator->SetNextPage(last_page, others);
int page_count = 0;
for (Page* p = first_page; p->is_valid(); p = p->next_page()) {
- CHECK(isolate->memory_allocator()->IsPageInSpace(p, &faked_space));
+ CHECK(memory_allocator->IsPageInSpace(p, &faked_space));
page_count++;
}
CHECK(total_pages == page_count);
@@ -141,34 +169,39 @@
// 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 = isolate->memory_allocator()->FreePages(second_page);
+ Page* free_return = memory_allocator->FreePages(second_page);
CHECK(free_return == second_page);
- isolate->memory_allocator()->SetNextPage(first_page, free_return);
+ 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 = isolate->memory_allocator()->FreePages(first_page);
+ Page* invalid_page = memory_allocator->FreePages(first_page);
CHECK(!invalid_page->is_valid());
- isolate->memory_allocator()->TearDown();
+ memory_allocator->TearDown();
+ delete memory_allocator;
}
TEST(NewSpace) {
OS::Setup();
- CHECK(HEAP->ConfigureHeapDefault());
- CHECK(Isolate::Current()->memory_allocator()->Setup(
- HEAP->MaxReserved(), HEAP->MaxExecutableSize()));
+ Isolate* isolate = Isolate::Current();
+ isolate->InitializeLoggingAndCounters();
+ Heap* heap = isolate->heap();
+ CHECK(heap->ConfigureHeapDefault());
+ MemoryAllocator* memory_allocator = new MemoryAllocator(isolate);
+ CHECK(memory_allocator->Setup(heap->MaxReserved(),
+ heap->MaxExecutableSize()));
+ TestMemoryAllocatorScope test_scope(isolate, memory_allocator);
- NewSpace new_space(HEAP);
+ NewSpace new_space(heap);
void* chunk =
- Isolate::Current()->memory_allocator()->ReserveInitialChunk(
- 4 * HEAP->ReservedSemiSpaceSize());
+ 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()));
+ 2 * heap->ReservedSemiSpaceSize());
+ CHECK(new_space.Setup(start, 2 * heap->ReservedSemiSpaceSize()));
CHECK(new_space.HasBeenSetup());
while (new_space.Available() >= Page::kMaxHeapObjectSize) {
@@ -178,28 +211,33 @@
}
new_space.TearDown();
- Isolate::Current()->memory_allocator()->TearDown();
+ memory_allocator->TearDown();
+ delete memory_allocator;
}
TEST(OldSpace) {
OS::Setup();
- CHECK(HEAP->ConfigureHeapDefault());
- CHECK(Isolate::Current()->memory_allocator()->Setup(
- HEAP->MaxReserved(), HEAP->MaxExecutableSize()));
+ Isolate* isolate = Isolate::Current();
+ isolate->InitializeLoggingAndCounters();
+ Heap* heap = isolate->heap();
+ CHECK(heap->ConfigureHeapDefault());
+ MemoryAllocator* memory_allocator = new MemoryAllocator(isolate);
+ CHECK(memory_allocator->Setup(heap->MaxReserved(),
+ heap->MaxExecutableSize()));
+ TestMemoryAllocatorScope test_scope(isolate, memory_allocator);
- OldSpace* s = new OldSpace(HEAP,
- HEAP->MaxOldGenerationSize(),
+ OldSpace* s = new OldSpace(heap,
+ heap->MaxOldGenerationSize(),
OLD_POINTER_SPACE,
NOT_EXECUTABLE);
CHECK(s != NULL);
- void* chunk =
- Isolate::Current()->memory_allocator()->ReserveInitialChunk(
- 4 * HEAP->ReservedSemiSpaceSize());
+ 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;
+ size_t size = RoundUp(start, 2 * heap->ReservedSemiSpaceSize()) - start;
CHECK(s->Setup(start, size));
@@ -209,13 +247,13 @@
s->TearDown();
delete s;
- Isolate::Current()->memory_allocator()->TearDown();
+ memory_allocator->TearDown();
+ delete memory_allocator;
}
TEST(LargeObjectSpace) {
- OS::Setup();
- CHECK(HEAP->Setup(false));
+ v8::V8::Initialize();
LargeObjectSpace* lo = HEAP->lo_space();
CHECK(lo != NULL);
@@ -247,9 +285,4 @@
CHECK(!lo->IsEmpty());
CHECK(lo->AllocateRaw(lo_size)->IsFailure());
-
- lo->TearDown();
- delete lo;
-
- Isolate::Current()->memory_allocator()->TearDown();
}
diff --git a/test/cctest/test-strings.cc b/test/cctest/test-strings.cc
index 4d9b264..17020a3 100644
--- a/test/cctest/test-strings.cc
+++ b/test/cctest/test-strings.cc
@@ -430,8 +430,7 @@
" return 0;"
"};"
"test()";
- CHECK_EQ(0,
- v8::Script::Compile(v8::String::New(source))->Run()->Int32Value());
+ CHECK_EQ(0, CompileRun(source)->Int32Value());
}
@@ -481,3 +480,52 @@
}
}
}
+
+
+TEST(SliceFromCons) {
+ FLAG_string_slices = true;
+ InitializeVM();
+ v8::HandleScope scope;
+ Handle<String> string =
+ FACTORY->NewStringFromAscii(CStrVector("parentparentparent"));
+ Handle<String> parent = FACTORY->NewConsString(string, string);
+ CHECK(parent->IsConsString());
+ CHECK(!parent->IsFlat());
+ Handle<String> slice = FACTORY->NewSubString(parent, 1, 25);
+ // After slicing, the original string becomes a flat cons.
+ CHECK(parent->IsFlat());
+ CHECK(slice->IsSlicedString());
+ CHECK_EQ(SlicedString::cast(*slice)->parent(),
+ ConsString::cast(*parent)->first());
+ CHECK(SlicedString::cast(*slice)->parent()->IsSeqString());
+ CHECK(slice->IsFlat());
+}
+
+
+TEST(TrivialSlice) {
+ // This tests whether a slice that contains the entire parent string
+ // actually creates a new string (it should not).
+ FLAG_string_slices = true;
+ InitializeVM();
+ HandleScope scope;
+ v8::Local<v8::Value> result;
+ Handle<String> string;
+ const char* init = "var str = 'abcdefghijklmnopqrstuvwxyz';";
+ const char* check = "str.slice(0,26)";
+ const char* crosscheck = "str.slice(1,25)";
+
+ CompileRun(init);
+
+ result = CompileRun(check);
+ CHECK(result->IsString());
+ string = v8::Utils::OpenHandle(v8::String::Cast(*result));
+ CHECK(!string->IsSlicedString());
+
+ string = FACTORY->NewSubString(string, 0, 26);
+ CHECK(!string->IsSlicedString());
+ result = CompileRun(crosscheck);
+ CHECK(result->IsString());
+ string = v8::Utils::OpenHandle(v8::String::Cast(*result));
+ CHECK(string->IsSlicedString());
+ CHECK_EQ("bcdefghijklmnopqrstuvwxy", *(string->ToCString()));
+}
diff --git a/test/cctest/test-unbound-queue.cc b/test/cctest/test-unbound-queue.cc
index df5509e..3dc87ae 100644
--- a/test/cctest/test-unbound-queue.cc
+++ b/test/cctest/test-unbound-queue.cc
@@ -6,8 +6,6 @@
#include "unbound-queue-inl.h"
#include "cctest.h"
-namespace i = v8::internal;
-
using i::UnboundQueue;
diff --git a/test/cctest/test-weakmaps.cc b/test/cctest/test-weakmaps.cc
new file mode 100644
index 0000000..db4db25
--- /dev/null
+++ b/test/cctest/test-weakmaps.cc
@@ -0,0 +1,149 @@
+// 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.
+
+#include "v8.h"
+
+#include "global-handles.h"
+#include "snapshot.h"
+#include "cctest.h"
+
+using namespace v8::internal;
+
+
+static Handle<JSWeakMap> AllocateJSWeakMap() {
+ Handle<Map> map = FACTORY->NewMap(JS_WEAK_MAP_TYPE, JSWeakMap::kSize);
+ Handle<JSObject> weakmap_obj = FACTORY->NewJSObjectFromMap(map);
+ Handle<JSWeakMap> weakmap(JSWeakMap::cast(*weakmap_obj));
+ // Do not use handles for the hash table, it would make entries strong.
+ Object* table_obj = ObjectHashTable::Allocate(1)->ToObjectChecked();
+ ObjectHashTable* table = ObjectHashTable::cast(table_obj);
+ weakmap->set_table(table);
+ weakmap->set_next(Smi::FromInt(0));
+ return weakmap;
+}
+
+static void PutIntoWeakMap(Handle<JSWeakMap> weakmap,
+ Handle<JSObject> key,
+ int value) {
+ Handle<ObjectHashTable> table = PutIntoObjectHashTable(
+ Handle<ObjectHashTable>(weakmap->table()),
+ Handle<JSObject>(JSObject::cast(*key)),
+ Handle<Smi>(Smi::FromInt(value)));
+ weakmap->set_table(*table);
+}
+
+static int NumberOfWeakCalls = 0;
+static void WeakPointerCallback(v8::Persistent<v8::Value> handle, void* id) {
+ ASSERT(id == reinterpret_cast<void*>(1234));
+ NumberOfWeakCalls++;
+ handle.Dispose();
+}
+
+
+TEST(Weakness) {
+ LocalContext context;
+ v8::HandleScope scope;
+ Handle<JSWeakMap> weakmap = AllocateJSWeakMap();
+ GlobalHandles* global_handles = Isolate::Current()->global_handles();
+
+ // Keep global reference to the key.
+ Handle<Object> key;
+ {
+ v8::HandleScope scope;
+ Handle<Map> map = FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
+ Handle<JSObject> object = FACTORY->NewJSObjectFromMap(map);
+ key = global_handles->Create(*object);
+ }
+ CHECK(!global_handles->IsWeak(key.location()));
+
+ // Put entry into weak map.
+ {
+ v8::HandleScope scope;
+ PutIntoWeakMap(weakmap, Handle<JSObject>(JSObject::cast(*key)), 23);
+ }
+ CHECK_EQ(1, 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());
+
+ // Make the global reference to the key weak.
+ {
+ v8::HandleScope scope;
+ global_handles->MakeWeak(key.location(),
+ reinterpret_cast<void*>(1234),
+ &WeakPointerCallback);
+ }
+ CHECK(global_handles->IsWeak(key.location()));
+
+ // Force a full GC.
+ // Perform two consecutive GCs because the first one will only clear
+ // 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());
+ HEAP->CollectAllGarbage(false);
+ CHECK_EQ(1, NumberOfWeakCalls);
+ CHECK_EQ(0, weakmap->table()->NumberOfElements());
+ CHECK_EQ(1, weakmap->table()->NumberOfDeletedElements());
+}
+
+
+TEST(Shrinking) {
+ LocalContext context;
+ v8::HandleScope scope;
+ Handle<JSWeakMap> weakmap = AllocateJSWeakMap();
+
+ // Check initial capacity.
+ CHECK_EQ(32, weakmap->table()->Capacity());
+
+ // Fill up weak map to trigger capacity change.
+ {
+ v8::HandleScope scope;
+ Handle<Map> map = FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
+ for (int i = 0; i < 32; i++) {
+ Handle<JSObject> object = FACTORY->NewJSObjectFromMap(map);
+ PutIntoWeakMap(weakmap, object, i);
+ }
+ }
+
+ // Check increased capacity.
+ CHECK_EQ(128, weakmap->table()->Capacity());
+
+ // Force a full GC.
+ CHECK_EQ(32, weakmap->table()->NumberOfElements());
+ CHECK_EQ(0, weakmap->table()->NumberOfDeletedElements());
+ HEAP->CollectAllGarbage(false);
+ CHECK_EQ(0, weakmap->table()->NumberOfElements());
+ CHECK_EQ(32, weakmap->table()->NumberOfDeletedElements());
+
+ // Check shrunk capacity.
+ CHECK_EQ(32, weakmap->table()->Capacity());
+}
diff --git a/test/cctest/testcfg.py b/test/cctest/testcfg.py
index a137275..b2eabc4 100644
--- a/test/cctest/testcfg.py
+++ b/test/cctest/testcfg.py
@@ -48,7 +48,11 @@
return self.path[-1]
def BuildCommand(self, name):
- serialization_file = join('obj', 'test', self.mode, 'serdes')
+ serialization_file = ''
+ if exists(join(self.context.buildspace, 'obj', 'test', self.mode)):
+ serialization_file = join('obj', 'test', self.mode, 'serdes')
+ else:
+ serialization_file = join('obj', 'serdes')
serialization_file += '_' + self.GetName()
serialization_file = join(self.context.buildspace, serialization_file)
serialization_file += ''.join(self.variant_flags).replace('-', '_')
@@ -78,10 +82,15 @@
return ['cctests']
def ListTests(self, current_path, path, mode, variant_flags):
- executable = join('obj', 'test', mode, 'cctest')
+ executable = 'cctest'
if utils.IsWindows():
executable += '.exe'
executable = join(self.context.buildspace, executable)
+ if not exists(executable):
+ executable = join('obj', 'test', mode, 'cctest')
+ if utils.IsWindows():
+ executable += '.exe'
+ executable = join(self.context.buildspace, executable)
output = test.Execute([executable, '--list'], self.context)
if output.exit_code != 0:
print output.stdout
diff --git a/test/es5conform/testcfg.py b/test/es5conform/testcfg.py
index af74b8c..b6a17d9 100644
--- a/test/es5conform/testcfg.py
+++ b/test/es5conform/testcfg.py
@@ -97,7 +97,7 @@
return tests
def GetBuildRequirements(self):
- return ['sample', 'sample=shell']
+ return ['d8']
def GetTestStatus(self, sections, defs):
status_file = join(self.root, 'es5conform.status')
diff --git a/test/message/testcfg.py b/test/message/testcfg.py
index aabbfef..af467e6 100644
--- a/test/message/testcfg.py
+++ b/test/message/testcfg.py
@@ -125,7 +125,7 @@
return result
def GetBuildRequirements(self):
- return ['sample', 'sample=shell']
+ return ['d8']
def GetTestStatus(self, sections, defs):
status_file = join(self.root, 'message.status')
diff --git a/test/mjsunit/assert-opt-and-deopt.js b/test/mjsunit/assert-opt-and-deopt.js
index f589868..c9adb5b 100644
--- a/test/mjsunit/assert-opt-and-deopt.js
+++ b/test/mjsunit/assert-opt-and-deopt.js
@@ -54,7 +54,7 @@
* that you later want to track de/optimizations for. It is necessary because
* tests are sometimes executed several times in a row, and you want to
* disregard counts from previous runs.
- */
+ */
OptTracker.prototype.CheckpointOptCount = function(func) {
this.opt_counts_[func] = %GetOptimizationCount(func);
};
@@ -148,7 +148,7 @@
tracker.AssertDeoptHappened(f, false);
tracker.AssertDeoptCount(f, 0);
-for (var i = 0; i < 2; i++) f(1);
+f(1);
tracker.AssertOptCount(f, 0);
tracker.AssertIsOptimized(f, false);
diff --git a/test/mjsunit/bugs/harmony/debug-blockscopes.js b/test/mjsunit/bugs/harmony/debug-blockscopes.js
new file mode 100644
index 0000000..a407c53
--- /dev/null
+++ b/test/mjsunit/bugs/harmony/debug-blockscopes.js
@@ -0,0 +1,224 @@
+// 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 --harmony-block-scoping
+// 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 test_name;
+var listener_delegate;
+var listener_called;
+var exception;
+var begin_test_count = 0;
+var end_test_count = 0;
+var break_count = 0;
+
+
+// Debug event listener which delegates.
+function listener(event, exec_state, event_data, data) {
+ try {
+ if (event == Debug.DebugEvent.Break) {
+ break_count++;
+ listener_called = true;
+ listener_delegate(exec_state);
+ }
+ } catch (e) {
+ exception = e;
+ }
+}
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+
+// Initialize for a new test.
+function BeginTest(name) {
+ test_name = name;
+ listener_delegate = null;
+ listener_called = false;
+ exception = null;
+ begin_test_count++;
+}
+
+
+// Check result of a test.
+function EndTest() {
+ assertTrue(listener_called, "listerner not called for " + test_name);
+ assertNull(exception, test_name);
+ end_test_count++;
+}
+
+
+// Check that the scope chain contains the expected types of scopes.
+function CheckScopeChain(scopes, exec_state) {
+ assertEquals(scopes.length, exec_state.frame().scopeCount());
+ for (var i = 0; i < scopes.length; i++) {
+ var scope = exec_state.frame().scope(i);
+ assertTrue(scope.isScope());
+ assertEquals(scopes[i], scope.scopeType());
+
+ // Check the global object when hitting the global scope.
+ 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());
+ }
+ }
+
+ // Get the debug command processor.
+ var dcp = exec_state.debugCommandProcessor("unspecified_running_state");
+
+ // Send a scopes request and check the result.
+ var json;
+ var request_json = '{"seq":0,"type":"request","command":"scopes"}';
+ var response_json = dcp.processDebugJSONRequest(request_json);
+ var response = JSON.parse(response_json);
+ assertEquals(scopes.length, response.body.scopes.length);
+ for (var i = 0; i < scopes.length; i++) {
+ assertEquals(i, response.body.scopes[i].index);
+ assertEquals(scopes[i], response.body.scopes[i].type);
+ if (scopes[i] == debug.ScopeType.Local ||
+ scopes[i] == debug.ScopeType.Closure) {
+ assertTrue(response.body.scopes[i].object.ref < 0);
+ } else {
+ assertTrue(response.body.scopes[i].object.ref >= 0);
+ }
+ var found = false;
+ for (var j = 0; j < response.refs.length && !found; j++) {
+ found = response.refs[j].handle == response.body.scopes[i].object.ref;
+ }
+ assertTrue(found, "Scope object " + response.body.scopes[i].object.ref + " not found");
+ }
+}
+
+// Check that the content of the scope is as expected. For functions just check
+// that there is a function.
+function CheckScopeContent(content, number, exec_state) {
+ var scope = exec_state.frame().scope(number);
+ var count = 0;
+ for (var p in content) {
+ var property_mirror = scope.scopeObject().property(p);
+ if (property_mirror.isUndefined()) {
+ print('property ' + p + ' not found in scope');
+ }
+ assertFalse(property_mirror.isUndefined(), 'property ' + p + ' not found in scope');
+ if (typeof(content[p]) === 'function') {
+ assertTrue(property_mirror.value().isFunction());
+ } else {
+ assertEquals(content[p], property_mirror.value().value(), 'property ' + p + ' has unexpected value');
+ }
+ count++;
+ }
+
+ // 'arguments' and might be exposed in the local and closure scope. Just
+ // ignore this.
+ var scope_size = scope.scopeObject().properties().length;
+ if (!scope.scopeObject().property('arguments').isUndefined()) {
+ scope_size--;
+ }
+ // Also ignore synthetic variable from catch block.
+ if (!scope.scopeObject().property('.catch-var').isUndefined()) {
+ scope_size--;
+ }
+ // Skip property with empty name.
+ if (!scope.scopeObject().property('').isUndefined()) {
+ scope_size--;
+ }
+ // Also ignore synthetic variable from block scopes.
+ if (!scope.scopeObject().property('.block').isUndefined()) {
+ scope_size--;
+ }
+
+ if (count != scope_size) {
+ print('Names found in scope:');
+ var names = scope.scopeObject().propertyNames();
+ for (var i = 0; i < names.length; i++) {
+ print(names[i]);
+ }
+ }
+ assertEquals(count, scope_size);
+
+ // Get the debug command processor.
+ var dcp = exec_state.debugCommandProcessor("unspecified_running_state");
+
+ // Send a scope request for information on a single scope and check the
+ // result.
+ var request_json = '{"seq":0,"type":"request","command":"scope","arguments":{"number":';
+ request_json += scope.scopeIndex();
+ request_json += '}}';
+ var response_json = dcp.processDebugJSONRequest(request_json);
+ var response = JSON.parse(response_json);
+ assertEquals(scope.scopeType(), response.body.type);
+ assertEquals(number, response.body.index);
+ if (scope.scopeType() == debug.ScopeType.Local ||
+ scope.scopeType() == debug.ScopeType.Closure) {
+ assertTrue(response.body.object.ref < 0);
+ } else {
+ assertTrue(response.body.object.ref >= 0);
+ }
+ var found = false;
+ for (var i = 0; i < response.refs.length && !found; i++) {
+ found = response.refs[i].handle == response.body.object.ref;
+ }
+ assertTrue(found, "Scope object " + response.body.object.ref + " not found");
+}
+
+
+// Simple closure formed by returning an inner function referering to an outer
+// block local variable and an outer function's parameter. Due to VM
+// optimizations parts of the actual closure is missing from the debugger
+// information.
+BeginTest("Closure 1");
+
+function closure_1(a) {
+ var x = 2;
+ let y = 3;
+ if (true) {
+ let z = 4;
+ function f() {
+ debugger;
+ return a + x + y + z;
+ };
+ return f;
+ }
+}
+
+listener_delegate = function(exec_state) {
+ CheckScopeChain([debug.ScopeType.Local,
+ debug.ScopeType.Block,
+ debug.ScopeType.Closure,
+ debug.ScopeType.Global], exec_state);
+ CheckScopeContent({}, 0, exec_state);
+ CheckScopeContent({z:4}, 1, exec_state);
+ CheckScopeContent({a:1,x:2,y:3}, 2, exec_state);
+};
+closure_1(1)();
+EndTest();
diff --git a/test/mjsunit/d8-os.js b/test/mjsunit/d8-os.js
index 630a39e..fd6fb77 100644
--- a/test/mjsunit/d8-os.js
+++ b/test/mjsunit/d8-os.js
@@ -30,6 +30,9 @@
// implemented on Windows, and even if it were then many of the things
// we are calling would not be available.
+var TEST_DIR = "d8-os-test-directory-" + ((Math.random() * (1<<30)) | 0);
+
+
function arg_error(str) {
try {
eval(str);
@@ -53,96 +56,98 @@
if (this.os && os.system) {
try {
// Delete the dir if it is lying around from last time.
- os.system("ls", ["d8-os-test-directory"]);
- os.system("rm", ["-r", "d8-os-test-directory"]);
+ os.system("ls", [TEST_DIR]);
+ os.system("rm", ["-r", TEST_DIR]);
} catch (e) {
}
- os.mkdirp("d8-os-test-directory");
- os.chdir("d8-os-test-directory");
- // Check the chdir worked.
- os.system('ls', ['../d8-os-test-directory']);
- // Simple create dir.
- os.mkdirp("dir");
- // Create dir in dir.
- os.mkdirp("dir/foo");
- // Check that they are there.
- os.system('ls', ['dir/foo']);
- // Check that we can detect when something is not there.
- assertThrows("os.system('ls', ['dir/bar']);", "dir not there");
- // Check that mkdirp makes intermediate directories.
- os.mkdirp("dir2/foo");
- os.system("ls", ["dir2/foo"]);
- // Check that mkdirp doesn't mind if the dir is already there.
- os.mkdirp("dir2/foo");
- os.mkdirp("dir2/foo/");
- // Check that mkdirp can cope with trailing /
- os.mkdirp("dir3/");
- os.system("ls", ["dir3"]);
- // Check that we get an error if the name is taken by a file.
- os.system("sh", ["-c", "echo foo > file1"]);
- os.system("ls", ["file1"]);
- assertThrows("os.mkdirp('file1');", "mkdir over file1");
- assertThrows("os.mkdirp('file1/foo');", "mkdir over file2");
- assertThrows("os.mkdirp('file1/');", "mkdir over file3");
- assertThrows("os.mkdirp('file1/foo/');", "mkdir over file4");
- // Create a dir we cannot read.
- os.mkdirp("dir4", 0);
- // This test fails if you are root since root can read any dir.
- assertThrows("os.chdir('dir4');", "chdir dir4 I");
- os.rmdir("dir4");
- assertThrows("os.chdir('dir4');", "chdir dir4 II");
- // Set umask.
- var old_umask = os.umask(0777);
- // Create a dir we cannot read.
- os.mkdirp("dir5");
- // This test fails if you are root since root can read any dir.
- assertThrows("os.chdir('dir5');", "cd dir5 I");
- os.rmdir("dir5");
- assertThrows("os.chdir('dir5');", "chdir dir5 II");
- os.umask(old_umask);
-
- os.mkdirp("hest/fisk/../fisk/ged");
- os.system("ls", ["hest/fisk/ged"]);
-
- os.setenv("FOO", "bar");
- var environment = os.system("printenv");
- assertTrue(/FOO=bar/.test(environment));
-
- // Check we time out.
- var have_sleep = true;
- var have_echo = true;
+ os.mkdirp(TEST_DIR);
+ os.chdir(TEST_DIR);
try {
- os.system("ls", ["/bin/sleep"]);
- } catch (e) {
- have_sleep = false;
- }
- try {
- os.system("ls", ["/bin/echo"]);
- } catch (e) {
- have_echo = false;
- }
- if (have_sleep) {
- assertThrows("os.system('sleep', ['2000'], 200);", "sleep 1");
+ // Check the chdir worked.
+ os.system('ls', ['../' + TEST_DIR]);
+ // Simple create dir.
+ os.mkdirp("dir");
+ // Create dir in dir.
+ os.mkdirp("dir/foo");
+ // Check that they are there.
+ os.system('ls', ['dir/foo']);
+ // Check that we can detect when something is not there.
+ assertThrows("os.system('ls', ['dir/bar']);", "dir not there");
+ // Check that mkdirp makes intermediate directories.
+ os.mkdirp("dir2/foo");
+ os.system("ls", ["dir2/foo"]);
+ // Check that mkdirp doesn't mind if the dir is already there.
+ os.mkdirp("dir2/foo");
+ os.mkdirp("dir2/foo/");
+ // Check that mkdirp can cope with trailing /
+ os.mkdirp("dir3/");
+ os.system("ls", ["dir3"]);
+ // Check that we get an error if the name is taken by a file.
+ os.system("sh", ["-c", "echo foo > file1"]);
+ os.system("ls", ["file1"]);
+ assertThrows("os.mkdirp('file1');", "mkdir over file1");
+ assertThrows("os.mkdirp('file1/foo');", "mkdir over file2");
+ assertThrows("os.mkdirp('file1/');", "mkdir over file3");
+ assertThrows("os.mkdirp('file1/foo/');", "mkdir over file4");
+ // Create a dir we cannot read.
+ os.mkdirp("dir4", 0);
+ // This test fails if you are root since root can read any dir.
+ assertThrows("os.chdir('dir4');", "chdir dir4 I");
+ os.rmdir("dir4");
+ assertThrows("os.chdir('dir4');", "chdir dir4 II");
+ // Set umask.
+ var old_umask = os.umask(0777);
+ // Create a dir we cannot read.
+ os.mkdirp("dir5");
+ // This test fails if you are root since root can read any dir.
+ assertThrows("os.chdir('dir5');", "cd dir5 I");
+ os.rmdir("dir5");
+ assertThrows("os.chdir('dir5');", "chdir dir5 II");
+ os.umask(old_umask);
- // Check we time out with total time.
- assertThrows("os.system('sleep', ['2000'], -1, 200);", "sleep 2");
+ os.mkdirp("hest/fisk/../fisk/ged");
+ os.system("ls", ["hest/fisk/ged"]);
- // Check that -1 means no timeout.
- os.system('sleep', ['1'], -1, -1);
+ os.setenv("FOO", "bar");
+ var environment = os.system("printenv");
+ assertTrue(/FOO=bar/.test(environment));
- }
+ // Check we time out.
+ var have_sleep = true;
+ var have_echo = true;
+ try {
+ os.system("ls", ["/bin/sleep"]);
+ } catch (e) {
+ have_sleep = false;
+ }
+ try {
+ os.system("ls", ["/bin/echo"]);
+ } catch (e) {
+ have_echo = false;
+ }
+ if (have_sleep) {
+ assertThrows("os.system('sleep', ['2000'], 200);", "sleep 1");
- // Check that we don't fill up the process table with zombies.
- // Disabled because it's too slow.
- if (have_echo) {
- //for (var i = 0; i < 65536; i++) {
+ // Check we time out with total time.
+ assertThrows("os.system('sleep', ['2000'], -1, 200);", "sleep 2");
+
+ // Check that -1 means no timeout.
+ os.system('sleep', ['1'], -1, -1);
+
+ }
+
+ // Check that we don't fill up the process table with zombies.
+ // Disabled because it's too slow.
+ if (have_echo) {
+ //for (var i = 0; i < 65536; i++) {
assertEquals("baz\n", os.system("echo", ["baz"]));
- //}
+ //}
+ }
+ } finally {
+ os.chdir("..");
+ os.system("rm", ["-r", TEST_DIR]);
}
- os.chdir("..");
- os.system("rm", ["-r", "d8-os-test-directory"]);
-
// Too few args.
arg_error("os.umask();");
arg_error("os.system();");
diff --git a/test/mjsunit/debug-script.js b/test/mjsunit/debug-script.js
index 643dd8c..9767888 100644
--- a/test/mjsunit/debug-script.js
+++ b/test/mjsunit/debug-script.js
@@ -34,13 +34,19 @@
// Count script types.
var named_native_count = 0;
+var named_native_names = {};
var extension_count = 0;
var normal_count = 0;
var scripts = Debug.scripts();
for (i = 0; i < scripts.length; i++) {
if (scripts[i].type == Debug.ScriptType.Native) {
if (scripts[i].name) {
- named_native_count++;
+ // TODO(1641): Remove check for equally named native scripts once the
+ // underlying issue is fixed.
+ if (!named_native_names[scripts[i].name]) {
+ named_native_names[scripts[i].name] = true;
+ named_native_count++;
+ }
}
} else if (scripts[i].type == Debug.ScriptType.Extension) {
extension_count++;
diff --git a/test/mjsunit/external-array.js b/test/mjsunit/external-array.js
index 94105ec..d7e9de0 100644
--- a/test/mjsunit/external-array.js
+++ b/test/mjsunit/external-array.js
@@ -190,9 +190,19 @@
gc(); // Makes V8 forget about type information for test_func.
}
+function run_bounds_test(test_func, array, expected_result) {
+ assertEquals(undefined, a[kElementCount]);
+ a[kElementCount] = 456;
+ assertEquals(undefined, a[kElementCount]);
+ assertEquals(undefined, a[kElementCount+1]);
+ a[kElementCount+1] = 456;
+ assertEquals(undefined, a[kElementCount+1]);
+}
+
for (var t = 0; t < types.length; t++) {
var type = types[t];
var a = new type(kElementCount);
+
for (var i = 0; i < kElementCount; i++) {
a[i] = i;
}
@@ -220,6 +230,16 @@
assertTrue(delete a.length);
a.length = 2;
assertEquals(2, a.length);
+
+ // Make sure bounds checks are handled correctly for external arrays.
+ run_bounds_test(a);
+ run_bounds_test(a);
+ run_bounds_test(a);
+ %OptimizeFunctionOnNextCall(run_bounds_test);
+ run_bounds_test(a);
+ %DeoptimizeFunction(run_bounds_test);
+ gc(); // Makes V8 forget about type information for test_func.
+
}
function array_load_set_smi_check(a) {
diff --git a/test/mjsunit/fuzz-natives.js b/test/mjsunit/fuzz-natives.js
index ffa9268..f8f0a28 100644
--- a/test/mjsunit/fuzz-natives.js
+++ b/test/mjsunit/fuzz-natives.js
@@ -146,6 +146,7 @@
"NewStrictArgumentsFast": true,
"PushWithContext": true,
"PushCatchContext": true,
+ "PushBlockContext": true,
"LazyCompile": true,
"LazyRecompile": true,
"NotifyDeoptimized": true,
diff --git a/test/mjsunit/harmony/block-lazy-compile.js b/test/mjsunit/harmony/block-lazy-compile.js
new file mode 100644
index 0000000..a6efcbf
--- /dev/null
+++ b/test/mjsunit/harmony/block-lazy-compile.js
@@ -0,0 +1,50 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+// Test deserialization of block contexts during lazy compilation
+// of closures.
+
+function f() {
+ var g;
+ {
+ // TODO(keuchel): introduce let
+ var x = 0;
+ g = function () {
+ x = x + 1;
+ return x;
+ }
+ }
+ return g;
+}
+
+var o = f();
+assertEquals(1, o());
+assertEquals(2, o());
+assertEquals(3, o());
+%OptimizeFunctionOnNextCall(o);
+assertEquals(4, o());
diff --git a/test/mjsunit/harmony/block-let-crankshaft.js b/test/mjsunit/harmony/block-let-crankshaft.js
new file mode 100644
index 0000000..c2fb96b
--- /dev/null
+++ b/test/mjsunit/harmony/block-let-crankshaft.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.
+
+// Flags: --harmony-block-scoping --allow-natives-syntax
+
+// Test that temporal dead zone semantics for function and block scoped
+// ket bindings are handled by the optimizing compiler.
+
+function f(x, b) {
+ let y = (b ? y : x) + 42;
+ return y;
+}
+
+function g(x, b) {
+ {
+ let y = (b ? y : x) + 42;
+ return y;
+ }
+}
+
+for (var i=0; i<10; i++) {
+ f(i, false);
+ g(i, false);
+}
+
+%OptimizeFunctionOnNextCall(f);
+%OptimizeFunctionOnNextCall(g);
+
+try {
+ f(42, true);
+} catch (e) {
+ assertInstanceof(e, ReferenceError);
+}
+
+try {
+ g(42, true);
+} catch (e) {
+ assertInstanceof(e, ReferenceError);
+}
diff --git a/test/mjsunit/harmony/block-let-declaration.js b/test/mjsunit/harmony/block-let-declaration.js
new file mode 100644
index 0000000..19c943f
--- /dev/null
+++ b/test/mjsunit/harmony/block-let-declaration.js
@@ -0,0 +1,67 @@
+// 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-block-scoping
+
+// Test let declarations in various settings.
+
+// Global
+let x;
+let y = 2;
+
+// Block local
+{
+ let y;
+ let x = 3;
+}
+
+assertEquals(undefined, x);
+assertEquals(2,y);
+
+if (true) {
+ let y;
+ assertEquals(undefined, y);
+}
+
+function TestLocalThrows(str, expect) {
+ assertThrows("(function(){" + str + "})()", expect);
+}
+
+function TestLocalDoesNotThrow(str) {
+ assertDoesNotThrow("(function(){" + str + "})()");
+}
+
+// Unprotected statement
+TestLocalThrows("if (true) let x;", SyntaxError);
+TestLocalThrows("with ({}) let x;", SyntaxError);
+TestLocalThrows("do let x; while (false)", SyntaxError);
+TestLocalThrows("while (false) let x;", SyntaxError);
+
+TestLocalDoesNotThrow("if (true) var x;");
+TestLocalDoesNotThrow("with ({}) var x;");
+TestLocalDoesNotThrow("do var x; while (false)");
+TestLocalDoesNotThrow("while (false) var x;");
diff --git a/test/mjsunit/harmony/block-let-semantics.js b/test/mjsunit/harmony/block-let-semantics.js
new file mode 100644
index 0000000..198c3b4
--- /dev/null
+++ b/test/mjsunit/harmony/block-let-semantics.js
@@ -0,0 +1,138 @@
+// 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-block-scoping
+
+// Test temporal dead zone semantics of let bound variables in
+// function and block scopes.
+
+function TestFunctionLocal(s) {
+ try {
+ eval("(function(){" + s + "; })")();
+ } catch (e) {
+ assertInstanceof(e, ReferenceError);
+ return;
+ }
+ assertUnreachable();
+}
+
+function TestBlockLocal(s,e) {
+ try {
+ eval("(function(){ {" + s + ";} })")();
+ } catch (e) {
+ assertInstanceof(e, ReferenceError);
+ return;
+ }
+ assertUnreachable();
+}
+
+
+function TestAll(s) {
+ TestBlockLocal(s);
+ TestFunctionLocal(s);
+}
+
+// Use before initialization in declaration statement.
+TestAll('let x = x + 1');
+TestAll('let x = x += 1');
+TestAll('let x = x++');
+TestAll('let x = ++x');
+
+// Use before initialization in prior statement.
+TestAll('x + 1; let x;');
+TestAll('x = 1; let x;');
+TestAll('x += 1; let x;');
+TestAll('++x; let x;');
+TestAll('x++; let x;');
+
+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()(); 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++; } }');
+
+// Use in 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;');
+
+// Test that variables introduced by function declarations are created and
+// initialized upon entering a function / block scope.
+function f() {
+ {
+ assertEquals(2, g1());
+ assertEquals(2, eval("g1()"));
+
+ // block scoped function declaration
+ function g1() {
+ return 2;
+ }
+ }
+
+ assertEquals(3, g2());
+ assertEquals(3, eval("g2()"));
+ // function scoped function declaration
+ function g2() {
+ return 3;
+ }
+}
+f();
+
+// Test that a function declaration introduces a block scoped variable.
+TestAll('{ function k() { return 0; } }; k(); ');
+
+// Test that a function declaration sees the scope it resides in.
+function f2() {
+ let m, n;
+ {
+ m = g;
+ function g() {
+ return a;
+ }
+ let a = 1;
+ }
+ assertEquals(1, m());
+
+ try {
+ throw 2;
+ } catch(b) {
+ n = h;
+ function h() {
+ return b + c;
+ }
+ let b = 3;
+ }
+ assertEquals(5, n());
+}
diff --git a/test/mjsunit/harmony/block-scoping.js b/test/mjsunit/harmony/block-scoping.js
new file mode 100644
index 0000000..266e380
--- /dev/null
+++ b/test/mjsunit/harmony/block-scoping.js
@@ -0,0 +1,216 @@
+// 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 --harmony-block-scoping
+// Test functionality of block scopes.
+
+// Hoisting of var declarations.
+function f1() {
+ {
+ var x = 1;
+ var y;
+ }
+ assertEquals(1, x)
+ assertEquals(undefined, y)
+}
+f1();
+
+
+// Dynamic lookup in and through block contexts.
+function f2(one) {
+ var x = one + 1;
+ let y = one + 2;
+ {
+ let z = one + 3;
+ assertEquals(1, eval('one'));
+ assertEquals(2, eval('x'));
+ assertEquals(3, eval('y'));
+ assertEquals(4, eval('z'));
+ }
+}
+f2(1);
+
+
+// Lookup in and through block contexts.
+function f3(one) {
+ var x = one + 1;
+ let y = one + 2;
+ {
+ let z = one + 3;
+ assertEquals(1, one);
+ assertEquals(2, x);
+ assertEquals(3, y);
+ assertEquals(4, z);
+ }
+}
+f3(1);
+
+
+// Dynamic lookup from closure.
+function f4(one) {
+ var x = one + 1;
+ let y = one + 2;
+ {
+ let z = one + 3;
+ function f() {
+ assertEquals(1, eval('one'));
+ assertEquals(2, eval('x'));
+ assertEquals(3, eval('y'));
+ assertEquals(4, eval('z'));
+ };
+ }
+}
+f4(1);
+
+
+// Lookup from closure.
+function f5(one) {
+ var x = one + 1;
+ let y = one + 2;
+ {
+ let z = one + 3;
+ function f() {
+ assertEquals(1, one);
+ assertEquals(2, x);
+ assertEquals(3, y);
+ assertEquals(4, z);
+ };
+ }
+}
+f5(1);
+
+
+// Return from block.
+function f6() {
+ let x = 1;
+ {
+ let y = 2;
+ return x + y;
+ }
+}
+assertEquals(3, f6(6));
+
+
+// Variable shadowing and lookup.
+function f7(a) {
+ let b = 1;
+ var c = 1;
+ var d = 1;
+ { // let variables shadowing argument, let and var variables
+ let a = 2;
+ let b = 2;
+ let c = 2;
+ assertEquals(2,a);
+ assertEquals(2,b);
+ assertEquals(2,c);
+ }
+ try {
+ throw 'stuff1';
+ } catch (a) {
+ assertEquals('stuff1',a);
+ // catch variable shadowing argument
+ a = 2;
+ assertEquals(2,a);
+ {
+ // let variable shadowing catch variable
+ let a = 3;
+ assertEquals(3,a);
+ try {
+ throw 'stuff2';
+ } catch (a) {
+ assertEquals('stuff2',a);
+ // catch variable shadowing let variable
+ a = 4;
+ assertEquals(4,a);
+ }
+ assertEquals(3,a);
+ }
+ assertEquals(2,a);
+ }
+ try {
+ throw 'stuff3';
+ } catch (c) {
+ // catch variable shadowing var variable
+ assertEquals('stuff3',c);
+ try {
+ throw 'stuff4';
+ } catch(c) {
+ assertEquals('stuff4',c);
+ // catch variable shadowing catch variable
+ c = 3;
+ assertEquals(3,c);
+ }
+ (function(c) {
+ // argument shadowing catch variable
+ c = 3;
+ assertEquals(3,c);
+ })();
+ assertEquals('stuff3', c);
+ (function() {
+ // var variable shadowing catch variable
+ var c = 3;
+ })();
+ assertEquals('stuff3', c);
+ c = 2;
+ }
+ assertEquals(1,c);
+ (function(a,b,c) {
+ // arguments shadowing argument, let and var variable
+ a = 2;
+ b = 2;
+ c = 2;
+ assertEquals(2,a);
+ assertEquals(2,b);
+ assertEquals(2,c);
+ // var variable shadowing var variable
+ var d = 2;
+ })(1,1);
+ assertEquals(1,a);
+ assertEquals(1,b);
+ assertEquals(1,c);
+ assertEquals(1,d);
+}
+f7(1);
+
+
+// Ensure let variables are block local and var variables function local.
+function f8() {
+ var let_accessors = [];
+ var var_accessors = [];
+ for (var i = 0; i < 10; i++) {
+ let x = i;
+ var y = i;
+ let_accessors[i] = function() { return x; }
+ var_accessors[i] = function() { return y; }
+ }
+ for (var j = 0; j < 10; j++) {
+ y = j + 10;
+ assertEquals(j, let_accessors[j]());
+ assertEquals(y, var_accessors[j]());
+ }
+}
+f8();
diff --git a/test/mjsunit/harmony/debug-blockscopes.js b/test/mjsunit/harmony/debug-blockscopes.js
new file mode 100644
index 0000000..e0df71b
--- /dev/null
+++ b/test/mjsunit/harmony/debug-blockscopes.js
@@ -0,0 +1,389 @@
+// 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 --harmony-block-scoping
+// 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 test_name;
+var listener_delegate;
+var listener_called;
+var exception;
+var begin_test_count = 0;
+var end_test_count = 0;
+var break_count = 0;
+
+
+// Debug event listener which delegates.
+function listener(event, exec_state, event_data, data) {
+ try {
+ if (event == Debug.DebugEvent.Break) {
+ break_count++;
+ listener_called = true;
+ listener_delegate(exec_state);
+ }
+ } catch (e) {
+ exception = e;
+ }
+}
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+
+// Initialize for a new test.
+function BeginTest(name) {
+ test_name = name;
+ listener_delegate = null;
+ listener_called = false;
+ exception = null;
+ begin_test_count++;
+}
+
+
+// Check result of a test.
+function EndTest() {
+ assertTrue(listener_called, "listerner not called for " + test_name);
+ assertNull(exception, test_name);
+ end_test_count++;
+}
+
+
+// Check that the scope chain contains the expected types of scopes.
+function CheckScopeChain(scopes, exec_state) {
+ assertEquals(scopes.length, exec_state.frame().scopeCount());
+ for (var i = 0; i < scopes.length; i++) {
+ var scope = exec_state.frame().scope(i);
+ assertTrue(scope.isScope());
+ assertEquals(scopes[i], scope.scopeType());
+
+ // Check the global object when hitting the global scope.
+ 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());
+ }
+ }
+
+ // Get the debug command processor.
+ var dcp = exec_state.debugCommandProcessor("unspecified_running_state");
+
+ // Send a scopes request and check the result.
+ var json;
+ var request_json = '{"seq":0,"type":"request","command":"scopes"}';
+ var response_json = dcp.processDebugJSONRequest(request_json);
+ var response = JSON.parse(response_json);
+ assertEquals(scopes.length, response.body.scopes.length);
+ for (var i = 0; i < scopes.length; i++) {
+ assertEquals(i, response.body.scopes[i].index);
+ assertEquals(scopes[i], response.body.scopes[i].type);
+ if (scopes[i] == debug.ScopeType.Local ||
+ scopes[i] == debug.ScopeType.Closure) {
+ assertTrue(response.body.scopes[i].object.ref < 0);
+ } else {
+ assertTrue(response.body.scopes[i].object.ref >= 0);
+ }
+ var found = false;
+ for (var j = 0; j < response.refs.length && !found; j++) {
+ found = response.refs[j].handle == response.body.scopes[i].object.ref;
+ }
+ assertTrue(found, "Scope object " + response.body.scopes[i].object.ref + " not found");
+ }
+}
+
+// Check that the content of the scope is as expected. For functions just check
+// that there is a function.
+function CheckScopeContent(content, number, exec_state) {
+ var scope = exec_state.frame().scope(number);
+ var count = 0;
+ for (var p in content) {
+ var property_mirror = scope.scopeObject().property(p);
+ if (property_mirror.isUndefined()) {
+ print('property ' + p + ' not found in scope');
+ }
+ assertFalse(property_mirror.isUndefined(), 'property ' + p + ' not found in scope');
+ if (typeof(content[p]) === 'function') {
+ assertTrue(property_mirror.value().isFunction());
+ } else {
+ assertEquals(content[p], property_mirror.value().value(), 'property ' + p + ' has unexpected value');
+ }
+ count++;
+ }
+
+ // 'arguments' and might be exposed in the local and closure scope. Just
+ // ignore this.
+ var scope_size = scope.scopeObject().properties().length;
+ if (!scope.scopeObject().property('arguments').isUndefined()) {
+ scope_size--;
+ }
+ // Also ignore synthetic variable from catch block.
+ if (!scope.scopeObject().property('.catch-var').isUndefined()) {
+ scope_size--;
+ }
+ // Skip property with empty name.
+ if (!scope.scopeObject().property('').isUndefined()) {
+ scope_size--;
+ }
+ // Also ignore synthetic variable from block scopes.
+ if (!scope.scopeObject().property('.block').isUndefined()) {
+ scope_size--;
+ }
+
+ if (count != scope_size) {
+ print('Names found in scope:');
+ var names = scope.scopeObject().propertyNames();
+ for (var i = 0; i < names.length; i++) {
+ print(names[i]);
+ }
+ }
+ assertEquals(count, scope_size);
+
+ // Get the debug command processor.
+ var dcp = exec_state.debugCommandProcessor("unspecified_running_state");
+
+ // Send a scope request for information on a single scope and check the
+ // result.
+ var request_json = '{"seq":0,"type":"request","command":"scope","arguments":{"number":';
+ request_json += scope.scopeIndex();
+ request_json += '}}';
+ var response_json = dcp.processDebugJSONRequest(request_json);
+ var response = JSON.parse(response_json);
+ assertEquals(scope.scopeType(), response.body.type);
+ assertEquals(number, response.body.index);
+ if (scope.scopeType() == debug.ScopeType.Local ||
+ scope.scopeType() == debug.ScopeType.Closure) {
+ assertTrue(response.body.object.ref < 0);
+ } else {
+ assertTrue(response.body.object.ref >= 0);
+ }
+ var found = false;
+ for (var i = 0; i < response.refs.length && !found; i++) {
+ found = response.refs[i].handle == response.body.object.ref;
+ }
+ assertTrue(found, "Scope object " + response.body.object.ref + " not found");
+}
+
+
+// Simple empty block scope in local scope.
+BeginTest("Local block 1");
+
+function local_block_1() {
+ {
+ debugger;
+ }
+}
+
+listener_delegate = function(exec_state) {
+ CheckScopeChain([debug.ScopeType.Block,
+ debug.ScopeType.Local,
+ debug.ScopeType.Global], exec_state);
+ CheckScopeContent({}, 0, exec_state);
+ CheckScopeContent({}, 1, exec_state);
+};
+local_block_1();
+EndTest();
+
+
+// Local scope with a parameter.
+BeginTest("Local 2");
+
+function local_2(a) {
+ {
+ debugger;
+ }
+}
+
+listener_delegate = function(exec_state) {
+ CheckScopeChain([debug.ScopeType.Block,
+ debug.ScopeType.Local,
+ debug.ScopeType.Global], exec_state);
+ CheckScopeContent({a:1}, 1, exec_state);
+};
+local_2(1);
+EndTest();
+
+
+// Local scope with a parameter and a local variable.
+BeginTest("Local 3");
+
+function local_3(a) {
+ let x = 3;
+ debugger;
+}
+
+listener_delegate = function(exec_state) {
+ CheckScopeChain([debug.ScopeType.Local,
+ debug.ScopeType.Global], exec_state);
+ CheckScopeContent({a:1,x:3}, 0, exec_state);
+};
+local_3(1);
+EndTest();
+
+
+// Local scope with parameters and local variables.
+BeginTest("Local 4");
+
+function local_4(a, b) {
+ let x = 3;
+ let y = 4;
+ debugger;
+}
+
+listener_delegate = function(exec_state) {
+ CheckScopeChain([debug.ScopeType.Local,
+ debug.ScopeType.Global], exec_state);
+ CheckScopeContent({a:1,b:2,x:3,y:4}, 0, exec_state);
+};
+local_4(1, 2);
+EndTest();
+
+
+// Single empty with block.
+BeginTest("With block 1");
+
+function with_block_1() {
+ with({}) {
+ debugger;
+ }
+}
+
+listener_delegate = function(exec_state) {
+ CheckScopeChain([debug.ScopeType.Block,
+ 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.Block,
+ debug.ScopeType.With,
+ debug.ScopeType.Block,
+ debug.ScopeType.With,
+ debug.ScopeType.Local,
+ debug.ScopeType.Global], exec_state);
+ CheckScopeContent({}, 0, exec_state);
+ CheckScopeContent({}, 1, exec_state);
+ CheckScopeContent({}, 2, exec_state);
+ CheckScopeContent({}, 3, 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.Block,
+ debug.ScopeType.With,
+ debug.ScopeType.Local,
+ debug.ScopeType.Global], exec_state);
+ CheckScopeContent({}, 0, exec_state);
+ CheckScopeContent({a:1,b:2}, 1, 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.Block,
+ debug.ScopeType.With,
+ debug.ScopeType.Block,
+ debug.ScopeType.With,
+ debug.ScopeType.Local,
+ debug.ScopeType.Global], exec_state);
+ CheckScopeContent({a:2,b:1}, 1, exec_state);
+ CheckScopeContent({a:1,b:2}, 3, exec_state);
+};
+with_block_4();
+EndTest();
+
+
+// Simple closure formed by returning an inner function referering to an outer
+// block local variable and an outer function's parameter.
+BeginTest("Closure 1");
+
+function closure_1(a) {
+ var x = 2;
+ let y = 3;
+ if (true) {
+ let z = 4;
+ function f() {
+ debugger;
+ return a + x + y + z;
+ };
+ return f;
+ }
+}
+
+listener_delegate = function(exec_state) {
+ CheckScopeChain([debug.ScopeType.Local,
+ debug.ScopeType.Block,
+ debug.ScopeType.Closure,
+ debug.ScopeType.Global], exec_state);
+ CheckScopeContent({}, 0, exec_state);
+ CheckScopeContent({a:1,x:2,y:3}, 2, exec_state);
+};
+closure_1(1)();
+EndTest();
diff --git a/test/mjsunit/harmony/debug-evaluate-blockscopes.js b/test/mjsunit/harmony/debug-evaluate-blockscopes.js
new file mode 100644
index 0000000..549960a
--- /dev/null
+++ b/test/mjsunit/harmony/debug-evaluate-blockscopes.js
@@ -0,0 +1,64 @@
+// 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 --harmony-block-scoping
+
+// Test debug evaluation for functions without local context, but with
+// nested catch contexts.
+
+function f() {
+ { // Line 1.
+ let i = 1; // Line 2.
+ try { // Line 3.
+ throw 'stuff'; // Line 4.
+ } catch (e) { // Line 5.
+ x = 2; // Line 6.
+ }
+ }
+};
+
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+// Set breakpoint on line 6.
+var bp = Debug.setBreakPoint(f, 6);
+
+function listener(event, exec_state, event_data, data) {
+ if (event == Debug.DebugEvent.Break) {
+ result = exec_state.frame().evaluate("i").value();
+ }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+result = -1;
+f();
+assertEquals(1, result);
+
+// Clear breakpoint.
+Debug.clearBreakPoint(bp);
+// Get rid of the debug event listener.
+Debug.setListener(null);
diff --git a/test/mjsunit/harmony/proxies.js b/test/mjsunit/harmony/proxies.js
index 84641d5..640033d 100644
--- a/test/mjsunit/harmony/proxies.js
+++ b/test/mjsunit/harmony/proxies.js
@@ -42,22 +42,27 @@
TestGet({
get: function(r, k) { return 42 }
})
+
TestGet({
get: function(r, k) { return this.get2(r, k) },
get2: function(r, k) { return 42 }
})
+
TestGet({
getPropertyDescriptor: function(k) { return {value: 42} }
})
+
TestGet({
getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) },
getPropertyDescriptor2: function(k) { return {value: 42} }
})
+
TestGet({
getPropertyDescriptor: function(k) {
return {get value() { return 42 }}
}
})
+
TestGet({
get: undefined,
getPropertyDescriptor: function(k) { return {value: 42} }
@@ -83,32 +88,38 @@
TestGetCall({
get: function(r, k) { return function() { return 55 } }
})
+
TestGetCall({
get: function(r, k) { return this.get2(r, k) },
get2: function(r, k) { return function() { return 55 } }
})
+
TestGetCall({
getPropertyDescriptor: function(k) {
return {value: function() { return 55 }}
}
})
+
TestGetCall({
getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) },
getPropertyDescriptor2: function(k) {
return {value: function() { return 55 }}
}
})
+
TestGetCall({
getPropertyDescriptor: function(k) {
return {get value() { return function() { return 55 } }}
}
})
+
TestGetCall({
get: undefined,
getPropertyDescriptor: function(k) {
return {value: function() { return 55 }}
}
})
+
TestGetCall({
get: function(r, k) {
if (k == "gg") {
@@ -146,14 +157,17 @@
TestSet({
set: function(r, k, v) { key = k; val = v; return true }
})
+
TestSet({
set: function(r, k, v) { return this.set2(r, k, v) },
set2: function(r, k, v) { key = k; val = v; return true }
})
+
TestSet({
getOwnPropertyDescriptor: function(k) { return {writable: true} },
defineProperty: function(k, desc) { key = k; val = desc.value }
})
+
TestSet({
getOwnPropertyDescriptor: function(k) {
return this.getOwnPropertyDescriptor2(k)
@@ -162,22 +176,26 @@
defineProperty: function(k, desc) { this.defineProperty2(k, desc) },
defineProperty2: function(k, desc) { key = k; val = desc.value }
})
+
TestSet({
getOwnPropertyDescriptor: function(k) {
return {get writable() { return true }}
},
defineProperty: function(k, desc) { key = k; val = desc.value }
})
+
TestSet({
getOwnPropertyDescriptor: function(k) {
return {set: function(v) { key = k; val = v }}
}
})
+
TestSet({
getOwnPropertyDescriptor: function(k) { return null },
getPropertyDescriptor: function(k) { return {writable: true} },
defineProperty: function(k, desc) { key = k; val = desc.value }
})
+
TestSet({
getOwnPropertyDescriptor: function(k) { return null },
getPropertyDescriptor: function(k) {
@@ -185,12 +203,14 @@
},
defineProperty: function(k, desc) { key = k; val = desc.value }
})
+
TestSet({
getOwnPropertyDescriptor: function(k) { return null },
getPropertyDescriptor: function(k) {
return {set: function(v) { key = k; val = v }}
}
})
+
TestSet({
getOwnPropertyDescriptor: function(k) { return null },
getPropertyDescriptor: function(k) { return null },
@@ -279,10 +299,12 @@
TestDefine({
defineProperty: function(k, d) { key = k; desc = d; return true }
})
+
TestDefine({
defineProperty: function(k, d) { return this.defineProperty2(k, d) },
defineProperty2: function(k, d) { key = k; desc = d; return true }
})
+
TestDefine(Proxy.create({
get: function(pr, pk) {
return function(k, d) { key = k; desc = d; return true }
@@ -323,10 +345,12 @@
TestDelete({
'delete': function(k) { key = k; return k < "z" }
})
+
TestDelete({
'delete': function(k) { return this.delete2(k) },
delete2: function(k) { key = k; return k < "z" }
})
+
TestDelete(Proxy.create({
get: function(pr, pk) {
return function(k) { key = k; return k < "z" }
@@ -363,6 +387,7 @@
defineProperty: function(k, d) { this["__" + k] = d; return true },
getOwnPropertyDescriptor: function(k) { return this["__" + k] }
})
+
TestDescriptor({
defineProperty: function(k, d) { this["__" + k] = d; return true },
getOwnPropertyDescriptor: function(k) {
@@ -404,7 +429,7 @@
-// Element (in).
+// Membership test (in).
var key
function TestIn(handler) {
@@ -442,26 +467,31 @@
TestIn({
has: function(k) { key = k; return k < "z" }
})
+
TestIn({
has: function(k) { return this.has2(k) },
has2: function(k) { key = k; return k < "z" }
})
+
TestIn({
getPropertyDescriptor: function(k) {
key = k; return k < "z" ? {value: 42} : void 0
}
})
+
TestIn({
getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) },
getPropertyDescriptor2: function(k) {
key = k; return k < "z" ? {value: 42} : void 0
}
})
+
TestIn({
getPropertyDescriptor: function(k) {
key = k; return k < "z" ? {get value() { return 42 }} : void 0
}
})
+
TestIn({
get: undefined,
getPropertyDescriptor: function(k) {
@@ -477,7 +507,65 @@
-// Instanceof (instanceof).
+// Own Properties (Object.prototype.hasOwnProperty).
+
+var key
+function TestHasOwn(handler) {
+ var o = Proxy.create(handler)
+ assertTrue(Object.prototype.hasOwnProperty.call(o, "a"))
+ assertEquals("a", key)
+ assertTrue(Object.prototype.hasOwnProperty.call(o, 99))
+ assertEquals("99", key)
+ assertFalse(Object.prototype.hasOwnProperty.call(o, "z"))
+ assertEquals("z", key)
+}
+
+TestHasOwn({
+ hasOwn: function(k) { key = k; return k < "z" }
+})
+
+TestHasOwn({
+ hasOwn: function(k) { return this.hasOwn2(k) },
+ hasOwn2: function(k) { key = k; return k < "z" }
+})
+
+TestHasOwn({
+ getOwnPropertyDescriptor: function(k) {
+ key = k; return k < "z" ? {value: 42} : void 0
+ }
+})
+
+TestHasOwn({
+ getOwnPropertyDescriptor: function(k) {
+ return this.getOwnPropertyDescriptor2(k)
+ },
+ getOwnPropertyDescriptor2: function(k) {
+ key = k; return k < "z" ? {value: 42} : void 0
+ }
+})
+
+TestHasOwn({
+ getOwnPropertyDescriptor: function(k) {
+ key = k; return k < "z" ? {get value() { return 42 }} : void 0
+ }
+})
+
+TestHasOwn({
+ hasOwn: undefined,
+ getOwnPropertyDescriptor: function(k) {
+ key = k; return k < "z" ? {value: 42} : void 0
+ }
+})
+
+TestHasOwn(Proxy.create({
+ get: function(pr, pk) {
+ return function(k) { key = k; return k < "z" }
+ }
+}))
+
+
+
+// Instanceof (instanceof)
function TestInstanceof() {
var o = {}
@@ -514,7 +602,7 @@
-// Prototype (Object.getPrototypeOf).
+// Prototype (Object.getPrototypeOf, Object.prototype.isPrototypeOf).
function TestPrototype() {
var o = {}
@@ -528,6 +616,32 @@
assertSame(Object.getPrototypeOf(p2), o)
assertSame(Object.getPrototypeOf(p3), p2)
assertSame(Object.getPrototypeOf(p4), null)
+
+ assertTrue(Object.prototype.isPrototypeOf(o))
+ 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))
+ 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))
+ assertFalse(Object.prototype.isPrototypeOf.call(p1, p1))
+ assertFalse(Object.prototype.isPrototypeOf.call(p1, o))
+ 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(p2, p1))
+ assertFalse(Object.prototype.isPrototypeOf.call(p2, p2))
+ assertTrue(Object.prototype.isPrototypeOf.call(p2, p3))
+ assertFalse(Object.prototype.isPrototypeOf.call(p2, p4))
+ assertFalse(Object.prototype.isPrototypeOf.call(p3, p2))
}
TestPrototype()
@@ -544,13 +658,16 @@
TestPropertyNames([], {
getOwnPropertyNames: function() { return [] }
})
+
TestPropertyNames(["a", "zz", " ", "0"], {
getOwnPropertyNames: function() { return ["a", "zz", " ", 0] }
})
+
TestPropertyNames(["throw", "function "], {
getOwnPropertyNames: function() { return this.getOwnPropertyNames2() },
getOwnPropertyNames2: function() { return ["throw", "function "] }
})
+
TestPropertyNames(["[object Object]"], {
get getOwnPropertyNames() {
return function() { return [{}] }
@@ -566,22 +683,27 @@
TestKeys([], {
keys: function() { return [] }
})
+
TestKeys(["a", "zz", " ", "0"], {
keys: function() { return ["a", "zz", " ", 0] }
})
+
TestKeys(["throw", "function "], {
keys: function() { return this.keys2() },
keys2: function() { return ["throw", "function "] }
})
+
TestKeys(["[object Object]"], {
get keys() {
return function() { return [{}] }
}
})
+
TestKeys(["a", "0"], {
getOwnPropertyNames: function() { return ["a", 23, "zz", "", 0] },
getOwnPropertyDescriptor: function(k) { return {enumerable: k.length == 1} }
})
+
TestKeys(["23", "zz", ""], {
getOwnPropertyNames: function() { return this.getOwnPropertyNames2() },
getOwnPropertyNames2: function() { return ["a", 23, "zz", "", 0] },
@@ -590,6 +712,7 @@
},
getOwnPropertyDescriptor2: function(k) { return {enumerable: k.length != 1} }
})
+
TestKeys(["a", "b", "c", "5"], {
get getOwnPropertyNames() {
return function() { return ["0", 4, "a", "b", "c", 5] }
@@ -598,6 +721,7 @@
return function(k) { return {enumerable: k >= "44"} }
}
})
+
TestKeys([], {
get getOwnPropertyNames() {
return function() { return ["a", "b", "c"] }
@@ -661,6 +785,7 @@
TestFix([], {
fix: function() { return {} }
})
+
TestFix(["a", "b", "c", "d", "zz"], {
fix: function() {
return {
@@ -672,12 +797,14 @@
}
}
})
+
TestFix(["a"], {
fix: function() { return this.fix2() },
fix2: function() {
return {a: {value: 4, writable: true, configurable: true, enumerable: true}}
}
})
+
TestFix(["b"], {
get fix() {
return function() {
@@ -685,3 +812,87 @@
}
}
})
+
+
+
+// String conversion (Object.prototype.toString, Object.prototype.toLocaleString)
+
+var key
+function TestToString(handler) {
+ var o = Proxy.create(handler)
+ key = ""
+ assertEquals("[object Object]", Object.prototype.toString.call(o))
+ assertEquals("", key)
+ assertEquals("my_proxy", Object.prototype.toLocaleString.call(o))
+ assertEquals("toString", key)
+}
+
+TestToString({
+ get: function(r, k) { key = k; return function() { return "my_proxy" } }
+})
+
+TestToString({
+ get: function(r, k) { return this.get2(r, k) },
+ get2: function(r, k) { key = k; return function() { return "my_proxy" } }
+})
+
+TestToString(Proxy.create({
+ get: function(pr, pk) {
+ return function(r, k) { key = k; return function() { return "my_proxy" } }
+ }
+}))
+
+
+
+// Value conversion (Object.prototype.toValue)
+
+function TestValueOf(handler) {
+ var o = Proxy.create(handler)
+ assertSame(o, Object.prototype.valueOf.call(o))
+}
+
+TestValueOf({})
+
+
+
+// Enumerability (Object.prototype.propertyIsEnumerable)
+
+var key
+function TestIsEnumerable(handler) {
+ var o = Proxy.create(handler)
+ assertTrue(Object.prototype.propertyIsEnumerable.call(o, "a"))
+ assertEquals("a", key)
+ assertTrue(Object.prototype.propertyIsEnumerable.call(o, 2))
+ assertEquals("2", key)
+ assertFalse(Object.prototype.propertyIsEnumerable.call(o, "z"))
+ assertEquals("z", key)
+}
+
+TestIsEnumerable({
+ getOwnPropertyDescriptor: function(k) {
+ key = k; return {enumerable: k < "z", configurable: true}
+ },
+})
+
+TestIsEnumerable({
+ getOwnPropertyDescriptor: function(k) {
+ return this.getOwnPropertyDescriptor2(k)
+ },
+ getOwnPropertyDescriptor2: function(k) {
+ key = k; return {enumerable: k < "z", configurable: true}
+ },
+})
+
+TestIsEnumerable({
+ getOwnPropertyDescriptor: function(k) {
+ key = k; return {get enumerable() { return k < "z" }, configurable: true}
+ },
+})
+
+TestIsEnumerable(Proxy.create({
+ get: function(pr, pk) {
+ return function(k) {
+ key = k; return {enumerable: k < "z", configurable: true}
+ }
+ }
+}))
diff --git a/test/mjsunit/harmony/typeof.js b/test/mjsunit/harmony/typeof.js
new file mode 100644
index 0000000..acde977
--- /dev/null
+++ b/test/mjsunit/harmony/typeof.js
@@ -0,0 +1,35 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --harmony-typeof
+
+assertFalse(typeof null == 'object')
+assertFalse(typeof null === 'object')
+assertTrue(typeof null == 'null')
+assertTrue(typeof null === 'null')
+assertEquals("null", typeof null)
+assertSame("null", typeof null)
diff --git a/test/mjsunit/harmony/weakmaps.js b/test/mjsunit/harmony/weakmaps.js
new file mode 100644
index 0000000..e43f916
--- /dev/null
+++ b/test/mjsunit/harmony/weakmaps.js
@@ -0,0 +1,163 @@
+// 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)
+assertTrue(WeakMap.prototype.constructor === WeakMap)
+
+
+// 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/math-floor.js b/test/mjsunit/math-floor.js
index 11f4cd7..f211ce2 100644
--- a/test/mjsunit/math-floor.js
+++ b/test/mjsunit/math-floor.js
@@ -27,10 +27,11 @@
// Flags: --max-new-space-size=256 --allow-natives-syntax
+var test_id = 0;
+
function testFloor(expect, input) {
- function test(n) {
- return Math.floor(n);
- }
+ var test = new Function('n',
+ '"' + (test_id++) + '";return Math.floor(n)');
assertEquals(expect, test(input));
assertEquals(expect, test(input));
assertEquals(expect, test(input));
@@ -51,6 +52,17 @@
testFloor(-Infinity, -Infinity);
testFloor(NaN, NaN);
+ // Ensure that a negative zero coming from Math.floor is properly handled
+ // by other operations.
+ function ifloor(x) {
+ return 1 / Math.floor(x);
+ }
+ assertEquals(-Infinity, ifloor(-0));
+ assertEquals(-Infinity, ifloor(-0));
+ assertEquals(-Infinity, ifloor(-0));
+ %OptimizeFunctionOnNextCall(ifloor);
+ assertEquals(-Infinity, ifloor(-0));
+
testFloor(0, 0.1);
testFloor(0, 0.49999999999999994);
testFloor(0, 0.5);
@@ -129,3 +141,19 @@
for (var i = 0; i < 500; i++) {
test();
}
+
+
+// Regression test for a bug where a negative zero coming from Math.floor
+// was not properly handled by other operations.
+function floorsum(i, n) {
+ var ret = Math.floor(n);
+ while (--i > 0) {
+ ret += Math.floor(n);
+ }
+ return ret;
+}
+assertEquals(-0, floorsum(1, -0));
+%OptimizeFunctionOnNextCall(floorsum);
+// The optimized function will deopt. Run it with enough iterations to try
+// to optimize via OSR (triggering the bug).
+assertEquals(-0, floorsum(100000, -0));
diff --git a/test/mjsunit/math-round.js b/test/mjsunit/math-round.js
index 1366557..102c970 100644
--- a/test/mjsunit/math-round.js
+++ b/test/mjsunit/math-round.js
@@ -1,4 +1,4 @@
-// Copyright 2010 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:
@@ -27,10 +27,12 @@
// Flags: --allow-natives-syntax
+var test_id = 0;
function testRound(expect, input) {
- function doRound(input) {
- return Math.round(input);
- }
+ // Make source code different on each invocation to make
+ // sure it gets optimized each time.
+ var doRound = new Function('input',
+ '"' + (test_id++) + '";return Math.round(input)');
assertEquals(expect, doRound(input));
assertEquals(expect, doRound(input));
assertEquals(expect, doRound(input));
@@ -44,6 +46,21 @@
testRound(-Infinity, -Infinity);
testRound(NaN, NaN);
+// Regression test for a bug where a negative zero coming from Math.round
+// was not properly handled by other operations.
+function roundsum(i, n) {
+ var ret = Math.round(n);
+ while (--i > 0) {
+ ret += Math.round(n);
+ }
+ return ret;
+}
+assertEquals(-0, roundsum(1, -0));
+%OptimizeFunctionOnNextCall(roundsum);
+// The optimized function will deopt. Run it with enough iterations to try
+// to optimize via OSR (triggering the bug).
+assertEquals(-0, roundsum(100000, -0));
+
testRound(1, 0.5);
testRound(1, 0.7);
testRound(1, 1);
diff --git a/test/mjsunit/parse-int-float.js b/test/mjsunit/parse-int-float.js
index a4f09df..2e4f648 100644
--- a/test/mjsunit/parse-int-float.js
+++ b/test/mjsunit/parse-int-float.js
@@ -100,4 +100,17 @@
assertEquals(Infinity, parseFloat(1/0), "parseFloat Infinity");
assertEquals(-Infinity, parseFloat(-1/0), "parseFloat -Infinity");
+var state;
+var throwingRadix = { valueOf: function() { state = "throwingRadix"; throw null; } };
+var throwingString = { toString: function() { state = "throwingString"; throw null; } };
+state = null;
+try { parseInt('123', throwingRadix); } catch (e) {}
+assertEquals(state, "throwingRadix");
+state = null;
+try { parseInt(throwingString, 10); } catch (e) {}
+assertEquals(state, "throwingString");
+
+state = null;
+try { parseInt(throwingString, throwingRadix); } catch (e) {}
+assertEquals(state, "throwingString");
diff --git a/test/mjsunit/regress/regress-103259.js b/test/mjsunit/regress/regress-103259.js
new file mode 100644
index 0000000..447073c
--- /dev/null
+++ b/test/mjsunit/regress/regress-103259.js
@@ -0,0 +1,36 @@
+// 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
+
+var a = [];
+a[8192] = '';
+assertTrue(%HasDictionaryElements(a));
+var uc16 = '\u0094';
+var test = uc16;
+for (var i = 0; i < 13; i++) test += test;
+assertEquals(test, a.join(uc16));
diff --git a/test/mjsunit/regress/regress-1419.js b/test/mjsunit/regress/regress-1419.js
new file mode 100644
index 0000000..98a8b76
--- /dev/null
+++ b/test/mjsunit/regress/regress-1419.js
@@ -0,0 +1,47 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test that using bind several time does not change the length of existing
+// bound functions.
+
+function foo() {
+}
+
+var f1 = function (x) {}.bind(foo);
+var f2 = function () {};
+
+assertEquals(1, f1.length);
+
+// the object we bind to can be any object
+f2.bind(foo);
+
+assertEquals(1, f1.length);
+
+var desc = Object.getOwnPropertyDescriptor(f1, 'length');
+assertEquals(false, desc.writable);
+assertEquals(false, desc.enumerable);
+assertEquals(false, desc.configurable);
diff --git a/test/mjsunit/regress/regress-1546.js b/test/mjsunit/regress/regress-1546.js
new file mode 100644
index 0000000..7f1fa58
--- /dev/null
+++ b/test/mjsunit/regress/regress-1546.js
@@ -0,0 +1,32 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// See: http://code.google.com/p/v8/issues/detail?id=1546
+
+// Should't throw. Scanner incorrectly truncated to char before comparing
+// with "*", so it ended the comment early.
+eval("/*\u822a/ */");
\ No newline at end of file
diff --git a/test/mjsunit/regress/regress-1563.js b/test/mjsunit/regress/regress-1563.js
new file mode 100644
index 0000000..c25b6c7
--- /dev/null
+++ b/test/mjsunit/regress/regress-1563.js
@@ -0,0 +1,44 @@
+// Copyright 2008 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
+
+obj = new PixelArray(10);
+
+// Test that undefined gets properly clamped in Crankshafted pixel array
+// assignments.
+function set_pixel(obj, arg) {
+ obj[0] = arg;
+}
+
+set_pixel(obj, 1.5);
+set_pixel(obj, NaN);
+%OptimizeFunctionOnNextCall(set_pixel);
+set_pixel(obj, undefined);
+set_pixel(obj, undefined);
+
+assertEquals(0, obj[0]);
diff --git a/test/mjsunit/regress/regress-1586.js b/test/mjsunit/regress/regress-1586.js
new file mode 100644
index 0000000..b15e2f2
--- /dev/null
+++ b/test/mjsunit/regress/regress-1586.js
@@ -0,0 +1,64 @@
+// 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
+
+// Test debug evaluation for functions without local context, but with
+// nested catch contexts.
+
+function f() {
+ var i = 1; // Line 1.
+ { // Line 2.
+ try { // Line 3.
+ throw 'stuff'; // Line 4.
+ } catch (e) { // Line 5.
+ x = 2; // Line 6.
+ }
+ }
+};
+
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+// Set breakpoint on line 6.
+var bp = Debug.setBreakPoint(f, 6);
+
+function listener(event, exec_state, event_data, data) {
+ if (event == Debug.DebugEvent.Break) {
+ result = exec_state.frame().evaluate("i").value();
+ }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+result = -1;
+f();
+assertEquals(1, result);
+
+// Clear breakpoint.
+Debug.clearBreakPoint(bp);
+// Get rid of the debug event listener.
+Debug.setListener(null);
diff --git a/test/mjsunit/regress/regress-1620.js b/test/mjsunit/regress/regress-1620.js
new file mode 100644
index 0000000..6d72974
--- /dev/null
+++ b/test/mjsunit/regress/regress-1620.js
@@ -0,0 +1,54 @@
+// 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.
+
+// Don't allow malformed unicode escape sequences in identifiers.
+// In strings and regexps we currently allow malformed unicode escape
+// sequences without throwing a SyntaxError. Instead "\u22gk" would
+// treat the "\u" as an identity escape, and evaluate to "u22gk".
+// Due to code sharing, we did the same in identifiers. This should
+// no longer be the case.
+// See: http://code.google.com/p/v8/issues/detail?id=1620
+
+assertThrows("var \\u\\u\\u = 42;");
+assertThrows("var \\u41 = 42;");
+assertThrows("var \\u123 = 42;");
+eval("var \\u1234 = 42;");
+assertEquals(42, eval("\u1234"));
+assertThrows("var uuu = 42; var x = \\u\\u\\u");
+
+// Regressions introduced and fixed again while fixing the above.
+
+// Handle 0xFFFD correctly (it's a valid value, and shouldn't be used
+// to mark an error).
+assertEquals(0xFFFD, "\uFFFD".charCodeAt(0));
+
+// Handle unicode escapes in regexp flags correctly.
+assertThrows("/x/g\\uim", SyntaxError);
+assertThrows("/x/g\\u2im", SyntaxError);
+assertThrows("/x/g\\u22im", SyntaxError);
+assertThrows("/x/g\\u222im", SyntaxError);
+assertThrows("/x/g\\\\u2222im", SyntaxError);
diff --git a/test/mjsunit/regress/regress-1625.js b/test/mjsunit/regress/regress-1625.js
new file mode 100644
index 0000000..a2ef8df
--- /dev/null
+++ b/test/mjsunit/regress/regress-1625.js
@@ -0,0 +1,36 @@
+// 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 overwriting Array.prototype.push does not make
+// Object.defineProperties misbehave.
+
+Array.prototype.push = 1;
+var desc = {foo: {value: 10}, bar: {get: function() {return 42; }}};
+var obj = {};
+var x = Object.defineProperties(obj, desc);
+assertEquals(x.foo, 10);
+assertEquals(x.bar, 42);
diff --git a/test/mjsunit/regress/regress-219.js b/test/mjsunit/regress/regress-219.js
index 4bfabdc..b751f0f 100644
--- a/test/mjsunit/regress/regress-219.js
+++ b/test/mjsunit/regress/regress-219.js
@@ -30,6 +30,10 @@
// We should now allow duplicates of flags.
// (See http://code.google.com/p/v8/issues/detail?id=219)
+// This has been reversed by issue 1628, since other browsers have also
+// tightened their syntax.
+// (See http://code.google.com/p/v8/issues/detail?id=1628)
+
// Base tests: we recognize the basic flags
function assertFlags(re, global, multiline, ignoreCase) {
@@ -53,124 +57,92 @@
// Double i's
-re = /a/ii;
-assertFlags(re, false, false, true)
+assertThrows("/a/ii");
-re = /a/gii;
-assertFlags(re, true, false, true)
+assertThrows("/a/gii");
-re = /a/igi;
-assertFlags(re, true, false, true)
+assertThrows("/a/igi");
-re = /a/iig;
-assertFlags(re, true, false, true)
+assertThrows("/a/iig");
-re = /a/gimi;
-assertFlags(re, true, true, true)
+assertThrows("/a/gimi");
-re = /a/giim;
-assertFlags(re, true, true, true)
+assertThrows("/a/giim");
-re = /a/igim;
-assertFlags(re, true, true, true)
+assertThrows("/a/igim");
+assertThrows(function(){ return RegExp("a", "ii"); })
-re = RegExp("a", "ii");
-assertFlags(re, false, false, true)
+assertThrows(function(){ return RegExp("a", "gii"); })
-re = RegExp("a", "gii");
-assertFlags(re, true, false, true)
+assertThrows(function(){ return RegExp("a", "igi"); })
-re = RegExp("a", "igi");
-assertFlags(re, true, false, true)
+assertThrows(function(){ return RegExp("a", "iig"); })
-re = RegExp("a", "iig");
-assertFlags(re, true, false, true)
+assertThrows(function(){ return RegExp("a", "gimi"); })
-re = RegExp("a", "gimi");
-assertFlags(re, true, true, true)
+assertThrows(function(){ return RegExp("a", "giim"); })
-re = RegExp("a", "giim");
-assertFlags(re, true, true, true)
-
-re = RegExp("a", "igim");
-assertFlags(re, true, true, true)
+assertThrows(function(){ return RegExp("a", "igim"); })
// Tripple i's
-re = /a/iii;
-assertFlags(re, false, false, true)
+assertThrows("/a/iii");
-re = /a/giii;
-assertFlags(re, true, false, true)
+assertThrows("/a/giii");
-re = /a/igii;
-assertFlags(re, true, false, true)
+assertThrows("/a/igii");
-re = /a/iigi;
-assertFlags(re, true, false, true)
+assertThrows("/a/iigi");
-re = /a/iiig;
-assertFlags(re, true, false, true)
+assertThrows("/a/iiig");
-re = /a/miiig;
-assertFlags(re, true, true, true)
+assertThrows("/a/miiig");
+assertThrows(function(){ return RegExp("a", "iii"); })
-re = RegExp("a", "iii");
-assertFlags(re, false, false, true)
+assertThrows(function(){ return RegExp("a", "giii"); })
-re = RegExp("a", "giii");
-assertFlags(re, true, false, true)
+assertThrows(function(){ return RegExp("a", "igii"); })
-re = RegExp("a", "igii");
-assertFlags(re, true, false, true)
+assertThrows(function(){ return RegExp("a", "iigi"); })
-re = RegExp("a", "iigi");
-assertFlags(re, true, false, true)
+assertThrows(function(){ return RegExp("a", "iiig"); })
-re = RegExp("a", "iiig");
-assertFlags(re, true, false, true)
+assertThrows(function(){ return RegExp("a", "miiig"); })
-re = RegExp("a", "miiig");
-assertFlags(re, true, true, true)
+// Illegal flags - valid flags late in string.
-// Illegal flags - flags late in string.
+assertThrows("/a/arglebargleglopglyf");
-re = /a/arglebargleglopglyf;
-assertFlags(re, true, false, false)
+assertThrows("/a/arglebargleglopglif");
-re = /a/arglebargleglopglif;
-assertFlags(re, true, false, true)
+assertThrows("/a/arglebargleglopglym");
-re = /a/arglebargleglopglym;
-assertFlags(re, true, true, false)
-
-re = /a/arglebargleglopglim;
-assertFlags(re, true, true, true)
+assertThrows("/a/arglebargleglopglim");
// Case of flags still matters.
-re = /a/gmi;
+var re = /a/gmi;
assertFlags(re, true, true, true)
-re = /a/Gmi;
-assertFlags(re, false, true, true)
+assertThrows("/a/Gmi");
-re = /a/gMi;
-assertFlags(re, true, false, true)
+assertThrows("/a/gMi");
-re = /a/gmI;
-assertFlags(re, true, true, false)
+assertThrows("/a/gmI");
-re = /a/GMi;
-assertFlags(re, false, false, true)
+assertThrows("/a/GMi");
-re = /a/GmI;
-assertFlags(re, false, true, false)
+assertThrows("/a/GmI");
-re = /a/gMI;
-assertFlags(re, true, false, false)
+assertThrows("/a/gMI");
-re = /a/GMI;
-assertFlags(re, false, false, false)
+assertThrows("/a/GMI");
+
+// Unicode escape sequences are not interpreted.
+
+assertThrows("/a/\\u0067");
+assertThrows("/a/\\u0069");
+assertThrows("/a/\\u006d");
+assertThrows("/a/\\u006D");
diff --git a/test/mjsunit/regress/regress-87.js b/test/mjsunit/regress/regress-87.js
index 131cb58..10446fd 100644
--- a/test/mjsunit/regress/regress-87.js
+++ b/test/mjsunit/regress/regress-87.js
@@ -25,34 +25,29 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-function testFlags(flagstring, global, ignoreCase, multiline) {
- var text = "/x/"+flagstring;
- var re = eval(text);
- assertEquals(global, re.global, text + ".global");
- assertEquals(ignoreCase, re.ignoreCase, text + ".ignoreCase");
- assertEquals(multiline, re.multiline, text + ".multiline");
-}
+// In Issue 87, we allowed unicode escape sequences in RegExp flags.
+// However, according to ES5, they should not be interpreted, but passed
+// verbatim to the RegExp constructor.
+// (On top of that, the original test was bugged and never tested anything).
+// The behavior was changed in r8969 to not interpret escapes, but this
+// test didn't test that, and only failed when making invalid flag characters
+// an error too.
-testFlags("", false, false, false);
+assertThrows("/x/\\u0067");
+assertThrows("/x/\\u0069");
+assertThrows("/x/\\u006d");
-testFlags("\u0067", true, false, false);
+assertThrows("/x/\\u0067i");
+assertThrows("/x/\\u0069m");
+assertThrows("/x/\\u006dg");
-testFlags("\u0069", false, true, false)
+assertThrows("/x/m\\u0067");
+assertThrows("/x/g\\u0069");
+assertThrows("/x/i\\u006d");
-testFlags("\u006d", false, false, true);
+assertThrows("/x/m\\u0067i");
+assertThrows("/x/g\\u0069m");
+assertThrows("/x/i\\u006dg");
-testFlags("\u0068", false, false, false);
-
-testFlags("\u0020", false, false, false);
-
-
-testFlags("\u0067g", true, false, false);
-
-testFlags("g\u0067", true, false, false);
-
-testFlags("abc\u0067efg", true, false, false);
-
-testFlags("i\u0067", true, true, false);
-
-testFlags("\u0067i", true, true, false);
-
+assertThrows("/x/\\u0068");
+assertThrows("/x/\\u0020");
diff --git a/test/mjsunit/regress/regress-91008.js b/test/mjsunit/regress/regress-91008.js
new file mode 100644
index 0000000..d7ea2df
--- /dev/null
+++ b/test/mjsunit/regress/regress-91008.js
@@ -0,0 +1,43 @@
+// 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.
+
+function testsort(n) {
+ var numbers=new Array(n);
+ for (var i=0;i<n;i++) numbers[i]=i;
+ delete numbers[50];
+ delete numbers[150];
+ delete numbers[25000];
+ delete numbers[n-1];
+ delete numbers[n-2];
+ delete numbers[30];
+ delete numbers[2];
+ delete numbers[1];
+ delete numbers[0];
+ numbers.sort();
+}
+
+testsort(100000)
diff --git a/test/mjsunit/regress/regress-91010.js b/test/mjsunit/regress/regress-91010.js
new file mode 100644
index 0000000..a077999
--- /dev/null
+++ b/test/mjsunit/regress/regress-91010.js
@@ -0,0 +1,36 @@
+// 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.
+
+try {
+ try {
+ var N = 100*1000;
+ var array = Array(N);
+ for (var i = 0; i != N; ++i)
+ array[i] = i;
+ } catch(ex) {}
+ array.unshift('Kibo');
+} catch(ex) {}
diff --git a/test/mjsunit/regress/regress-91013.js b/test/mjsunit/regress/regress-91013.js
new file mode 100644
index 0000000..c61e2b1
--- /dev/null
+++ b/test/mjsunit/regress/regress-91013.js
@@ -0,0 +1,51 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test that KeyedStore stub for unboxed double arrays backing store
+// correctly returns stored value as the result.
+
+// Flags: --allow-natives-syntax --unbox-double-arrays
+
+// Create array with unboxed double array backing store.
+var i = 100000;
+var a = new Array(i);
+for (var j = 0; j < i; j++) {
+ a[j] = 0.5;
+}
+
+assertTrue(%HasFastDoubleElements(a));
+
+// Store some smis into it.
+for (var j = 0; j < 10; j++) {
+ assertEquals(j, a[j] = j);
+}
+
+// Store some heap numbers into it.
+for (var j = 0; j < 10; j++) {
+ var v = j + 0.5;
+ assertEquals(v, a[j] = v);
+}
diff --git a/test/mjsunit/regress/regress-95113.js b/test/mjsunit/regress/regress-95113.js
new file mode 100644
index 0000000..f01b270
--- /dev/null
+++ b/test/mjsunit/regress/regress-95113.js
@@ -0,0 +1,48 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+function get_double_array() {
+ var a = new Array(100000);
+ var i = 0;
+ while (!%HasFastDoubleElements(a)) {
+ a[i] = i;
+ i++;
+ }
+ assertTrue(%HasFastDoubleElements(a));
+ a.length = 1;
+ a[0] = 1.5;
+ a.length = 2;
+ a[1] = 2.5;
+ assertEquals(a[0], 1.5);
+ assertEquals(a[1], 2.5);
+ assertTrue(%HasFastDoubleElements(a));
+ return a;
+}
+
+var a = get_double_array();
diff --git a/test/mjsunit/regress/regress-95485.js b/test/mjsunit/regress/regress-95485.js
new file mode 100644
index 0000000..2510072
--- /dev/null
+++ b/test/mjsunit/regress/regress-95485.js
@@ -0,0 +1,42 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+function Test() {
+ var left = 'XXX';
+ var right = 'YYY';
+ for (var i = 0; i < 3; i++) {
+ var cons = left + right;
+ var substring = cons.substring(2, 4);
+ try {
+ with ({Test: i})
+ continue;
+ } finally { }
+ }
+ return substring;
+}
+
+assertEquals('XY', Test());
diff --git a/test/mjsunit/regress/regress-96523.js b/test/mjsunit/regress/regress-96523.js
new file mode 100644
index 0000000..e611ce3
--- /dev/null
+++ b/test/mjsunit/regress/regress-96523.js
@@ -0,0 +1,37 @@
+// 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.
+
+with ({x:'outer'}) {
+ (function() {
+ var x = 'inner';
+ try {
+ throw 'Exception';
+ } catch (e) {
+ assertEquals('inner', x);
+ }
+ })()
+}
diff --git a/test/mjsunit/scope-calls-eval.js b/test/mjsunit/scope-calls-eval.js
new file mode 100644
index 0000000..4a941aa
--- /dev/null
+++ b/test/mjsunit/scope-calls-eval.js
@@ -0,0 +1,65 @@
+// 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.
+
+// Tests if the information about eval calls in a function is
+// propagated correctly through catch and with blocks.
+
+
+function f1() {
+ var x = 5;
+ function g() {
+ try {
+ throw '';
+ } catch (e) {
+ eval('var x = 3;');
+ }
+ try {
+ throw '';
+ } catch (e) {
+ return x;
+ }
+ }
+ return g();
+}
+
+
+function f2() {
+ var x = 5;
+ function g() {
+ with ({e:42}) {
+ eval('var x = 3;');
+ }
+ with ({e:42}) {
+ return x;
+ }
+ }
+ return g();
+}
+
+
+assertEquals(3, f1());
+assertEquals(3, f2());
diff --git a/test/mjsunit/string-slices-regexp.js b/test/mjsunit/string-slices-regexp.js
new file mode 100644
index 0000000..a8cadae
--- /dev/null
+++ b/test/mjsunit/string-slices-regexp.js
@@ -0,0 +1,81 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Flags: --string-slices
+
+//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++) {
+ assertTrue(/^([a-z]+): (.*)/.test(foo.substring(foo.indexOf("regexp:"))));
+ assertEquals("regexp", RegExp.$1, "RegExp.$1");
+}
+
+var re = /^(((N({)?)|(R)|(U)|(V)|(B)|(H)|(n((n)|(r)|(v)|(h))?)|(r(r)?)|(v)|(b((n)|(b))?)|(h))|((Y)|(A)|(E)|(o(u)?)|(p(u)?)|(q(u)?)|(s)|(t)|(u)|(w)|(x(u)?)|(y)|(z)|(a((T)|(A)|(L))?)|(c)|(e)|(f(u)?)|(g(u)?)|(i)|(j)|(l)|(m(u)?)))+/;
+var r = new RegExp(re)
+var str = "_Avtnennan gunzvmu pubExnY nEvln vaTxh rmuhguhaTxnY_".slice(1,-1);
+str = str + str;
+assertTrue(r.test(str));
+assertTrue(r.test(str));
+var re = /x/;
+assertEquals("a.yb", "_axyb_".slice(1,-1).replace(re, "."));
+re.compile("y");
+assertEquals("ax.b", "_axyb_".slice(1,-1).replace(re, "."));
+re.compile("(x)");
+assertEquals(["x", "x"], re.exec("_axyb_".slice(1,-1)));
+re.compile("(y)");
+assertEquals(["y", "y"], re.exec("_axyb_".slice(1,-1)));
+
+for(var i = 0; i < 100; i++) {
+ var a = "aaaaaaaaaaaaaaaaaaaaaaaabbaacabbabaaaaabbaaaabbac".slice(24,-1);
+ var b = "bbaacabbabaaaaabbaaaabba" + a;
+ // The first time, the cons string will be flattened and handled by the
+ // runtime system.
+ assertEquals(["bbaa", "a", "", "a"], /((\3|b)\2(a)){2,}/.exec(b));
+ // The second time, the cons string is already flattened and will be
+ // handled by generated code.
+ assertEquals(["bbaa", "a", "", "a"], /((\3|b)\2(a)){2,}/.exec(b));
+ assertEquals(["bbaa", "a", "", "a"], /((\3|b)\2(a)){2,}/.exec(a));
+ assertEquals(["bbaa", "a", "", "a"], /((\3|b)\2(a)){2,}/.exec(a));
+}
+
+var c = "ABCDEFGHIJKLMN".slice(2,-2);
+var d = "ABCDEF\u1234GHIJKLMN".slice(2,-2);
+var e = "ABCDEFGHIJKLMN".slice(0,-2);
+assertTrue(/^C.*L$/.test(c));
+assertTrue(/^C.*L$/.test(c));
+assertTrue(/^C.*L$/.test(d));
+assertTrue(/^C.*L$/.test(d));
+assertTrue(/^A\w{10}L$/.test(e));
+assertTrue(/^A\w{10}L$/.test(e));
+
+var e = "qui-opIasd-fghjklzx-cvbn-mqwer-tyuio-pasdf-ghIjkl-zx".slice(6,-6);
+var e_split = e.split("-");
+assertEquals(e_split[0], "Iasd");
+assertEquals(e_split[1], "fghjklzx");
+assertEquals(e_split[6], "ghI");
diff --git a/test/mjsunit/string-slices.js b/test/mjsunit/string-slices.js
new file mode 100755
index 0000000..f629ca9
--- /dev/null
+++ b/test/mjsunit/string-slices.js
@@ -0,0 +1,199 @@
+// Copyright 2008 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --string-slices --expose-externalize-string
+
+var s = 'abcdefghijklmn';
+assertEquals(s, s.substr());
+assertEquals(s, s.substr(0));
+assertEquals(s, s.substr('0'));
+assertEquals(s, s.substr(void 0));
+assertEquals(s, s.substr(null));
+assertEquals(s, s.substr(false));
+assertEquals(s, s.substr(0.9));
+assertEquals(s, s.substr({ valueOf: function() { return 0; } }));
+assertEquals(s, s.substr({ toString: function() { return '0'; } }));
+
+var s1 = s.substring(1);
+assertEquals(s1, s.substr(1));
+assertEquals(s1, s.substr('1'));
+assertEquals(s1, s.substr(true));
+assertEquals(s1, s.substr(1.1));
+assertEquals(s1, s.substr({ valueOf: function() { return 1; } }));
+assertEquals(s1, s.substr({ toString: function() { return '1'; } }));
+
+
+assertEquals(s.substring(s.length - 1), s.substr(-1));
+assertEquals(s.substring(s.length - 1), s.substr(-1.2));
+assertEquals(s.substring(s.length - 1), s.substr(-1.7));
+assertEquals(s.substring(s.length - 2), s.substr(-2));
+assertEquals(s.substring(s.length - 2), s.substr(-2.3));
+assertEquals(s.substring(s.length - 2, s.length - 1), s.substr(-2, 1));
+assertEquals(s, s.substr(-100));
+assertEquals('abc', s.substr(-100, 3));
+assertEquals(s1, s.substr(-s.length + 1));
+
+// assertEquals('', s.substr(0, void 0)); // smjs and rhino
+assertEquals('abcdefghijklmn', s.substr(0, void 0)); // kjs and v8
+assertEquals('', s.substr(0, null));
+assertEquals(s, s.substr(0, String(s.length)));
+assertEquals('a', s.substr(0, true));
+
+
+// Test substrings of different lengths and alignments.
+// First ASCII.
+var x = "ASCII";
+for (var i = 0; i < 25; i++) {
+ x += (i >> 4).toString(16) + (i & 0x0f).toString(16);
+}
+/x/.exec(x); // Try to force a flatten.
+for (var i = 5; i < 25; i++) {
+ for (var j = 0; j < 25; j++) {
+ var z = x.substring(i, i+j);
+ var w = Math.random() * 42; // Allocate something new in new-space.
+ assertEquals(j, z.length);
+ for (var k = 0; k < j; k++) {
+ assertEquals(x.charAt(i+k), z.charAt(k));
+ }
+ }
+}
+// Then two-byte strings.
+x = "UC16\u2028"; // Non-ascii char forces two-byte string.
+for (var i = 0; i < 25; i++) {
+ x += (i >> 4).toString(16) + (i & 0x0f).toString(16);
+}
+/x/.exec(x); // Try to force a flatten.
+for (var i = 5; i < 25; i++) {
+ for (var j = 0; j < 25; j++) {
+ var z = x.substring(i, i + j);
+ var w = Math.random() * 42; // Allocate something new in new-space.
+ assertEquals(j, z.length);
+ for (var k = 0; k < j; k++) {
+ assertEquals(x.charAt(i+k), z.charAt(k));
+ }
+ }
+}
+
+// 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;
+var xl = x.length;
+var cache = [];
+for (var i = 0; i < 1000; i++) {
+ var z = x.substring(i % xl);
+ assertEquals(xl - (i % xl), z.length);
+ cache.push(z);
+}
+
+
+// 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;
+var xl = x.length;
+var cache = [];
+for (var i = 0; i < 1000; i++) {
+ var z = x.substring(i % xl);
+ assertEquals(xl - (i % xl), z.length);
+ cache.push(z);
+}
+
+// Substring of substring.
+var cache = [];
+var last = x;
+var offset = 0;
+for (var i = 0; i < 64; i++) {
+ var z = last.substring(i);
+ last = z;
+ cache.push(z);
+ offset += i;
+}
+for (var i = 63; i >= 0; i--) {
+ var z = cache.pop();
+ assertTrue(/\u2028123456789ABCDEF/.test(z));
+ assertEquals(xl - offset, z.length);
+ assertEquals(x.charAt(i*(i+1)/2), z.charAt(0));
+ offset -= i;
+}
+
+// Test charAt for different strings.
+function f(s1, s2, s3, i) {
+ assertEquals(String.fromCharCode(97+i%11), s1.charAt(i%11));
+ assertEquals(String.fromCharCode(97+i%11), s2.charAt(i%11));
+ assertEquals(String.fromCharCode(98+i%11), s3.charAt(i%11));
+ assertEquals(String.fromCharCode(101), s3.charAt(3));
+}
+
+flat = "abcdefghijkl12345";
+cons = flat + flat.toUpperCase();
+slice = "abcdefghijklmn12345".slice(1, -1);
+for ( var i = 0; i < 1000; i++) {
+ f(flat, cons, slice, i);
+}
+flat = "abcdefghijkl1\u20232345";
+cons = flat + flat.toUpperCase();
+slice = "abcdefghijklmn1\u20232345".slice(1, -1);
+for ( var i = 0; i < 1000; i++) {
+ f(flat, cons, slice, i);
+}
+
+// Concatenate substrings.
+var ascii = 'abcdefghijklmnop';
+var utf = '\u03B1\u03B2\u03B3\u03B4\u03B5\u03B6\u03B7\u03B8\u03B9\u03BA\u03BB';
+assertEquals("klmno", ascii.substring(10,15) + ascii.substring(16));
+assertEquals("\u03B4\u03B7", utf.substring(3,4) + utf.substring(6,7));
+assertEquals("klp", ascii.substring(10,12) + ascii.substring(15,16));
+assertEquals("\u03B1\u03B4\u03B5", utf.substring(0,1) + utf.substring(5,3));
+assertEquals("", ascii.substring(16) + utf.substring(16));
+assertEquals("bcdef\u03B4\u03B5\u03B6\u03B7\u03B8\u03B9",
+ ascii.substring(1,6) + utf.substring(3,9));
+assertEquals("\u03B4\u03B5\u03B6\u03B7\u03B8\u03B9abcdefghijklmnop",
+ utf.substring(3,9) + ascii);
+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);
+assertEquals(a.slice(1,-1), b);
+externalizeString(a);
+assertEquals(a.slice(1,-1), b);
+*/
\ No newline at end of file
diff --git a/test/mjsunit/string-split.js b/test/mjsunit/string-split.js
index 6fcf557..bc50945 100644
--- a/test/mjsunit/string-split.js
+++ b/test/mjsunit/string-split.js
@@ -116,3 +116,15 @@
assertEquals(["a", "b", "c"], "abc".split("", numberObj(3)));
assertEquals(["a", "b", "c"], "abc".split("", 4));
assertEquals(["a", "b", "c"], "abc".split("", numberObj(4)));
+
+
+var all_ascii_codes = [];
+for (var i = 0; i < 128; i++) all_ascii_codes[i] = i;
+var all_ascii_string = String.fromCharCode.apply(String, all_ascii_codes);
+
+var split_chars = all_ascii_string.split("");
+assertEquals(128, split_chars.length);
+for (var i = 0; i < 128; i++) {
+ assertEquals(1, split_chars[i].length);
+ assertEquals(i, split_chars[i].charCodeAt(0));
+}
diff --git a/test/mjsunit/substr.js b/test/mjsunit/substr.js
index f69a9c0..cffaf94 100755
--- a/test/mjsunit/substr.js
+++ b/test/mjsunit/substr.js
@@ -135,3 +135,20 @@
assertEquals(xl - (i % xl), z.length);
cache.push(z);
}
+
+// Substring of substring.
+var cache = [];
+var last = x;
+var offset = 0;
+for (var i = 0; i < 64; i++) {
+ var z = last.substring(i);
+ last = z;
+ cache.push(z);
+ offset += i;
+}
+for (var i = 63; i >= 0; i--) {
+ var z = cache.pop();
+ assertTrue(/\u2028123456789ABCDEF/.test(z));
+ assertEquals(xl - offset, z.length);
+ offset -= i;
+}
diff --git a/test/mjsunit/testcfg.py b/test/mjsunit/testcfg.py
index 7c6311b..87ed4fa 100644
--- a/test/mjsunit/testcfg.py
+++ b/test/mjsunit/testcfg.py
@@ -145,7 +145,7 @@
return result
def GetBuildRequirements(self):
- return ['sample', 'sample=shell']
+ return ['d8']
def GetTestStatus(self, sections, defs):
status_file = join(self.root, 'mjsunit.status')
diff --git a/test/mjsunit/unbox-double-arrays.js b/test/mjsunit/unbox-double-arrays.js
index 351765e..feecaec 100644
--- a/test/mjsunit/unbox-double-arrays.js
+++ b/test/mjsunit/unbox-double-arrays.js
@@ -29,12 +29,12 @@
// Flags: --allow-natives-syntax --unbox-double-arrays --expose-gc
var large_array_size = 100000;
-var approx_dict_to_elements_threshold = 75000;
+var approx_dict_to_elements_threshold = 70000;
var name = 0;
function expected_array_value(i) {
- if ((i % 2) == 0) {
+ if ((i % 50) != 0) {
return i;
} else {
return i + 0.5;
@@ -466,3 +466,62 @@
test_for_in();
test_for_in();
test_for_in();
+
+function test_get_property_names() {
+ names = %GetPropertyNames(large_array3);
+ property_name_count = 0;
+ for (x in names) { property_name_count++; };
+ assertEquals(26, property_name_count);
+}
+
+test_get_property_names();
+test_get_property_names();
+test_get_property_names();
+
+// Test elements getters.
+assertEquals(expected_array_value(10), large_array3[10]);
+assertEquals(expected_array_value(-NaN), large_array3[2]);
+large_array3.__defineGetter__("2", function(){
+ return expected_array_value(10);
+});
+
+function test_getter() {
+ assertEquals(expected_array_value(10), large_array3[10]);
+ assertEquals(expected_array_value(10), large_array3[2]);
+}
+
+test_getter();
+test_getter();
+test_getter();
+%OptimizeFunctionOnNextCall(test_getter);
+test_getter();
+test_getter();
+test_getter();
+
+// Test element setters.
+large_array4 = new Array(large_array_size);
+force_to_fast_double_array(large_array4);
+
+var setter_called = false;
+
+assertEquals(expected_array_value(10), large_array4[10]);
+assertEquals(expected_array_value(2), large_array4[2]);
+large_array4.__defineSetter__("10", function(value){
+ setter_called = true;
+ });
+
+function test_setter() {
+ setter_called = false;
+ large_array4[10] = 119;
+ assertTrue(setter_called);
+ assertEquals(undefined, large_array4[10]);
+ assertEquals(expected_array_value(2), large_array4[2]);
+}
+
+test_setter();
+test_setter();
+test_setter();
+%OptimizeFunctionOnNextCall(test_setter);
+test_setter();
+test_setter();
+test_setter();
diff --git a/test/mjsunit/with-leave.js b/test/mjsunit/with-leave.js
index ded62ca..7369faa 100644
--- a/test/mjsunit/with-leave.js
+++ b/test/mjsunit/with-leave.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:
@@ -59,3 +59,162 @@
}
assertTrue(caught);
+
+// 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'
+// to actually verify that the inner context has been discarded. A static
+// lookup of 'x' might accidentally succeed.
+with ({x: 'outer'}) {
+ label: {
+ with ({x: 'inner'}) {
+ break label;
+ }
+ }
+ assertEquals('outer', x);
+}
+
+
+with ({x: 'outer'}) {
+ label: {
+ with ({x: 'middle'}) {
+ with ({x: 'inner'}) {
+ break label;
+ }
+ }
+ }
+ assertEquals('outer', x);
+}
+
+
+with ({x: 'outer'}) {
+ for (var i = 0; i < 10; ++i) {
+ with ({x: 'inner' + i}) {
+ continue;
+ }
+ }
+ assertEquals('outer', x);
+}
+
+
+with ({x: 'outer'}) {
+ label: for (var i = 0; i < 10; ++i) {
+ with ({x: 'middle' + i}) {
+ for (var j = 0; j < 10; ++j) {
+ with ({x: 'inner' + j}) {
+ continue label;
+ }
+ }
+ }
+ }
+ assertEquals('outer', x);
+}
+
+
+with ({x: 'outer'}) {
+ try {
+ with ({x: 'inner'}) {
+ throw 0;
+ }
+ } catch (e) {
+ assertEquals('outer', x);
+ }
+}
+
+
+with ({x: 'outer'}) {
+ try {
+ with ({x: 'middle'}) {
+ with ({x: 'inner'}) {
+ throw 0;
+ }
+ }
+ } catch (e) {
+ assertEquals('outer', x);
+ }
+}
+
+
+try {
+ with ({x: 'outer'}) {
+ try {
+ with ({x: 'inner'}) {
+ throw 0;
+ }
+ } finally {
+ assertEquals('outer', x);
+ }
+ }
+} catch (e) {
+ if (e instanceof MjsUnitAssertionError) throw e;
+}
+
+
+try {
+ with ({x: 'outer'}) {
+ try {
+ with ({x: 'middle'}) {
+ with ({x: 'inner'}) {
+ throw 0;
+ }
+ }
+ } finally {
+ assertEquals('outer', x);
+ }
+ }
+} catch (e) {
+ if (e instanceof MjsUnitAssertionError) throw e;
+}
+
+
+// Verify that the context is correctly set in the stack frame after exiting
+// from with.
+function f() {}
+
+with ({x: 'outer'}) {
+ label: {
+ with ({x: 'inner'}) {
+ break label;
+ }
+ }
+ f(); // The context could be restored from the stack after the call.
+ assertEquals('outer', x);
+}
+
+
+with ({x: 'outer'}) {
+ for (var i = 0; i < 10; ++i) {
+ with ({x: 'inner' + i}) {
+ continue;
+ }
+ }
+ f();
+ assertEquals('outer', x);
+}
+
+
+with ({x: 'outer'}) {
+ try {
+ with ({x: 'inner'}) {
+ throw 0;
+ }
+ } catch (e) {
+ f();
+ assertEquals('outer', x);
+ }
+}
+
+
+try {
+ with ({x: 'outer'}) {
+ try {
+ with ({x: 'inner'}) {
+ throw 0;
+ }
+ } finally {
+ f();
+ assertEquals('outer', x);
+ }
+ }
+} catch (e) {
+ if (e instanceof MjsUnitAssertionError) throw e;
+}
diff --git a/test/mozilla/mozilla.status b/test/mozilla/mozilla.status
index c62d770..f6d6925 100644
--- a/test/mozilla/mozilla.status
+++ b/test/mozilla/mozilla.status
@@ -246,9 +246,8 @@
ecma_3/Number/15.7.4.6-1: FAIL_OK
#:=== RegExp:===
-# To be compatible with JSC we silently ignore flags that do not make
-# sense. These tests expects us to throw exceptions.
-ecma_3/RegExp/regress-57631: FAIL_OK
+# We don't match the syntax error message of Mozilla for invalid
+# RegExp flags.
ecma_3/RegExp/15.10.4.1-6: FAIL_OK
# PCRE doesn't allow subpattern nesting deeper than 200, this tests
diff --git a/test/mozilla/testcfg.py b/test/mozilla/testcfg.py
index 3728f79..587781d 100644
--- a/test/mozilla/testcfg.py
+++ b/test/mozilla/testcfg.py
@@ -125,7 +125,7 @@
return tests
def GetBuildRequirements(self):
- return ['sample', 'sample=shell']
+ return ['d8']
def GetTestStatus(self, sections, defs):
status_file = join(self.root, 'mozilla.status')
diff --git a/test/preparser/testcfg.py b/test/preparser/testcfg.py
index 39b62c3..d900e26 100644
--- a/test/preparser/testcfg.py
+++ b/test/preparser/testcfg.py
@@ -27,7 +27,7 @@
import test
import os
-from os.path import join, dirname, exists
+from os.path import join, dirname, exists, isfile
import platform
import utils
import re
@@ -122,10 +122,15 @@
{"Test": Test, "Template": Template}, {})
def ListTests(self, current_path, path, mode, variant_flags):
- executable = join('obj', 'preparser', mode, 'preparser')
+ executable = 'preparser'
if utils.IsWindows():
executable += '.exe'
executable = join(self.context.buildspace, executable)
+ if not isfile(executable):
+ executable = join('obj', 'preparser', mode, 'preparser')
+ if utils.IsWindows():
+ executable += '.exe'
+ executable = join(self.context.buildspace, executable)
expectations = self.GetExpectations()
result = []
# Find all .js files in tests/preparser directory.
diff --git a/test/sputnik/sputnik.status b/test/sputnik/sputnik.status
index 82d8a61..868509d 100644
--- a/test/sputnik/sputnik.status
+++ b/test/sputnik/sputnik.status
@@ -56,15 +56,6 @@
# errors, for compatibility.
S15.10.2.11_A1_T2: FAIL
S15.10.2.11_A1_T3: FAIL
-S15.10.4.1_A5_T1: FAIL
-S15.10.4.1_A5_T2: FAIL
-S15.10.4.1_A5_T3: FAIL
-S15.10.4.1_A5_T4: FAIL
-S15.10.4.1_A5_T5: FAIL
-S15.10.4.1_A5_T6: FAIL
-S15.10.4.1_A5_T7: FAIL
-S15.10.4.1_A5_T8: FAIL
-S15.10.4.1_A5_T9: 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.
@@ -99,6 +90,13 @@
S7.8.4_A4.3_T5: FAIL_OK
S7.8.4_A7.2_T5: 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
diff --git a/test/sputnik/testcfg.py b/test/sputnik/testcfg.py
index c9eb4f2..1032c13 100644
--- a/test/sputnik/testcfg.py
+++ b/test/sputnik/testcfg.py
@@ -101,7 +101,7 @@
return result
def GetBuildRequirements(self):
- return ['sample', 'sample=shell']
+ return ['d8']
def GetTestStatus(self, sections, defs):
status_file = join(self.root, 'sputnik.status')
diff --git a/test/test262/testcfg.py b/test/test262/testcfg.py
index aa1212e..9482046 100644
--- a/test/test262/testcfg.py
+++ b/test/test262/testcfg.py
@@ -111,7 +111,7 @@
return tests
def GetBuildRequirements(self):
- return ['sample', 'sample=shell']
+ return ['d8']
def GetTestStatus(self, sections, defs):
status_file = join(self.root, 'test262.status')