Update V8 to r3431 as required by WebKit r51976.
Change-Id: I567392c3f8c0a0d5201a4249611ac4ccf468cd5b
diff --git a/test/cctest/SConscript b/test/cctest/SConscript
index f041041..e6c81d8 100644
--- a/test/cctest/SConscript
+++ b/test/cctest/SConscript
@@ -34,6 +34,7 @@
SOURCES = {
'all': [
+ 'test-accessors.cc',
'test-alloc.cc',
'test-api.cc',
'test-ast.cc',
@@ -51,6 +52,7 @@
'test-log.cc',
'test-log-utils.cc',
'test-mark-compact.cc',
+ 'test-parsing.cc',
'test-regexp.cc',
'test-serialize.cc',
'test-sockets.cc',
diff --git a/test/cctest/cctest.cc b/test/cctest/cctest.cc
index 82a33e6..f638ed4 100644
--- a/test/cctest/cctest.cc
+++ b/test/cctest/cctest.cc
@@ -121,3 +121,6 @@
v8::V8::Dispose();
return 0;
}
+
+RegisterThreadedTest *RegisterThreadedTest::first_ = NULL;
+int RegisterThreadedTest::count_ = 0;
diff --git a/test/cctest/cctest.h b/test/cctest/cctest.h
index a95645e..404b692 100644
--- a/test/cctest/cctest.h
+++ b/test/cctest/cctest.h
@@ -28,6 +28,8 @@
#ifndef CCTEST_H_
#define CCTEST_H_
+#include "v8.h"
+
#ifndef TEST
#define TEST(Name) \
static void Test##Name(); \
@@ -72,4 +74,138 @@
CcTest* prev_;
};
+// Switches between all the Api tests using the threading support.
+// In order to get a surprising but repeatable pattern of thread
+// switching it has extra semaphores to control the order in which
+// the tests alternate, not relying solely on the big V8 lock.
+//
+// A test is augmented with calls to ApiTestFuzzer::Fuzz() in its
+// callbacks. This will have no effect when we are not running the
+// thread fuzzing test. In the thread fuzzing test it will
+// pseudorandomly select a successor thread and switch execution
+// to that thread, suspending the current test.
+class ApiTestFuzzer: public v8::internal::Thread {
+ public:
+ void CallTest();
+ explicit ApiTestFuzzer(int num)
+ : test_number_(num),
+ gate_(v8::internal::OS::CreateSemaphore(0)),
+ active_(true) {
+ }
+ ~ApiTestFuzzer() { delete gate_; }
+
+ // The ApiTestFuzzer is also a Thread, so it has a Run method.
+ virtual void Run();
+
+ enum PartOfTest { FIRST_PART, SECOND_PART };
+
+ static void Setup(PartOfTest part);
+ static void RunAllTests();
+ static void TearDown();
+ // This method switches threads if we are running the Threading test.
+ // Otherwise it does nothing.
+ static void Fuzz();
+ private:
+ static bool fuzzing_;
+ static int tests_being_run_;
+ static int current_;
+ static int active_tests_;
+ static bool NextThread();
+ int test_number_;
+ v8::internal::Semaphore* gate_;
+ bool active_;
+ void ContextSwitch();
+ static int GetNextTestNumber();
+ static v8::internal::Semaphore* all_tests_done_;
+};
+
+
+#define THREADED_TEST(Name) \
+ static void Test##Name(); \
+ RegisterThreadedTest register_##Name(Test##Name, #Name); \
+ /* */ TEST(Name)
+
+
+class RegisterThreadedTest {
+ public:
+ explicit RegisterThreadedTest(CcTest::TestFunction* callback,
+ const char* name)
+ : fuzzer_(NULL), callback_(callback), name_(name) {
+ prev_ = first_;
+ first_ = this;
+ count_++;
+ }
+ static int count() { return count_; }
+ static RegisterThreadedTest* nth(int i) {
+ CHECK(i < count());
+ RegisterThreadedTest* current = first_;
+ while (i > 0) {
+ i--;
+ current = current->prev_;
+ }
+ return current;
+ }
+ CcTest::TestFunction* callback() { return callback_; }
+ ApiTestFuzzer* fuzzer_;
+ const char* name() { return name_; }
+
+ private:
+ static RegisterThreadedTest* first_;
+ static int count_;
+ CcTest::TestFunction* callback_;
+ RegisterThreadedTest* prev_;
+ const char* name_;
+};
+
+
+// A LocalContext holds a reference to a v8::Context.
+class LocalContext {
+ public:
+ LocalContext(v8::ExtensionConfiguration* extensions = 0,
+ v8::Handle<v8::ObjectTemplate> global_template =
+ v8::Handle<v8::ObjectTemplate>(),
+ v8::Handle<v8::Value> global_object = v8::Handle<v8::Value>())
+ : context_(v8::Context::New(extensions, global_template, global_object)) {
+ context_->Enter();
+ }
+
+ virtual ~LocalContext() {
+ context_->Exit();
+ context_.Dispose();
+ }
+
+ v8::Context* operator->() { return *context_; }
+ v8::Context* operator*() { return *context_; }
+ bool IsReady() { return !context_.IsEmpty(); }
+
+ v8::Local<v8::Context> local() {
+ return v8::Local<v8::Context>::New(context_);
+ }
+
+ private:
+ v8::Persistent<v8::Context> context_;
+};
+
+
+static inline v8::Local<v8::Value> v8_num(double x) {
+ return v8::Number::New(x);
+}
+
+
+static inline v8::Local<v8::String> v8_str(const char* x) {
+ return v8::String::New(x);
+}
+
+
+static inline v8::Local<v8::Script> v8_compile(const char* x) {
+ return v8::Script::Compile(v8_str(x));
+}
+
+
+// Helper function that compiles and runs the source.
+static inline v8::Local<v8::Value> CompileRun(const char* source) {
+ return v8::Script::Compile(v8::String::New(source))->Run();
+}
+
+
#endif // ifndef CCTEST_H_
diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status
index b43cd64..a143cbd 100644
--- a/test/cctest/cctest.status
+++ b/test/cctest/cctest.status
@@ -33,12 +33,6 @@
# BUG(382): Weird test. Can't guarantee that it never times out.
test-api/ApplyInterruption: PASS || TIMEOUT
-# This is about to go away anyway since new snapshot code is on the way.
-test-serialize/Deserialize: FAIL
-test-serialize/DeserializeAndRunScript: FAIL
-test-serialize/DeserializeNatives: FAIL
-test-serialize/DeserializeExtensions: FAIL
-
# These tests always fail. They are here to test test.py. If
# they don't fail then test.py has failed.
test-serialize/TestThatAlwaysFails: FAIL
@@ -47,9 +41,6 @@
[ $arch == arm ]
-# BUG(113): Test seems flaky on ARM.
-test-spaces/LargeObjectSpace: PASS || FAIL
-
# BUG(240): Test seems flaky on ARM.
test-api/RegExpInterruption: SKIP
@@ -61,11 +52,3 @@
# BUG(355): Test crashes on ARM.
test-log/ProfLazyMode: SKIP
-
-[ $simulator == arm ]
-
-# BUG(271): During exception propagation, we compare pointers into the
-# stack. These tests fail on the ARM simulator because the C++ and
-# the JavaScript stacks are separate.
-test-api/ExceptionOrder: FAIL
-test-api/TryCatchInTryFinally: FAIL
diff --git a/test/cctest/test-accessors.cc b/test/cctest/test-accessors.cc
new file mode 100644
index 0000000..25f5c39
--- /dev/null
+++ b/test/cctest/test-accessors.cc
@@ -0,0 +1,450 @@
+// 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.
+
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "api.h"
+#include "cctest.h"
+#include "frames-inl.h"
+#include "string-stream.h"
+
+using ::v8::ObjectTemplate;
+using ::v8::Value;
+using ::v8::Context;
+using ::v8::Local;
+using ::v8::String;
+using ::v8::Script;
+using ::v8::Function;
+using ::v8::AccessorInfo;
+using ::v8::Extension;
+
+namespace i = ::v8::internal;
+
+static v8::Handle<Value> handle_property(Local<String> name,
+ const AccessorInfo&) {
+ ApiTestFuzzer::Fuzz();
+ return v8_num(900);
+}
+
+
+THREADED_TEST(PropertyHandler) {
+ v8::HandleScope scope;
+ Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
+ fun_templ->InstanceTemplate()->SetAccessor(v8_str("foo"), handle_property);
+ LocalContext env;
+ Local<Function> fun = fun_templ->GetFunction();
+ env->Global()->Set(v8_str("Fun"), fun);
+ Local<Script> getter = v8_compile("var obj = new Fun(); obj.foo;");
+ CHECK_EQ(900, getter->Run()->Int32Value());
+ Local<Script> setter = v8_compile("obj.foo = 901;");
+ CHECK_EQ(901, setter->Run()->Int32Value());
+}
+
+
+static v8::Handle<Value> GetIntValue(Local<String> property,
+ const AccessorInfo& info) {
+ ApiTestFuzzer::Fuzz();
+ int* value =
+ static_cast<int*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
+ return v8_num(*value);
+}
+
+
+static void SetIntValue(Local<String> property,
+ Local<Value> value,
+ const AccessorInfo& info) {
+ int* field =
+ static_cast<int*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
+ *field = value->Int32Value();
+}
+
+int foo, bar, baz;
+
+THREADED_TEST(GlobalVariableAccess) {
+ foo = 0;
+ bar = -4;
+ baz = 10;
+ v8::HandleScope scope;
+ v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
+ templ->InstanceTemplate()->SetAccessor(v8_str("foo"),
+ GetIntValue,
+ SetIntValue,
+ v8::External::New(&foo));
+ templ->InstanceTemplate()->SetAccessor(v8_str("bar"),
+ GetIntValue,
+ SetIntValue,
+ v8::External::New(&bar));
+ templ->InstanceTemplate()->SetAccessor(v8_str("baz"),
+ GetIntValue,
+ SetIntValue,
+ v8::External::New(&baz));
+ LocalContext env(0, templ->InstanceTemplate());
+ v8_compile("foo = (++bar) + baz")->Run();
+ CHECK_EQ(bar, -3);
+ CHECK_EQ(foo, 7);
+}
+
+
+static int x_register = 0;
+static v8::Handle<v8::Object> x_receiver;
+static v8::Handle<v8::Object> x_holder;
+
+
+static v8::Handle<Value> XGetter(Local<String> name, const AccessorInfo& info) {
+ ApiTestFuzzer::Fuzz();
+ CHECK_EQ(x_receiver, info.This());
+ CHECK_EQ(x_holder, info.Holder());
+ return v8_num(x_register);
+}
+
+
+static void XSetter(Local<String> name,
+ Local<Value> value,
+ const AccessorInfo& info) {
+ CHECK_EQ(x_holder, info.This());
+ CHECK_EQ(x_holder, info.Holder());
+ x_register = value->Int32Value();
+}
+
+
+THREADED_TEST(AccessorIC) {
+ v8::HandleScope scope;
+ v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+ obj->SetAccessor(v8_str("x"), XGetter, XSetter);
+ LocalContext context;
+ x_holder = obj->NewInstance();
+ context->Global()->Set(v8_str("holder"), x_holder);
+ x_receiver = v8::Object::New();
+ context->Global()->Set(v8_str("obj"), x_receiver);
+ v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(CompileRun(
+ "obj.__proto__ = holder;"
+ "var result = [];"
+ "for (var i = 0; i < 10; i++) {"
+ " holder.x = i;"
+ " result.push(obj.x);"
+ "}"
+ "result"));
+ CHECK_EQ(10, array->Length());
+ for (int i = 0; i < 10; i++) {
+ v8::Handle<Value> entry = array->Get(v8::Integer::New(i));
+ CHECK_EQ(v8::Integer::New(i), entry);
+ }
+}
+
+
+static v8::Handle<Value> AccessorProhibitsOverwritingGetter(
+ Local<String> name,
+ const AccessorInfo& info) {
+ ApiTestFuzzer::Fuzz();
+ return v8::True();
+}
+
+
+THREADED_TEST(AccessorProhibitsOverwriting) {
+ v8::HandleScope scope;
+ LocalContext context;
+ Local<ObjectTemplate> templ = ObjectTemplate::New();
+ templ->SetAccessor(v8_str("x"),
+ AccessorProhibitsOverwritingGetter,
+ 0,
+ v8::Handle<Value>(),
+ v8::PROHIBITS_OVERWRITING,
+ v8::ReadOnly);
+ Local<v8::Object> instance = templ->NewInstance();
+ context->Global()->Set(v8_str("obj"), instance);
+ Local<Value> value = CompileRun(
+ "obj.__defineGetter__('x', function() { return false; });"
+ "obj.x");
+ CHECK(value->BooleanValue());
+ value = CompileRun(
+ "var setter_called = false;"
+ "obj.__defineSetter__('x', function() { setter_called = true; });"
+ "obj.x = 42;"
+ "setter_called");
+ CHECK(!value->BooleanValue());
+ value = CompileRun(
+ "obj2 = {};"
+ "obj2.__proto__ = obj;"
+ "obj2.__defineGetter__('x', function() { return false; });"
+ "obj2.x");
+ CHECK(value->BooleanValue());
+ value = CompileRun(
+ "var setter_called = false;"
+ "obj2 = {};"
+ "obj2.__proto__ = obj;"
+ "obj2.__defineSetter__('x', function() { setter_called = true; });"
+ "obj2.x = 42;"
+ "setter_called");
+ CHECK(!value->BooleanValue());
+}
+
+
+template <int C>
+static v8::Handle<Value> HandleAllocatingGetter(Local<String> name,
+ const AccessorInfo& info) {
+ ApiTestFuzzer::Fuzz();
+ for (int i = 0; i < C; i++)
+ v8::String::New("foo");
+ return v8::String::New("foo");
+}
+
+
+THREADED_TEST(HandleScopePop) {
+ v8::HandleScope scope;
+ v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+ obj->SetAccessor(v8_str("one"), HandleAllocatingGetter<1>);
+ obj->SetAccessor(v8_str("many"), HandleAllocatingGetter<1024>);
+ LocalContext context;
+ v8::Handle<v8::Object> inst = obj->NewInstance();
+ context->Global()->Set(v8::String::New("obj"), inst);
+ int count_before = i::HandleScope::NumberOfHandles();
+ {
+ v8::HandleScope scope;
+ CompileRun(
+ "for (var i = 0; i < 1000; i++) {"
+ " obj.one;"
+ " obj.many;"
+ "}");
+ }
+ int count_after = i::HandleScope::NumberOfHandles();
+ CHECK_EQ(count_before, count_after);
+}
+
+static v8::Handle<Value> CheckAccessorArgsCorrect(Local<String> name,
+ const AccessorInfo& info) {
+ CHECK(info.This() == info.Holder());
+ CHECK(info.Data()->Equals(v8::String::New("data")));
+ ApiTestFuzzer::Fuzz();
+ CHECK(info.This() == info.Holder());
+ CHECK(info.Data()->Equals(v8::String::New("data")));
+ i::Heap::CollectAllGarbage(true);
+ CHECK(info.This() == info.Holder());
+ CHECK(info.Data()->Equals(v8::String::New("data")));
+ return v8::Integer::New(17);
+}
+
+THREADED_TEST(DirectCall) {
+ v8::HandleScope scope;
+ v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+ obj->SetAccessor(v8_str("xxx"),
+ CheckAccessorArgsCorrect,
+ NULL,
+ v8::String::New("data"));
+ LocalContext context;
+ v8::Handle<v8::Object> inst = obj->NewInstance();
+ context->Global()->Set(v8::String::New("obj"), inst);
+ Local<Script> scr = v8::Script::Compile(v8::String::New("obj.xxx"));
+ for (int i = 0; i < 10; i++) {
+ Local<Value> result = scr->Run();
+ CHECK(!result.IsEmpty());
+ CHECK_EQ(17, result->Int32Value());
+ }
+}
+
+static v8::Handle<Value> EmptyGetter(Local<String> name,
+ const AccessorInfo& info) {
+ CheckAccessorArgsCorrect(name, info);
+ ApiTestFuzzer::Fuzz();
+ CheckAccessorArgsCorrect(name, info);
+ return v8::Handle<v8::Value>();
+}
+
+THREADED_TEST(EmptyResult) {
+ v8::HandleScope scope;
+ v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+ obj->SetAccessor(v8_str("xxx"), EmptyGetter, NULL, v8::String::New("data"));
+ LocalContext context;
+ v8::Handle<v8::Object> inst = obj->NewInstance();
+ context->Global()->Set(v8::String::New("obj"), inst);
+ Local<Script> scr = v8::Script::Compile(v8::String::New("obj.xxx"));
+ for (int i = 0; i < 10; i++) {
+ Local<Value> result = scr->Run();
+ CHECK(result == v8::Undefined());
+ }
+}
+
+
+THREADED_TEST(NoReuseRegress) {
+ // Check that the IC generated for the one test doesn't get reused
+ // for the other.
+ v8::HandleScope scope;
+ {
+ v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+ obj->SetAccessor(v8_str("xxx"), EmptyGetter, NULL, v8::String::New("data"));
+ LocalContext context;
+ v8::Handle<v8::Object> inst = obj->NewInstance();
+ context->Global()->Set(v8::String::New("obj"), inst);
+ Local<Script> scr = v8::Script::Compile(v8::String::New("obj.xxx"));
+ for (int i = 0; i < 2; i++) {
+ Local<Value> result = scr->Run();
+ CHECK(result == v8::Undefined());
+ }
+ }
+ {
+ v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+ obj->SetAccessor(v8_str("xxx"),
+ CheckAccessorArgsCorrect,
+ NULL,
+ v8::String::New("data"));
+ LocalContext context;
+ v8::Handle<v8::Object> inst = obj->NewInstance();
+ context->Global()->Set(v8::String::New("obj"), inst);
+ Local<Script> scr = v8::Script::Compile(v8::String::New("obj.xxx"));
+ for (int i = 0; i < 10; i++) {
+ Local<Value> result = scr->Run();
+ CHECK(!result.IsEmpty());
+ CHECK_EQ(17, result->Int32Value());
+ }
+ }
+}
+
+static v8::Handle<Value> ThrowingGetAccessor(Local<String> name,
+ const AccessorInfo& info) {
+ ApiTestFuzzer::Fuzz();
+ return v8::ThrowException(v8_str("g"));
+}
+
+
+static void ThrowingSetAccessor(Local<String> name,
+ Local<Value> value,
+ const AccessorInfo& info) {
+ v8::ThrowException(value);
+}
+
+
+THREADED_TEST(Regress1054726) {
+ v8::HandleScope scope;
+ v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+ obj->SetAccessor(v8_str("x"),
+ ThrowingGetAccessor,
+ ThrowingSetAccessor,
+ Local<Value>());
+
+ LocalContext env;
+ env->Global()->Set(v8_str("obj"), obj->NewInstance());
+
+ // Use the throwing property setter/getter in a loop to force
+ // the accessor ICs to be initialized.
+ v8::Handle<Value> result;
+ result = Script::Compile(v8_str(
+ "var result = '';"
+ "for (var i = 0; i < 5; i++) {"
+ " try { obj.x; } catch (e) { result += e; }"
+ "}; result"))->Run();
+ CHECK_EQ(v8_str("ggggg"), result);
+
+ result = Script::Compile(String::New(
+ "var result = '';"
+ "for (var i = 0; i < 5; i++) {"
+ " try { obj.x = i; } catch (e) { result += e; }"
+ "}; result"))->Run();
+ CHECK_EQ(v8_str("01234"), result);
+}
+
+
+static v8::Handle<Value> AllocGetter(Local<String> name,
+ const AccessorInfo& info) {
+ ApiTestFuzzer::Fuzz();
+ return v8::Array::New(1000);
+}
+
+
+THREADED_TEST(Gc) {
+ v8::HandleScope scope;
+ v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+ obj->SetAccessor(v8_str("xxx"), AllocGetter);
+ LocalContext env;
+ env->Global()->Set(v8_str("obj"), obj->NewInstance());
+ Script::Compile(String::New(
+ "var last = [];"
+ "for (var i = 0; i < 2048; i++) {"
+ " var result = obj.xxx;"
+ " result[0] = last;"
+ " last = result;"
+ "}"))->Run();
+}
+
+
+static v8::Handle<Value> StackCheck(Local<String> name,
+ const AccessorInfo& info) {
+ i::StackFrameIterator iter;
+ for (int i = 0; !iter.done(); i++) {
+ i::StackFrame* frame = iter.frame();
+ CHECK(i != 0 || (frame->type() == i::StackFrame::EXIT));
+ CHECK(frame->code()->IsCode());
+ i::Address pc = frame->pc();
+ i::Code* code = frame->code();
+ CHECK(code->contains(pc));
+ iter.Advance();
+ }
+ return v8::Undefined();
+}
+
+
+THREADED_TEST(StackIteration) {
+ v8::HandleScope scope;
+ v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+ i::StringStream::ClearMentionedObjectCache();
+ obj->SetAccessor(v8_str("xxx"), StackCheck);
+ LocalContext env;
+ env->Global()->Set(v8_str("obj"), obj->NewInstance());
+ Script::Compile(String::New(
+ "function foo() {"
+ " return obj.xxx;"
+ "}"
+ "for (var i = 0; i < 100; i++) {"
+ " foo();"
+ "}"))->Run();
+}
+
+
+static v8::Handle<Value> AllocateHandles(Local<String> name,
+ const AccessorInfo& info) {
+ for (int i = 0; i < i::kHandleBlockSize + 1; i++) {
+ v8::Local<v8::Value>::New(name);
+ }
+ return v8::Integer::New(100);
+}
+
+
+THREADED_TEST(HandleScopeSegment) {
+ // Check that we can return values past popping of handle scope
+ // segments.
+ v8::HandleScope scope;
+ v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+ obj->SetAccessor(v8_str("xxx"), AllocateHandles);
+ LocalContext env;
+ env->Global()->Set(v8_str("obj"), obj->NewInstance());
+ v8::Handle<v8::Value> result = Script::Compile(String::New(
+ "var result;"
+ "for (var i = 0; i < 4; i++)"
+ " result = obj.xxx;"
+ "result;"))->Run();
+ CHECK_EQ(100, result->Int32Value());
+}
diff --git a/test/cctest/test-alloc.cc b/test/cctest/test-alloc.cc
index 1235b13..315a34e 100644
--- a/test/cctest/test-alloc.cc
+++ b/test/cctest/test-alloc.cc
@@ -65,9 +65,9 @@
// Old data space.
OldSpace* old_data_space = Heap::old_data_space();
- static const int kOldDataSpaceFillerSize = SeqAsciiString::SizeFor(0);
+ static const int kOldDataSpaceFillerSize = ByteArray::SizeFor(0);
while (old_data_space->Available() > kOldDataSpaceFillerSize) {
- CHECK(!Heap::AllocateRawAsciiString(0, TENURED)->IsFailure());
+ CHECK(!Heap::AllocateByteArray(0, TENURED)->IsFailure());
}
CHECK(!Heap::AllocateRawAsciiString(100, TENURED)->IsFailure());
@@ -195,9 +195,9 @@
Pseudorandom() % 5000 + 1;
size_t allocated = 0;
void* base = CodeRange::AllocateRawMemory(requested, &allocated);
- blocks.Add(Block(base, allocated));
- current_allocated += allocated;
- total_allocated += allocated;
+ blocks.Add(Block(base, static_cast<int>(allocated)));
+ current_allocated += static_cast<int>(allocated);
+ total_allocated += static_cast<int>(allocated);
} else {
// Free a block.
int index = Pseudorandom() % blocks.length();
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index a943f30..6d6c174 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -38,6 +38,8 @@
#include "utils.h"
#include "cctest.h"
+static const bool kLogThreading = false;
+
static bool IsNaN(double x) {
#ifdef WIN32
return _isnan(x);
@@ -58,131 +60,6 @@
namespace i = ::v8::internal;
-static Local<Value> v8_num(double x) {
- return v8::Number::New(x);
-}
-
-
-static Local<String> v8_str(const char* x) {
- return String::New(x);
-}
-
-
-static Local<Script> v8_compile(const char* x) {
- return Script::Compile(v8_str(x));
-}
-
-
-// A LocalContext holds a reference to a v8::Context.
-class LocalContext {
- public:
- LocalContext(v8::ExtensionConfiguration* extensions = 0,
- v8::Handle<ObjectTemplate> global_template =
- v8::Handle<ObjectTemplate>(),
- v8::Handle<Value> global_object = v8::Handle<Value>())
- : context_(Context::New(extensions, global_template, global_object)) {
- context_->Enter();
- }
-
- virtual ~LocalContext() {
- context_->Exit();
- context_.Dispose();
- }
-
- Context* operator->() { return *context_; }
- Context* operator*() { return *context_; }
- Local<Context> local() { return Local<Context>::New(context_); }
- bool IsReady() { return !context_.IsEmpty(); }
-
- private:
- v8::Persistent<Context> context_;
-};
-
-
-// Switches between all the Api tests using the threading support.
-// In order to get a surprising but repeatable pattern of thread
-// switching it has extra semaphores to control the order in which
-// the tests alternate, not relying solely on the big V8 lock.
-//
-// A test is augmented with calls to ApiTestFuzzer::Fuzz() in its
-// callbacks. This will have no effect when we are not running the
-// thread fuzzing test. In the thread fuzzing test it will
-// pseudorandomly select a successor thread and switch execution
-// to that thread, suspending the current test.
-class ApiTestFuzzer: public v8::internal::Thread {
- public:
- void CallTest();
- explicit ApiTestFuzzer(int num)
- : test_number_(num),
- gate_(v8::internal::OS::CreateSemaphore(0)),
- active_(true) {
- }
- ~ApiTestFuzzer() { delete gate_; }
-
- // The ApiTestFuzzer is also a Thread, so it has a Run method.
- virtual void Run();
-
- enum PartOfTest { FIRST_PART, SECOND_PART };
-
- static void Setup(PartOfTest part);
- static void RunAllTests();
- static void TearDown();
- // This method switches threads if we are running the Threading test.
- // Otherwise it does nothing.
- static void Fuzz();
- private:
- static bool fuzzing_;
- static int tests_being_run_;
- static int current_;
- static int active_tests_;
- static bool NextThread();
- int test_number_;
- v8::internal::Semaphore* gate_;
- bool active_;
- void ContextSwitch();
- static int GetNextTestNumber();
- static v8::internal::Semaphore* all_tests_done_;
-};
-
-
-#define THREADED_TEST(Name) \
- static void Test##Name(); \
- RegisterThreadedTest register_##Name(Test##Name); \
- /* */ TEST(Name)
-
-
-class RegisterThreadedTest {
- public:
- explicit RegisterThreadedTest(CcTest::TestFunction* callback)
- : fuzzer_(NULL), callback_(callback) {
- prev_ = first_;
- first_ = this;
- count_++;
- }
- static int count() { return count_; }
- static RegisterThreadedTest* nth(int i) {
- CHECK(i < count());
- RegisterThreadedTest* current = first_;
- while (i > 0) {
- i--;
- current = current->prev_;
- }
- return current;
- }
- CcTest::TestFunction* callback() { return callback_; }
- ApiTestFuzzer* fuzzer_;
-
- private:
- static RegisterThreadedTest* first_;
- static int count_;
- CcTest::TestFunction* callback_;
- RegisterThreadedTest* prev_;
-};
-
-
-RegisterThreadedTest *RegisterThreadedTest::first_ = NULL;
-int RegisterThreadedTest::count_ = 0;
-
static int signature_callback_count;
static v8::Handle<Value> IncrementingSignatureCallback(
@@ -231,11 +108,6 @@
}
-// Helper function that compiles and runs the source.
-static Local<Value> CompileRun(const char* source) {
- return Script::Compile(String::New(source))->Run();
-}
-
THREADED_TEST(ReceiverSignature) {
v8::HandleScope scope;
LocalContext env;
@@ -382,9 +254,9 @@
static uint16_t* AsciiToTwoByteString(const char* source) {
- size_t array_length = strlen(source) + 1;
+ int array_length = i::StrLength(source) + 1;
uint16_t* converted = i::NewArray<uint16_t>(array_length);
- for (size_t i = 0; i < array_length; i++) converted[i] = source[i];
+ for (int i = 0; i < array_length; i++) converted[i] = source[i];
return converted;
}
@@ -720,27 +592,6 @@
}
-static v8::Handle<Value> handle_property(Local<String> name,
- const AccessorInfo&) {
- ApiTestFuzzer::Fuzz();
- return v8_num(900);
-}
-
-
-THREADED_TEST(PropertyHandler) {
- v8::HandleScope scope;
- Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
- fun_templ->InstanceTemplate()->SetAccessor(v8_str("foo"), handle_property);
- LocalContext env;
- Local<Function> fun = fun_templ->GetFunction();
- env->Global()->Set(v8_str("Fun"), fun);
- Local<Script> getter = v8_compile("var obj = new Fun(); obj.foo;");
- CHECK_EQ(900, getter->Run()->Int32Value());
- Local<Script> setter = v8_compile("obj.foo = 901;");
- CHECK_EQ(901, setter->Run()->Int32Value());
-}
-
-
THREADED_TEST(TinyInteger) {
v8::HandleScope scope;
LocalContext env;
@@ -907,49 +758,6 @@
}
-static v8::Handle<Value> GetIntValue(Local<String> property,
- const AccessorInfo& info) {
- ApiTestFuzzer::Fuzz();
- int* value =
- static_cast<int*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
- return v8_num(*value);
-}
-
-static void SetIntValue(Local<String> property,
- Local<Value> value,
- const AccessorInfo& info) {
- int* field =
- static_cast<int*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
- *field = value->Int32Value();
-}
-
-int foo, bar, baz;
-
-THREADED_TEST(GlobalVariableAccess) {
- foo = 0;
- bar = -4;
- baz = 10;
- v8::HandleScope scope;
- v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
- templ->InstanceTemplate()->SetAccessor(v8_str("foo"),
- GetIntValue,
- SetIntValue,
- v8::External::New(&foo));
- templ->InstanceTemplate()->SetAccessor(v8_str("bar"),
- GetIntValue,
- SetIntValue,
- v8::External::New(&bar));
- templ->InstanceTemplate()->SetAccessor(v8_str("baz"),
- GetIntValue,
- SetIntValue,
- v8::External::New(&baz));
- LocalContext env(0, templ->InstanceTemplate());
- v8_compile("foo = (++bar) + baz")->Run();
- CHECK_EQ(bar, -3);
- CHECK_EQ(foo, 7);
-}
-
-
THREADED_TEST(ObjectTemplate) {
v8::HandleScope scope;
Local<ObjectTemplate> templ1 = ObjectTemplate::New();
@@ -1365,50 +1173,6 @@
}
-static v8::Handle<Value> ThrowingGetAccessor(Local<String> name,
- const AccessorInfo& info) {
- ApiTestFuzzer::Fuzz();
- return v8::ThrowException(v8_str("g"));
-}
-
-
-static void ThrowingSetAccessor(Local<String> name,
- Local<Value> value,
- const AccessorInfo& info) {
- v8::ThrowException(value);
-}
-
-
-THREADED_TEST(Regress1054726) {
- v8::HandleScope scope;
- v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
- obj->SetAccessor(v8_str("x"),
- ThrowingGetAccessor,
- ThrowingSetAccessor,
- Local<Value>());
-
- LocalContext env;
- env->Global()->Set(v8_str("obj"), obj->NewInstance());
-
- // Use the throwing property setter/getter in a loop to force
- // the accessor ICs to be initialized.
- v8::Handle<Value> result;
- result = Script::Compile(v8_str(
- "var result = '';"
- "for (var i = 0; i < 5; i++) {"
- " try { obj.x; } catch (e) { result += e; }"
- "}; result"))->Run();
- CHECK_EQ(v8_str("ggggg"), result);
-
- result = Script::Compile(String::New(
- "var result = '';"
- "for (var i = 0; i < 5; i++) {"
- " try { obj.x = i; } catch (e) { result += e; }"
- "}; result"))->Run();
- CHECK_EQ(v8_str("01234"), result);
-}
-
-
THREADED_TEST(FunctionPrototype) {
v8::HandleScope scope;
Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New();
@@ -1580,17 +1344,10 @@
}
+static bool interceptor_for_hidden_properties_called;
static v8::Handle<Value> InterceptorForHiddenProperties(
Local<String> name, const AccessorInfo& info) {
- // Make sure objects move.
- bool saved_always_compact = i::FLAG_always_compact;
- if (!i::FLAG_never_compact) {
- i::FLAG_always_compact = true;
- }
- // The whole goal of this interceptor is to cause a GC during local property
- // lookup.
- i::Heap::CollectAllGarbage(false);
- i::FLAG_always_compact = saved_always_compact;
+ interceptor_for_hidden_properties_called = true;
return v8::Handle<Value>();
}
@@ -1599,6 +1356,8 @@
v8::HandleScope scope;
LocalContext context;
+ interceptor_for_hidden_properties_called = false;
+
v8::Local<v8::String> key = v8_str("api-test::hidden-key");
// Associate an interceptor with an object and start setting hidden values.
@@ -1609,6 +1368,7 @@
Local<v8::Object> obj = function->NewInstance();
CHECK(obj->SetHiddenValue(key, v8::Integer::New(2302)));
CHECK_EQ(2302, obj->GetHiddenValue(key)->Int32Value());
+ CHECK(!interceptor_for_hidden_properties_called);
}
@@ -2910,6 +2670,40 @@
}
+static const char* kSyntaxErrorInExtensionSource =
+ "[";
+
+
+// Test that a syntax error in an extension does not cause a fatal
+// error but results in an empty context.
+THREADED_TEST(SyntaxErrorExtensions) {
+ v8::HandleScope handle_scope;
+ v8::RegisterExtension(new Extension("syntaxerror",
+ kSyntaxErrorInExtensionSource));
+ const char* extension_names[] = { "syntaxerror" };
+ v8::ExtensionConfiguration extensions(1, extension_names);
+ v8::Handle<Context> context = Context::New(&extensions);
+ CHECK(context.IsEmpty());
+}
+
+
+static const char* kExceptionInExtensionSource =
+ "throw 42";
+
+
+// Test that an exception when installing an extension does not cause
+// a fatal error but results in an empty context.
+THREADED_TEST(ExceptionExtensions) {
+ v8::HandleScope handle_scope;
+ v8::RegisterExtension(new Extension("exception",
+ kExceptionInExtensionSource));
+ const char* extension_names[] = { "exception" };
+ v8::ExtensionConfiguration extensions(1, extension_names);
+ v8::Handle<Context> context = Context::New(&extensions);
+ CHECK(context.IsEmpty());
+}
+
+
static void CheckDependencies(const char* name, const char* expected) {
v8::HandleScope handle_scope;
v8::ExtensionConfiguration config(1, &name);
@@ -3157,6 +2951,58 @@
}
+static bool in_scavenge = false;
+static int last = -1;
+
+static void ForceScavenge(v8::Persistent<v8::Value> obj, void* data) {
+ CHECK_EQ(-1, last);
+ last = 0;
+ obj.Dispose();
+ obj.Clear();
+ in_scavenge = true;
+ i::Heap::PerformScavenge();
+ in_scavenge = false;
+ *(reinterpret_cast<bool*>(data)) = true;
+}
+
+static void CheckIsNotInvokedInScavenge(v8::Persistent<v8::Value> obj,
+ void* data) {
+ CHECK_EQ(0, last);
+ last = 1;
+ *(reinterpret_cast<bool*>(data)) = in_scavenge;
+ obj.Dispose();
+ obj.Clear();
+}
+
+THREADED_TEST(NoWeakRefCallbacksInScavenge) {
+ // Test verifies that scavenge cannot invoke WeakReferenceCallbacks.
+ // Calling callbacks from scavenges is unsafe as objects held by those
+ // handlers might have become strongly reachable, but scavenge doesn't
+ // check that.
+ v8::Persistent<Context> context = Context::New();
+ Context::Scope context_scope(context);
+
+ v8::Persistent<v8::Object> object_a;
+ v8::Persistent<v8::Object> object_b;
+
+ {
+ v8::HandleScope handle_scope;
+ object_b = v8::Persistent<v8::Object>::New(v8::Object::New());
+ object_a = v8::Persistent<v8::Object>::New(v8::Object::New());
+ }
+
+ bool object_a_disposed = false;
+ object_a.MakeWeak(&object_a_disposed, &ForceScavenge);
+ bool released_in_scavenge = false;
+ object_b.MakeWeak(&released_in_scavenge, &CheckIsNotInvokedInScavenge);
+
+ while (!object_a_disposed) {
+ i::Heap::CollectAllGarbage(false);
+ }
+ CHECK(!released_in_scavenge);
+}
+
+
v8::Handle<Function> args_fun;
@@ -3184,53 +3030,6 @@
}
-static int x_register = 0;
-static v8::Handle<v8::Object> x_receiver;
-static v8::Handle<v8::Object> x_holder;
-
-
-static v8::Handle<Value> XGetter(Local<String> name, const AccessorInfo& info) {
- ApiTestFuzzer::Fuzz();
- CHECK_EQ(x_receiver, info.This());
- CHECK_EQ(x_holder, info.Holder());
- return v8_num(x_register);
-}
-
-
-static void XSetter(Local<String> name,
- Local<Value> value,
- const AccessorInfo& info) {
- CHECK_EQ(x_holder, info.This());
- CHECK_EQ(x_holder, info.Holder());
- x_register = value->Int32Value();
-}
-
-
-THREADED_TEST(AccessorIC) {
- v8::HandleScope scope;
- v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
- obj->SetAccessor(v8_str("x"), XGetter, XSetter);
- LocalContext context;
- x_holder = obj->NewInstance();
- context->Global()->Set(v8_str("holder"), x_holder);
- x_receiver = v8::Object::New();
- context->Global()->Set(v8_str("obj"), x_receiver);
- v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(CompileRun(
- "obj.__proto__ = holder;"
- "var result = [];"
- "for (var i = 0; i < 10; i++) {"
- " holder.x = i;"
- " result.push(obj.x);"
- "}"
- "result"));
- CHECK_EQ(10, array->Length());
- for (int i = 0; i < 10; i++) {
- v8::Handle<Value> entry = array->Get(v8::Integer::New(i));
- CHECK_EQ(v8::Integer::New(i), entry);
- }
-}
-
-
static v8::Handle<Value> NoBlockGetterX(Local<String> name,
const AccessorInfo&) {
return v8::Handle<Value>();
@@ -6094,13 +5893,17 @@
// not start immediately.
bool ApiTestFuzzer::NextThread() {
int test_position = GetNextTestNumber();
- int test_number = RegisterThreadedTest::nth(current_)->fuzzer_->test_number_;
+ const char* test_name = RegisterThreadedTest::nth(current_)->name();
if (test_position == current_) {
- printf("Stay with %d\n", test_number);
+ if (kLogThreading)
+ printf("Stay with %s\n", test_name);
return false;
}
- printf("Switch from %d to %d\n",
- current_ < 0 ? 0 : test_number, test_position < 0 ? 0 : test_number);
+ if (kLogThreading) {
+ printf("Switch from %s to %s\n",
+ test_name,
+ RegisterThreadedTest::nth(test_position)->name());
+ }
current_ = test_position;
RegisterThreadedTest::nth(current_)->fuzzer_->gate_->Signal();
return true;
@@ -6209,9 +6012,11 @@
void ApiTestFuzzer::CallTest() {
- printf("Start test %d\n", test_number_);
+ if (kLogThreading)
+ printf("Start test %d\n", test_number_);
CallTestNumber(test_number_);
- printf("End test %d\n", test_number_);
+ if (kLogThreading)
+ printf("End test %d\n", test_number_);
}
@@ -6455,6 +6260,31 @@
i::Heap::CollectAllGarbage(false);
}
+void DisposingCallback(v8::Persistent<v8::Value> handle, void*) {
+ handle.Dispose();
+}
+
+void HandleCreatingCallback(v8::Persistent<v8::Value> handle, void*) {
+ v8::HandleScope scope;
+ v8::Persistent<v8::Object>::New(v8::Object::New());
+}
+
+
+THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
+ LocalContext context;
+
+ v8::Persistent<v8::Object> handle1, handle2, handle3;
+ {
+ v8::HandleScope scope;
+ handle3 = v8::Persistent<v8::Object>::New(v8::Object::New());
+ handle2 = v8::Persistent<v8::Object>::New(v8::Object::New());
+ handle1 = v8::Persistent<v8::Object>::New(v8::Object::New());
+ }
+ handle2.MakeWeak(NULL, DisposingCallback);
+ handle3.MakeWeak(NULL, HandleCreatingCallback);
+ i::Heap::CollectAllGarbage(false);
+}
+
THREADED_TEST(CheckForCrossContextObjectLiterals) {
v8::V8::Initialize();
@@ -6699,53 +6529,6 @@
}
-static v8::Handle<Value> AccessorProhibitsOverwritingGetter(
- Local<String> name,
- const AccessorInfo& info) {
- ApiTestFuzzer::Fuzz();
- return v8::True();
-}
-
-
-THREADED_TEST(AccessorProhibitsOverwriting) {
- v8::HandleScope scope;
- LocalContext context;
- Local<ObjectTemplate> templ = ObjectTemplate::New();
- templ->SetAccessor(v8_str("x"),
- AccessorProhibitsOverwritingGetter,
- 0,
- v8::Handle<Value>(),
- v8::PROHIBITS_OVERWRITING,
- v8::ReadOnly);
- Local<v8::Object> instance = templ->NewInstance();
- context->Global()->Set(v8_str("obj"), instance);
- Local<Value> value = CompileRun(
- "obj.__defineGetter__('x', function() { return false; });"
- "obj.x");
- CHECK(value->BooleanValue());
- value = CompileRun(
- "var setter_called = false;"
- "obj.__defineSetter__('x', function() { setter_called = true; });"
- "obj.x = 42;"
- "setter_called");
- CHECK(!value->BooleanValue());
- value = CompileRun(
- "obj2 = {};"
- "obj2.__proto__ = obj;"
- "obj2.__defineGetter__('x', function() { return false; });"
- "obj2.x");
- CHECK(value->BooleanValue());
- value = CompileRun(
- "var setter_called = false;"
- "obj2 = {};"
- "obj2.__proto__ = obj;"
- "obj2.__defineSetter__('x', function() { setter_called = true; });"
- "obj2.x = 42;"
- "setter_called");
- CHECK(!value->BooleanValue());
-}
-
-
static bool NamedSetAccessBlocker(Local<v8::Object> obj,
Local<Value> name,
v8::AccessType type,
@@ -6921,7 +6704,8 @@
// a workaround for now to make this test not fail.
v8::V8::Initialize();
const char *script = "function foo(a) { return a+1; }";
- v8::ScriptData *sd = v8::ScriptData::PreCompile(script, strlen(script));
+ v8::ScriptData *sd =
+ v8::ScriptData::PreCompile(script, i::StrLength(script));
CHECK_NE(sd->Length(), 0);
CHECK_NE(sd->Data(), NULL);
delete sd;
@@ -7279,27 +7063,17 @@
CHECK(i::StringShape(string).IsExternal());
if (string->IsAsciiRepresentation()) {
// Check old map is not symbol or long.
- CHECK(string->map() == i::Heap::short_external_ascii_string_map() ||
- string->map() == i::Heap::medium_external_ascii_string_map());
+ CHECK(string->map() == i::Heap::external_ascii_string_map());
// Morph external string to be TwoByte string.
- if (string->length() <= i::String::kMaxShortStringSize) {
- string->set_map(i::Heap::short_external_string_map());
- } else {
- string->set_map(i::Heap::medium_external_string_map());
- }
+ string->set_map(i::Heap::external_string_map());
i::ExternalTwoByteString* morphed =
i::ExternalTwoByteString::cast(string);
morphed->set_resource(uc16_resource);
} else {
// Check old map is not symbol or long.
- CHECK(string->map() == i::Heap::short_external_string_map() ||
- string->map() == i::Heap::medium_external_string_map());
+ CHECK(string->map() == i::Heap::external_string_map());
// Morph external string to be ASCII string.
- if (string->length() <= i::String::kMaxShortStringSize) {
- string->set_map(i::Heap::short_external_ascii_string_map());
- } else {
- string->set_map(i::Heap::medium_external_ascii_string_map());
- }
+ string->set_map(i::Heap::external_ascii_string_map());
i::ExternalAsciiString* morphed =
i::ExternalAsciiString::cast(string);
morphed->set_resource(ascii_resource);
@@ -7317,9 +7091,10 @@
v8::HandleScope scope;
LocalContext env;
AsciiVectorResource ascii_resource(
- i::Vector<const char>(c_string, strlen(c_string)));
+ i::Vector<const char>(c_string, i::StrLength(c_string)));
UC16VectorResource uc16_resource(
- i::Vector<const uint16_t>(two_byte_string, strlen(c_string)));
+ i::Vector<const uint16_t>(two_byte_string,
+ i::StrLength(c_string)));
Local<String> lhs(v8::Utils::ToLocal(
i::Factory::NewExternalStringFromAscii(&ascii_resource)));
@@ -7377,7 +7152,8 @@
for (int i = 0; ascii_sources[i] != NULL; i++) {
uint16_t* two_byte_string = AsciiToTwoByteString(ascii_sources[i]);
UC16VectorResource uc16_resource(
- i::Vector<const uint16_t>(two_byte_string, strlen(ascii_sources[i])));
+ i::Vector<const uint16_t>(two_byte_string,
+ i::StrLength(ascii_sources[i])));
v8::Local<v8::String> source = v8::String::NewExternal(&uc16_resource);
v8::Script::Compile(source);
}
@@ -7863,18 +7639,18 @@
THREADED_TEST(PixelArray) {
v8::HandleScope scope;
LocalContext context;
- const int kElementCount = 40;
+ const int kElementCount = 260;
uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
i::Handle<i::PixelArray> pixels = i::Factory::NewPixelArray(kElementCount,
pixel_data);
i::Heap::CollectAllGarbage(false); // Force GC to trigger verification.
for (int i = 0; i < kElementCount; i++) {
- pixels->set(i, i);
+ pixels->set(i, i % 256);
}
i::Heap::CollectAllGarbage(false); // Force GC to trigger verification.
for (int i = 0; i < kElementCount; i++) {
- CHECK_EQ(i, pixels->get(i));
- CHECK_EQ(i, pixel_data[i]);
+ CHECK_EQ(i % 256, pixels->get(i));
+ CHECK_EQ(i % 256, pixel_data[i]);
}
v8::Handle<v8::Object> obj = v8::Object::New();
@@ -8038,6 +7814,15 @@
result = CompileRun("pixels[1] = 23;");
CHECK_EQ(23, result->Int32Value());
+ // Test for index greater than 255. Regression test for:
+ // http://code.google.com/p/chromium/issues/detail?id=26337.
+ result = CompileRun("pixels[256] = 255;");
+ CHECK_EQ(255, result->Int32Value());
+ result = CompileRun("var i = 0;"
+ "for (var j = 0; j < 8; j++) { i = pixels[256]; }"
+ "i");
+ CHECK_EQ(255, result->Int32Value());
+
free(pixel_data);
}
@@ -8298,6 +8083,85 @@
result = CompileRun("ext_array[1] = 23;");
CHECK_EQ(23, result->Int32Value());
+ // Test more complex manipulations which cause eax to contain values
+ // that won't be completely overwritten by loads from the arrays.
+ // This catches bugs in the instructions used for the KeyedLoadIC
+ // for byte and word types.
+ {
+ const int kXSize = 300;
+ const int kYSize = 300;
+ const int kLargeElementCount = kXSize * kYSize * 4;
+ ElementType* large_array_data =
+ static_cast<ElementType*>(malloc(kLargeElementCount * element_size));
+ i::Handle<ExternalArrayClass> large_array =
+ i::Handle<ExternalArrayClass>::cast(
+ i::Factory::NewExternalArray(kLargeElementCount,
+ array_type,
+ array_data));
+ v8::Handle<v8::Object> large_obj = v8::Object::New();
+ // Set the elements to be the external array.
+ large_obj->SetIndexedPropertiesToExternalArrayData(large_array_data,
+ array_type,
+ kLargeElementCount);
+ context->Global()->Set(v8_str("large_array"), large_obj);
+ // Initialize contents of a few rows.
+ for (int x = 0; x < 300; x++) {
+ int row = 0;
+ int offset = row * 300 * 4;
+ large_array_data[offset + 4 * x + 0] = (ElementType) 127;
+ large_array_data[offset + 4 * x + 1] = (ElementType) 0;
+ large_array_data[offset + 4 * x + 2] = (ElementType) 0;
+ large_array_data[offset + 4 * x + 3] = (ElementType) 127;
+ row = 150;
+ offset = row * 300 * 4;
+ large_array_data[offset + 4 * x + 0] = (ElementType) 127;
+ large_array_data[offset + 4 * x + 1] = (ElementType) 0;
+ large_array_data[offset + 4 * x + 2] = (ElementType) 0;
+ large_array_data[offset + 4 * x + 3] = (ElementType) 127;
+ row = 298;
+ offset = row * 300 * 4;
+ large_array_data[offset + 4 * x + 0] = (ElementType) 127;
+ large_array_data[offset + 4 * x + 1] = (ElementType) 0;
+ large_array_data[offset + 4 * x + 2] = (ElementType) 0;
+ large_array_data[offset + 4 * x + 3] = (ElementType) 127;
+ }
+ // The goal of the code below is to make "offset" large enough
+ // that the computation of the index (which goes into eax) has
+ // high bits set which will not be overwritten by a byte or short
+ // load.
+ result = CompileRun("var failed = false;"
+ "var offset = 0;"
+ "for (var i = 0; i < 300; i++) {"
+ " if (large_array[4 * i] != 127 ||"
+ " large_array[4 * i + 1] != 0 ||"
+ " large_array[4 * i + 2] != 0 ||"
+ " large_array[4 * i + 3] != 127) {"
+ " failed = true;"
+ " }"
+ "}"
+ "offset = 150 * 300 * 4;"
+ "for (var i = 0; i < 300; i++) {"
+ " if (large_array[offset + 4 * i] != 127 ||"
+ " large_array[offset + 4 * i + 1] != 0 ||"
+ " large_array[offset + 4 * i + 2] != 0 ||"
+ " large_array[offset + 4 * i + 3] != 127) {"
+ " failed = true;"
+ " }"
+ "}"
+ "offset = 298 * 300 * 4;"
+ "for (var i = 0; i < 300; i++) {"
+ " if (large_array[offset + 4 * i] != 127 ||"
+ " large_array[offset + 4 * i + 1] != 0 ||"
+ " large_array[offset + 4 * i + 2] != 0 ||"
+ " large_array[offset + 4 * i + 3] != 127) {"
+ " failed = true;"
+ " }"
+ "}"
+ "!failed;");
+ CHECK_EQ(true, result->BooleanValue());
+ free(large_array_data);
+ }
+
free(array_data);
}
@@ -8489,9 +8353,262 @@
v8::HandleScope scope;
LocalContext c1;
v8::HeapStatistics heap_statistics;
- CHECK_EQ(heap_statistics.total_heap_size(), 0);
- CHECK_EQ(heap_statistics.used_heap_size(), 0);
+ CHECK_EQ(static_cast<int>(heap_statistics.total_heap_size()), 0);
+ CHECK_EQ(static_cast<int>(heap_statistics.used_heap_size()), 0);
v8::V8::GetHeapStatistics(&heap_statistics);
- CHECK_NE(heap_statistics.total_heap_size(), 0);
- CHECK_NE(heap_statistics.used_heap_size(), 0);
+ CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
+ CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
+}
+
+
+static double DoubleFromBits(uint64_t value) {
+ double target;
+#ifdef BIG_ENDIAN_FLOATING_POINT
+ const int kIntSize = 4;
+ // Somebody swapped the lower and higher half of doubles.
+ memcpy(&target, reinterpret_cast<char*>(&value) + kIntSize, kIntSize);
+ memcpy(reinterpret_cast<char*>(&target) + kIntSize, &value, kIntSize);
+#else
+ memcpy(&target, &value, sizeof(target));
+#endif
+ return target;
+}
+
+
+static uint64_t DoubleToBits(double value) {
+ uint64_t target;
+#ifdef BIG_ENDIAN_FLOATING_POINT
+ const int kIntSize = 4;
+ // Somebody swapped the lower and higher half of doubles.
+ memcpy(&target, reinterpret_cast<char*>(&value) + kIntSize, kIntSize);
+ memcpy(reinterpret_cast<char*>(&target) + kIntSize, &value, kIntSize);
+#else
+ memcpy(&target, &value, sizeof(target));
+#endif
+ return target;
+}
+
+
+static double DoubleToDateTime(double input) {
+ double date_limit = 864e13;
+ if (IsNaN(input) || input < -date_limit || input > date_limit) {
+ return i::OS::nan_value();
+ }
+ return (input < 0) ? -(floor(-input)) : floor(input);
+}
+
+// We don't have a consistent way to write 64-bit constants syntactically, so we
+// split them into two 32-bit constants and combine them programmatically.
+static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
+ return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
+}
+
+
+THREADED_TEST(QuietSignalingNaNs) {
+ v8::HandleScope scope;
+ LocalContext context;
+ v8::TryCatch try_catch;
+
+ // Special double values.
+ double snan = DoubleFromBits(0x7ff00000, 0x00000001);
+ double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
+ double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
+ double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
+ double min_normal = DoubleFromBits(0x00100000, 0x00000000);
+ double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
+ double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
+
+ // Date values are capped at +/-100000000 days (times 864e5 ms per day)
+ // on either side of the epoch.
+ double date_limit = 864e13;
+
+ double test_values[] = {
+ snan,
+ qnan,
+ infinity,
+ max_normal,
+ date_limit + 1,
+ date_limit,
+ min_normal,
+ max_denormal,
+ min_denormal,
+ 0,
+ -0,
+ -min_denormal,
+ -max_denormal,
+ -min_normal,
+ -date_limit,
+ -date_limit - 1,
+ -max_normal,
+ -infinity,
+ -qnan,
+ -snan
+ };
+ int num_test_values = 20;
+
+ for (int i = 0; i < num_test_values; i++) {
+ double test_value = test_values[i];
+
+ // Check that Number::New preserves non-NaNs and quiets SNaNs.
+ v8::Handle<v8::Value> number = v8::Number::New(test_value);
+ double stored_number = number->NumberValue();
+ if (!IsNaN(test_value)) {
+ CHECK_EQ(test_value, stored_number);
+ } else {
+ uint64_t stored_bits = DoubleToBits(stored_number);
+ // Check if quiet nan (bits 51..62 all set).
+ CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
+ }
+
+ // Check that Date::New preserves non-NaNs in the date range and
+ // quiets SNaNs.
+ v8::Handle<v8::Value> date = v8::Date::New(test_value);
+ double expected_stored_date = DoubleToDateTime(test_value);
+ double stored_date = date->NumberValue();
+ if (!IsNaN(expected_stored_date)) {
+ CHECK_EQ(expected_stored_date, stored_date);
+ } else {
+ uint64_t stored_bits = DoubleToBits(stored_date);
+ // Check if quiet nan (bits 51..62 all set).
+ CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
+ }
+ }
+}
+
+
+static v8::Handle<Value> SpaghettiIncident(const v8::Arguments& args) {
+ v8::HandleScope scope;
+ v8::TryCatch tc;
+ v8::Handle<v8::String> str = args[0]->ToString();
+ if (tc.HasCaught())
+ return tc.ReThrow();
+ return v8::Undefined();
+}
+
+
+// Test that an exception can be propagated down through a spaghetti
+// stack using ReThrow.
+THREADED_TEST(SpaghettiStackReThrow) {
+ v8::HandleScope scope;
+ LocalContext context;
+ context->Global()->Set(
+ v8::String::New("s"),
+ v8::FunctionTemplate::New(SpaghettiIncident)->GetFunction());
+ v8::TryCatch try_catch;
+ CompileRun(
+ "var i = 0;"
+ "var o = {"
+ " toString: function () {"
+ " if (i == 10) {"
+ " throw 'Hey!';"
+ " } else {"
+ " i++;"
+ " return s(o);"
+ " }"
+ " }"
+ "};"
+ "s(o);");
+ CHECK(try_catch.HasCaught());
+ v8::String::Utf8Value value(try_catch.Exception());
+ CHECK_EQ(0, strcmp(*value, "Hey!"));
+}
+
+
+static int GetGlobalObjectsCount() {
+ int count = 0;
+ v8::internal::HeapIterator it;
+ while (it.has_next()) {
+ v8::internal::HeapObject* object = it.next();
+ if (object->IsJSGlobalObject()) count++;
+ }
+ return count;
+}
+
+
+TEST(Regress528) {
+ v8::V8::Initialize();
+
+ v8::HandleScope scope;
+ v8::Persistent<Context> context;
+ v8::Persistent<Context> other_context;
+ int gc_count;
+
+ // Create a context used to keep the code from aging in the compilation
+ // cache.
+ other_context = Context::New();
+
+ // Context-dependent context data creates reference from the compilation
+ // cache to the global object.
+ const char* source_simple = "1";
+ context = Context::New();
+ {
+ v8::HandleScope scope;
+
+ context->Enter();
+ Local<v8::String> obj = v8::String::New("");
+ context->SetData(obj);
+ CompileRun(source_simple);
+ context->Exit();
+ }
+ context.Dispose();
+ for (gc_count = 1; gc_count < 10; gc_count++) {
+ other_context->Enter();
+ CompileRun(source_simple);
+ other_context->Exit();
+ v8::internal::Heap::CollectAllGarbage(false);
+ if (GetGlobalObjectsCount() == 1) break;
+ }
+ CHECK_GE(2, gc_count);
+ CHECK_EQ(1, GetGlobalObjectsCount());
+
+ // Eval in a function creates reference from the compilation cache to the
+ // global object.
+ const char* source_eval = "function f(){eval('1')}; f()";
+ context = Context::New();
+ {
+ v8::HandleScope scope;
+
+ context->Enter();
+ CompileRun(source_eval);
+ context->Exit();
+ }
+ context.Dispose();
+ for (gc_count = 1; gc_count < 10; gc_count++) {
+ other_context->Enter();
+ CompileRun(source_eval);
+ other_context->Exit();
+ v8::internal::Heap::CollectAllGarbage(false);
+ if (GetGlobalObjectsCount() == 1) break;
+ }
+ CHECK_GE(2, gc_count);
+ CHECK_EQ(1, GetGlobalObjectsCount());
+
+ // Looking up the line number for an exception creates reference from the
+ // compilation cache to the global object.
+ const char* source_exception = "function f(){throw 1;} f()";
+ context = Context::New();
+ {
+ v8::HandleScope scope;
+
+ context->Enter();
+ v8::TryCatch try_catch;
+ CompileRun(source_exception);
+ CHECK(try_catch.HasCaught());
+ v8::Handle<v8::Message> message = try_catch.Message();
+ CHECK(!message.IsEmpty());
+ CHECK_EQ(1, message->GetLineNumber());
+ context->Exit();
+ }
+ context.Dispose();
+ for (gc_count = 1; gc_count < 10; gc_count++) {
+ other_context->Enter();
+ CompileRun(source_exception);
+ other_context->Exit();
+ v8::internal::Heap::CollectAllGarbage(false);
+ if (GetGlobalObjectsCount() == 1) break;
+ }
+ CHECK_GE(2, gc_count);
+ CHECK_EQ(1, GetGlobalObjectsCount());
+
+ other_context.Dispose();
}
diff --git a/test/cctest/test-assembler-ia32.cc b/test/cctest/test-assembler-ia32.cc
index 9ad7c76..76eb6bb 100644
--- a/test/cctest/test-assembler-ia32.cc
+++ b/test/cctest/test-assembler-ia32.cc
@@ -173,8 +173,8 @@
v8::internal::byte buffer[256];
Assembler assm(buffer, sizeof buffer);
- CHECK(CpuFeatures::IsSupported(CpuFeatures::SSE2));
- { CpuFeatures::Scope fscope(CpuFeatures::SSE2);
+ CHECK(CpuFeatures::IsSupported(SSE2));
+ { CpuFeatures::Scope fscope(SSE2);
__ cvttss2si(eax, Operand(esp, 4));
__ ret(0);
}
@@ -207,8 +207,8 @@
v8::internal::byte buffer[256];
Assembler assm(buffer, sizeof buffer);
- CHECK(CpuFeatures::IsSupported(CpuFeatures::SSE2));
- CpuFeatures::Scope fscope(CpuFeatures::SSE2);
+ CHECK(CpuFeatures::IsSupported(SSE2));
+ CpuFeatures::Scope fscope(SSE2);
__ cvttsd2si(eax, Operand(esp, 4));
__ ret(0);
@@ -260,8 +260,8 @@
TEST(AssemblerIa326) {
InitializeVM();
v8::HandleScope scope;
- CHECK(CpuFeatures::IsSupported(CpuFeatures::SSE2));
- CpuFeatures::Scope fscope(CpuFeatures::SSE2);
+ CHECK(CpuFeatures::IsSupported(SSE2));
+ CpuFeatures::Scope fscope(SSE2);
v8::internal::byte buffer[256];
Assembler assm(buffer, sizeof buffer);
@@ -305,8 +305,8 @@
TEST(AssemblerIa328) {
InitializeVM();
v8::HandleScope scope;
- CHECK(CpuFeatures::IsSupported(CpuFeatures::SSE2));
- CpuFeatures::Scope fscope(CpuFeatures::SSE2);
+ CHECK(CpuFeatures::IsSupported(SSE2));
+ CpuFeatures::Scope fscope(SSE2);
v8::internal::byte buffer[256];
Assembler assm(buffer, sizeof buffer);
__ mov(eax, Operand(esp, 4));
diff --git a/test/cctest/test-assembler-x64.cc b/test/cctest/test-assembler-x64.cc
index 81aa973..f100b73 100644
--- a/test/cctest/test-assembler-x64.cc
+++ b/test/cctest/test-assembler-x64.cc
@@ -86,7 +86,7 @@
&actual_size,
true));
CHECK(buffer);
- Assembler assm(buffer, actual_size);
+ Assembler assm(buffer, static_cast<int>(actual_size));
// Assemble a simple function that copies argument 2 and returns it.
__ movq(rax, arg2);
@@ -107,7 +107,7 @@
&actual_size,
true));
CHECK(buffer);
- Assembler assm(buffer, actual_size);
+ Assembler assm(buffer, static_cast<int>(actual_size));
// Assemble a simple function that copies argument 2 and returns it.
// We compile without stack frame pointers, so the gdb debugger shows
@@ -138,7 +138,7 @@
&actual_size,
true));
CHECK(buffer);
- Assembler assm(buffer, actual_size);
+ Assembler assm(buffer, static_cast<int>(actual_size));
// Assemble a simple function that adds arguments returning the sum.
__ movq(rax, arg2);
@@ -159,7 +159,7 @@
&actual_size,
true));
CHECK(buffer);
- Assembler assm(buffer, actual_size);
+ Assembler assm(buffer, static_cast<int>(actual_size));
// Assemble a simple function that multiplies arguments returning the high
// word.
@@ -186,7 +186,7 @@
&actual_size,
true));
CHECK(buffer);
- Assembler assm(buffer, actual_size);
+ Assembler assm(buffer, static_cast<int>(actual_size));
// Assemble a simple function that copies argument 2 and returns it.
__ push(rbp);
@@ -219,7 +219,7 @@
&actual_size,
true));
CHECK(buffer);
- Assembler assm(buffer, actual_size);
+ Assembler assm(buffer, static_cast<int>(actual_size));
// Assemble a simple function that copies argument 1 and returns it.
__ push(rbp);
@@ -247,7 +247,7 @@
&actual_size,
true));
CHECK(buffer);
- Assembler assm(buffer, actual_size);
+ Assembler assm(buffer, static_cast<int>(actual_size));
// Assemble two loops using rax as counter, and verify the ending counts.
Label Fail;
__ movq(rax, Immediate(-3));
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index 4ffcee3..5b72193 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -53,7 +53,7 @@
using ::v8::internal::StepNext; // From StepAction enum
using ::v8::internal::StepOut; // From StepAction enum
using ::v8::internal::Vector;
-
+using ::v8::internal::StrLength;
// Size of temp buffer for formatting small strings.
#define SMALL_STRING_BUFFER_SIZE 80
@@ -178,12 +178,6 @@
}
-// Helper function that compiles and runs the source.
-static v8::Local<v8::Value> CompileRun(const char* source) {
- return v8::Script::Compile(v8::String::New(source))->Run();
-}
-
-
// Is there any debug info for the function?
static bool HasDebugInfo(v8::Handle<v8::Function> fun) {
Handle<v8::internal::JSFunction> f = v8::Utils::OpenHandle(*fun);
@@ -806,14 +800,14 @@
if (event == v8::Break || event == v8::Exception) {
// Check that the current function is the expected.
CHECK(break_point_hit_count <
- static_cast<int>(strlen(expected_step_sequence)));
+ StrLength(expected_step_sequence));
const int argc = 1;
v8::Handle<v8::Value> argv[argc] = { exec_state };
v8::Handle<v8::Value> result = frame_function_name->Call(exec_state,
argc, argv);
CHECK(result->IsString());
v8::String::AsciiValue function_name(result->ToString());
- CHECK_EQ(1, strlen(*function_name));
+ CHECK_EQ(1, StrLength(*function_name));
CHECK_EQ((*function_name)[0],
expected_step_sequence[break_point_hit_count]);
@@ -872,6 +866,26 @@
}
+// Debug event handler which re-issues a debug break until a limit has been
+// reached.
+int max_break_point_hit_count = 0;
+static void DebugEventBreakMax(v8::DebugEvent event,
+ v8::Handle<v8::Object> exec_state,
+ v8::Handle<v8::Object> event_data,
+ v8::Handle<v8::Value> data) {
+ // When hitting a debug event listener there must be a break set.
+ CHECK_NE(v8::internal::Debug::break_id(), 0);
+
+ if (event == v8::Break && break_point_hit_count < max_break_point_hit_count) {
+ // Count the number of breaks.
+ break_point_hit_count++;
+
+ // Set the break flag again to come back here as soon as possible.
+ v8::Debug::DebugBreak();
+ }
+}
+
+
// --- M e s s a g e C a l l b a c k
@@ -1917,7 +1931,7 @@
// Chesk that a break point was hit when the script was run.
CHECK_EQ(1, break_point_hit_count);
- CHECK_EQ(0, strlen(last_function_hit));
+ CHECK_EQ(0, StrLength(last_function_hit));
// Call f and check that the script break point.
f->Call(env->Global(), 0, NULL);
@@ -1953,7 +1967,7 @@
break_point_hit_count = 0;
v8::Script::Compile(script, &origin)->Run();
CHECK_EQ(2, break_point_hit_count);
- CHECK_EQ(0, strlen(last_function_hit));
+ CHECK_EQ(0, StrLength(last_function_hit));
// Set a break point in the code after the last function decleration.
int sbp6 = SetScriptBreakPointByNameFromJS("test.html", 12, -1);
@@ -1962,7 +1976,7 @@
break_point_hit_count = 0;
v8::Script::Compile(script, &origin)->Run();
CHECK_EQ(3, break_point_hit_count);
- CHECK_EQ(0, strlen(last_function_hit));
+ CHECK_EQ(0, StrLength(last_function_hit));
// Clear the last break points, and reload the script which should not hit any
// break points.
@@ -2478,21 +2492,24 @@
break_point_hit_count = 0;
expected_step_sequence = "abcbaca";
a->Call(env->Global(), 0, NULL);
- CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
+ CHECK_EQ(StrLength(expected_step_sequence),
+ break_point_hit_count);
// Step through invocation of a with step next.
step_action = StepNext;
break_point_hit_count = 0;
expected_step_sequence = "aaa";
a->Call(env->Global(), 0, NULL);
- CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
+ CHECK_EQ(StrLength(expected_step_sequence),
+ break_point_hit_count);
// Step through invocation of a with step out.
step_action = StepOut;
break_point_hit_count = 0;
expected_step_sequence = "a";
a->Call(env->Global(), 0, NULL);
- CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
+ CHECK_EQ(StrLength(expected_step_sequence),
+ break_point_hit_count);
// Get rid of the debug event listener.
v8::Debug::SetDebugEventListener(NULL);
@@ -2525,21 +2542,24 @@
break_point_hit_count = 0;
expected_step_sequence = "adacadabcbadacada";
a->Call(env->Global(), 0, NULL);
- CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
+ CHECK_EQ(StrLength(expected_step_sequence),
+ break_point_hit_count);
// Step through invocation of a with step next.
step_action = StepNext;
break_point_hit_count = 0;
expected_step_sequence = "aaaa";
a->Call(env->Global(), 0, NULL);
- CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
+ CHECK_EQ(StrLength(expected_step_sequence),
+ break_point_hit_count);
// Step through invocation of a with step out.
step_action = StepOut;
break_point_hit_count = 0;
expected_step_sequence = "a";
a->Call(env->Global(), 0, NULL);
- CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
+ CHECK_EQ(StrLength(expected_step_sequence),
+ break_point_hit_count);
// Get rid of the debug event listener.
v8::Debug::SetDebugEventListener(NULL);
@@ -2571,7 +2591,8 @@
break_point_hit_count = 0;
expected_step_sequence = "abaca";
a->Call(env->Global(), 0, NULL);
- CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
+ CHECK_EQ(StrLength(expected_step_sequence),
+ break_point_hit_count);
// Get rid of the debug event listener.
v8::Debug::SetDebugEventListener(NULL);
@@ -2707,6 +2728,37 @@
}
+// Tests that breakpoint will be hit if it's set in script.
+TEST(PauseInScript) {
+ v8::HandleScope scope;
+ DebugLocalContext env;
+ env.ExposeDebug();
+
+ // Register a debug event listener which counts.
+ v8::Debug::SetDebugEventListener(DebugEventCounter);
+
+ // Create a script that returns a function.
+ const char* src = "(function (evt) {})";
+ const char* script_name = "StepInHandlerTest";
+
+ // Set breakpoint in the script.
+ SetScriptBreakPointByNameFromJS(script_name, 0, -1);
+ break_point_hit_count = 0;
+
+ v8::ScriptOrigin origin(v8::String::New(script_name), v8::Integer::New(0));
+ v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::New(src),
+ &origin);
+ v8::Local<v8::Value> r = script->Run();
+
+ CHECK(r->IsFunction());
+ CHECK_EQ(1, break_point_hit_count);
+
+ // Get rid of the debug event listener.
+ v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
+}
+
+
// Test break on exceptions. For each exception break combination the number
// of debug event exception callbacks and message callbacks are collected. The
// number of debug event exception callbacks are used to check that the
@@ -2938,7 +2990,8 @@
break_point_hit_count = 0;
expected_step_sequence = "aa";
a->Call(env->Global(), 0, NULL);
- CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
+ CHECK_EQ(StrLength(expected_step_sequence),
+ break_point_hit_count);
// Step through invocation of b + c.
v8::Local<v8::Function> b = CompileFunction(&env, src, "b");
@@ -2947,7 +3000,8 @@
break_point_hit_count = 0;
expected_step_sequence = "bcc";
b->Call(env->Global(), 0, NULL);
- CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
+ CHECK_EQ(StrLength(expected_step_sequence),
+ break_point_hit_count);
// Step through invocation of d + e.
v8::Local<v8::Function> d = CompileFunction(&env, src, "d");
@@ -2957,7 +3011,8 @@
break_point_hit_count = 0;
expected_step_sequence = "dded";
d->Call(env->Global(), 0, NULL);
- CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
+ CHECK_EQ(StrLength(expected_step_sequence),
+ break_point_hit_count);
// Step through invocation of d + e now with break on caught exceptions.
ChangeBreakOnException(true, true);
@@ -2965,7 +3020,8 @@
break_point_hit_count = 0;
expected_step_sequence = "ddeed";
d->Call(env->Global(), 0, NULL);
- CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
+ CHECK_EQ(StrLength(expected_step_sequence),
+ break_point_hit_count);
// Step through invocation of f + g + h.
v8::Local<v8::Function> f = CompileFunction(&env, src, "f");
@@ -2975,7 +3031,8 @@
break_point_hit_count = 0;
expected_step_sequence = "ffghf";
f->Call(env->Global(), 0, NULL);
- CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
+ CHECK_EQ(StrLength(expected_step_sequence),
+ break_point_hit_count);
// Step through invocation of f + g + h now with break on caught exceptions.
ChangeBreakOnException(true, true);
@@ -2983,7 +3040,8 @@
break_point_hit_count = 0;
expected_step_sequence = "ffghhf";
f->Call(env->Global(), 0, NULL);
- CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
+ CHECK_EQ(StrLength(expected_step_sequence),
+ break_point_hit_count);
// Get rid of the debug event listener.
v8::Debug::SetDebugEventListener(NULL);
@@ -3425,6 +3483,75 @@
}
+// Test that hidden properties object is not returned as an unnamed property
+// among regular properties.
+// See http://crbug.com/26491
+TEST(NoHiddenProperties) {
+ // Create a V8 environment with debug access.
+ v8::HandleScope scope;
+ DebugLocalContext env;
+ env.ExposeDebug();
+
+ // Create an object in the global scope.
+ const char* source = "var obj = {a: 1};";
+ v8::Script::Compile(v8::String::New(source))->Run();
+ v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
+ env->Global()->Get(v8::String::New("obj")));
+ // Set a hidden property on the object.
+ obj->SetHiddenValue(v8::String::New("v8::test-debug::a"),
+ v8::Int32::New(11));
+
+ // Get mirror for the object with property getter.
+ CompileRun("var obj_mirror = debug.MakeMirror(obj);");
+ CHECK(CompileRun(
+ "obj_mirror instanceof debug.ObjectMirror")->BooleanValue());
+ CompileRun("var named_names = obj_mirror.propertyNames();");
+ // There should be exactly one property. But there is also an unnamed
+ // property whose value is hidden properties dictionary. The latter
+ // property should not be in the list of reguar properties.
+ CHECK_EQ(1, CompileRun("named_names.length")->Int32Value());
+ CHECK(CompileRun("named_names[0] == 'a'")->BooleanValue());
+ CHECK(CompileRun(
+ "obj_mirror.property('a').value().value() == 1")->BooleanValue());
+
+ // Object created by t0 will become hidden prototype of object 'obj'.
+ v8::Handle<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New();
+ t0->InstanceTemplate()->Set(v8::String::New("b"), v8::Number::New(2));
+ t0->SetHiddenPrototype(true);
+ v8::Handle<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
+ t1->InstanceTemplate()->Set(v8::String::New("c"), v8::Number::New(3));
+
+ // Create proto objects, add hidden properties to them and set them on
+ // the global object.
+ v8::Handle<v8::Object> protoObj = t0->GetFunction()->NewInstance();
+ protoObj->SetHiddenValue(v8::String::New("v8::test-debug::b"),
+ v8::Int32::New(12));
+ env->Global()->Set(v8::String::New("protoObj"), protoObj);
+ v8::Handle<v8::Object> grandProtoObj = t1->GetFunction()->NewInstance();
+ grandProtoObj->SetHiddenValue(v8::String::New("v8::test-debug::c"),
+ v8::Int32::New(13));
+ env->Global()->Set(v8::String::New("grandProtoObj"), grandProtoObj);
+
+ // Setting prototypes: obj->protoObj->grandProtoObj
+ protoObj->Set(v8::String::New("__proto__"), grandProtoObj);
+ obj->Set(v8::String::New("__proto__"), protoObj);
+
+ // Get mirror for the object with property getter.
+ CompileRun("var obj_mirror = debug.MakeMirror(obj);");
+ CHECK(CompileRun(
+ "obj_mirror instanceof debug.ObjectMirror")->BooleanValue());
+ CompileRun("var named_names = obj_mirror.propertyNames();");
+ // There should be exactly two properties - one from the object itself and
+ // another from its hidden prototype.
+ CHECK_EQ(2, CompileRun("named_names.length")->Int32Value());
+ CHECK(CompileRun("named_names.sort(); named_names[0] == 'a' &&"
+ "named_names[1] == 'b'")->BooleanValue());
+ CHECK(CompileRun(
+ "obj_mirror.property('a').value().value() == 1")->BooleanValue());
+ CHECK(CompileRun(
+ "obj_mirror.property('b').value().value() == 2")->BooleanValue());
+}
+
// Multithreaded tests of JSON debugger protocol
@@ -4564,6 +4691,71 @@
}
+/* Test DebugMessageDispatch */
+/* In this test, the V8 thread waits for a message from the debug thread.
+ * The DebugMessageDispatchHandler is executed from the debugger thread
+ * which signals the V8 thread to wake up.
+ */
+
+class DebugMessageDispatchV8Thread : public v8::internal::Thread {
+ public:
+ void Run();
+};
+
+class DebugMessageDispatchDebuggerThread : public v8::internal::Thread {
+ public:
+ void Run();
+};
+
+Barriers* debug_message_dispatch_barriers;
+
+
+static void DebugMessageHandler() {
+ debug_message_dispatch_barriers->semaphore_1->Signal();
+}
+
+
+void DebugMessageDispatchV8Thread::Run() {
+ v8::HandleScope scope;
+ DebugLocalContext env;
+
+ // Setup debug message dispatch handler.
+ v8::Debug::SetDebugMessageDispatchHandler(DebugMessageHandler);
+
+ CompileRun("var y = 1 + 2;\n");
+ debug_message_dispatch_barriers->barrier_1.Wait();
+ debug_message_dispatch_barriers->semaphore_1->Wait();
+ debug_message_dispatch_barriers->barrier_2.Wait();
+}
+
+
+void DebugMessageDispatchDebuggerThread::Run() {
+ debug_message_dispatch_barriers->barrier_1.Wait();
+ SendContinueCommand();
+ debug_message_dispatch_barriers->barrier_2.Wait();
+}
+
+DebugMessageDispatchDebuggerThread debug_message_dispatch_debugger_thread;
+DebugMessageDispatchV8Thread debug_message_dispatch_v8_thread;
+
+
+TEST(DebuggerDebugMessageDispatch) {
+ i::FLAG_debugger_auto_break = true;
+
+ // Create a V8 environment
+ Barriers stack_allocated_debug_message_dispatch_barriers;
+ stack_allocated_debug_message_dispatch_barriers.Initialize();
+ debug_message_dispatch_barriers =
+ &stack_allocated_debug_message_dispatch_barriers;
+
+ debug_message_dispatch_v8_thread.Start();
+ debug_message_dispatch_debugger_thread.Start();
+
+ debug_message_dispatch_v8_thread.Join();
+ debug_message_dispatch_debugger_thread.Join();
+}
+
+
TEST(DebuggerAgent) {
// Make sure these ports is not used by other tests to allow tests to run in
// parallel.
@@ -4709,7 +4901,8 @@
// Add empty body to request.
const char* content_length_zero_header = "Content-Length:0\r\n";
- client->Send(content_length_zero_header, strlen(content_length_zero_header));
+ client->Send(content_length_zero_header,
+ StrLength(content_length_zero_header));
client->Send("\r\n", 2);
// Wait until data is received.
@@ -4823,7 +5016,7 @@
v8::ScriptOrigin origin2 = v8::ScriptOrigin(v8::String::New("new name"));
v8::Handle<v8::Script> script2 = v8::Script::Compile(script, &origin2);
script2->Run();
- script2->SetData(data_obj);
+ script2->SetData(data_obj->ToString());
f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
f->Call(env->Global(), 0, NULL);
CHECK_EQ(3, break_point_hit_count);
@@ -4876,8 +5069,8 @@
CHECK(context_2->GetData()->IsUndefined());
// Set and check different data values.
- v8::Handle<v8::Value> data_1 = v8::Number::New(1);
- v8::Handle<v8::Value> data_2 = v8::String::New("2");
+ v8::Handle<v8::String> data_1 = v8::String::New("1");
+ v8::Handle<v8::String> data_2 = v8::String::New("2");
context_1->SetData(data_1);
context_2->SetData(data_2);
CHECK(context_1->GetData()->StrictEquals(data_1));
@@ -5040,7 +5233,7 @@
CHECK(context_1->GetData()->IsUndefined());
// Set and check a data value.
- v8::Handle<v8::Value> data_1 = v8::Number::New(1);
+ v8::Handle<v8::String> data_1 = v8::String::New("1");
context_1->SetData(data_1);
CHECK(context_1->GetData()->StrictEquals(data_1));
@@ -5444,3 +5637,119 @@
v8::Handle<v8::Value> result = run_test->Call(env->Global(), 1, &obj);
CHECK(result->IsTrue());
}
+
+
+// Test that the debug break flag works with function.apply.
+TEST(DebugBreakFunctionApply) {
+ v8::HandleScope scope;
+ DebugLocalContext env;
+
+ // Create a function for testing breaking in apply.
+ v8::Local<v8::Function> foo = CompileFunction(
+ &env,
+ "function baz(x) { }"
+ "function bar(x) { baz(); }"
+ "function foo(){ bar.apply(this, [1]); }",
+ "foo");
+
+ // Register a debug event listener which steps and counts.
+ v8::Debug::SetDebugEventListener(DebugEventBreakMax);
+
+ // Set the debug break flag before calling the code using function.apply.
+ v8::Debug::DebugBreak();
+
+ // Limit the number of debug breaks. This is a regression test for issue 493
+ // where this test would enter an infinite loop.
+ break_point_hit_count = 0;
+ max_break_point_hit_count = 10000; // 10000 => infinite loop.
+ foo->Call(env->Global(), 0, NULL);
+
+ // When keeping the debug break several break will happen.
+ CHECK_EQ(3, break_point_hit_count);
+
+ v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
+}
+
+
+v8::Handle<v8::Context> debugee_context;
+v8::Handle<v8::Context> debugger_context;
+
+
+// Property getter that checks that current and calling contexts
+// are both the debugee contexts.
+static v8::Handle<v8::Value> NamedGetterWithCallingContextCheck(
+ v8::Local<v8::String> name,
+ const v8::AccessorInfo& info) {
+ CHECK_EQ(0, strcmp(*v8::String::AsciiValue(name), "a"));
+ v8::Handle<v8::Context> current = v8::Context::GetCurrent();
+ CHECK(current == debugee_context);
+ CHECK(current != debugger_context);
+ v8::Handle<v8::Context> calling = v8::Context::GetCalling();
+ CHECK(calling == debugee_context);
+ CHECK(calling != debugger_context);
+ return v8::Int32::New(1);
+}
+
+
+// Debug event listener that checks if the first argument of a function is
+// an object with property 'a' == 1. If the property has custom accessor
+// this handler will eventually invoke it.
+static void DebugEventGetAtgumentPropertyValue(
+ v8::DebugEvent event,
+ v8::Handle<v8::Object> exec_state,
+ v8::Handle<v8::Object> event_data,
+ v8::Handle<v8::Value> data) {
+ if (event == v8::Break) {
+ break_point_hit_count++;
+ CHECK(debugger_context == v8::Context::GetCurrent());
+ v8::Handle<v8::Function> func(v8::Function::Cast(*CompileRun(
+ "(function(exec_state) {\n"
+ " return (exec_state.frame(0).argumentValue(0).property('a').\n"
+ " value().value() == 1);\n"
+ "})")));
+ const int argc = 1;
+ v8::Handle<v8::Value> argv[argc] = { exec_state };
+ v8::Handle<v8::Value> result = func->Call(exec_state, argc, argv);
+ CHECK(result->IsTrue());
+ }
+}
+
+
+TEST(CallingContextIsNotDebugContext) {
+ // Create and enter a debugee context.
+ v8::HandleScope scope;
+ DebugLocalContext env;
+ env.ExposeDebug();
+
+ // Save handles to the debugger and debugee contexts to be used in
+ // NamedGetterWithCallingContextCheck.
+ debugee_context = v8::Local<v8::Context>(*env);
+ debugger_context = v8::Utils::ToLocal(Debug::debug_context());
+
+ // Create object with 'a' property accessor.
+ v8::Handle<v8::ObjectTemplate> named = v8::ObjectTemplate::New();
+ named->SetAccessor(v8::String::New("a"),
+ NamedGetterWithCallingContextCheck);
+ env->Global()->Set(v8::String::New("obj"),
+ named->NewInstance());
+
+ // Register the debug event listener
+ v8::Debug::SetDebugEventListener(DebugEventGetAtgumentPropertyValue);
+
+ // Create a function that invokes debugger.
+ v8::Local<v8::Function> foo = CompileFunction(
+ &env,
+ "function bar(x) { debugger; }"
+ "function foo(){ bar(obj); }",
+ "foo");
+
+ break_point_hit_count = 0;
+ foo->Call(env->Global(), 0, NULL);
+ CHECK_EQ(1, break_point_hit_count);
+
+ v8::Debug::SetDebugEventListener(NULL);
+ debugee_context = v8::Handle<v8::Context>();
+ debugger_context = v8::Handle<v8::Context>();
+ CheckDebuggerUnloaded();
+}
diff --git a/test/cctest/test-disasm-ia32.cc b/test/cctest/test-disasm-ia32.cc
index 74db234..b8b3364 100644
--- a/test/cctest/test-disasm-ia32.cc
+++ b/test/cctest/test-disasm-ia32.cc
@@ -105,13 +105,13 @@
__ xor_(edx, 3);
__ nop();
{
- CHECK(CpuFeatures::IsSupported(CpuFeatures::CPUID));
- CpuFeatures::Scope fscope(CpuFeatures::CPUID);
+ CHECK(CpuFeatures::IsSupported(CPUID));
+ CpuFeatures::Scope fscope(CPUID);
__ cpuid();
}
{
- CHECK(CpuFeatures::IsSupported(CpuFeatures::RDTSC));
- CpuFeatures::Scope fscope(CpuFeatures::RDTSC);
+ CHECK(CpuFeatures::IsSupported(RDTSC));
+ CpuFeatures::Scope fscope(RDTSC);
__ rdtsc();
}
__ movsx_b(edx, Operand(ecx));
@@ -194,15 +194,16 @@
__ rcl(edx, 7);
__ sar(edx, 1);
__ sar(edx, 6);
- __ sar(edx);
+ __ sar_cl(edx);
__ sbb(edx, Operand(ebx, ecx, times_4, 10000));
__ shld(edx, Operand(ebx, ecx, times_4, 10000));
__ shl(edx, 1);
__ shl(edx, 6);
- __ shl(edx);
+ __ shl_cl(edx);
__ shrd(edx, Operand(ebx, ecx, times_4, 10000));
+ __ shr(edx, 1);
__ shr(edx, 7);
- __ shr(edx);
+ __ shr_cl(edx);
// Immediates
@@ -353,8 +354,8 @@
__ fwait();
__ nop();
{
- CHECK(CpuFeatures::IsSupported(CpuFeatures::SSE2));
- CpuFeatures::Scope fscope(CpuFeatures::SSE2);
+ CHECK(CpuFeatures::IsSupported(SSE2));
+ CpuFeatures::Scope fscope(SSE2);
__ cvttss2si(edx, Operand(ebx, ecx, times_4, 10000));
__ cvtsi2sd(xmm1, Operand(ebx, ecx, times_4, 10000));
__ addsd(xmm1, xmm0);
@@ -368,8 +369,8 @@
// cmov.
{
- CHECK(CpuFeatures::IsSupported(CpuFeatures::CMOV));
- CpuFeatures::Scope use_cmov(CpuFeatures::CMOV);
+ CHECK(CpuFeatures::IsSupported(CMOV));
+ CpuFeatures::Scope use_cmov(CMOV);
__ cmov(overflow, eax, Operand(eax, 0));
__ cmov(no_overflow, eax, Operand(eax, 1));
__ cmov(below, eax, Operand(eax, 2));
diff --git a/test/cctest/test-flags.cc b/test/cctest/test-flags.cc
index 9019a89..32f1264 100644
--- a/test/cctest/test-flags.cc
+++ b/test/cctest/test-flags.cc
@@ -75,7 +75,7 @@
" -notesting-bool-flag notaflag --testing_int_flag=77 "
"-testing_float_flag=.25 "
"--testing_string_flag no_way! ";
- CHECK_EQ(0, FlagList::SetFlagsFromString(str, strlen(str)));
+ CHECK_EQ(0, FlagList::SetFlagsFromString(str, StrLength(str)));
CHECK(!FLAG_testing_bool_flag);
CHECK_EQ(77, FLAG_testing_int_flag);
CHECK_EQ(.25, FLAG_testing_float_flag);
@@ -107,7 +107,7 @@
"--testing_bool_flag notaflag --testing_int_flag -666 "
"--testing_float_flag -12E10 "
"-testing-string-flag=foo-bar";
- CHECK_EQ(0, FlagList::SetFlagsFromString(str, strlen(str)));
+ CHECK_EQ(0, FlagList::SetFlagsFromString(str, StrLength(str)));
CHECK(FLAG_testing_bool_flag);
CHECK_EQ(-666, FLAG_testing_int_flag);
CHECK_EQ(-12E10, FLAG_testing_float_flag);
@@ -129,7 +129,7 @@
TEST(Flags4b) {
SetFlagsToDefault();
const char* str = "--testing_bool_flag --foo";
- CHECK_EQ(2, FlagList::SetFlagsFromString(str, strlen(str)));
+ CHECK_EQ(2, FlagList::SetFlagsFromString(str, StrLength(str)));
}
@@ -147,7 +147,7 @@
TEST(Flags5b) {
SetFlagsToDefault();
const char* str = " --testing_int_flag=\"foobar\"";
- CHECK_EQ(1, FlagList::SetFlagsFromString(str, strlen(str)));
+ CHECK_EQ(1, FlagList::SetFlagsFromString(str, StrLength(str)));
}
@@ -166,7 +166,7 @@
TEST(Flags6b) {
SetFlagsToDefault();
const char* str = " --testing-int-flag 0 --testing_float_flag ";
- CHECK_EQ(3, FlagList::SetFlagsFromString(str, strlen(str)));
+ CHECK_EQ(3, FlagList::SetFlagsFromString(str, StrLength(str)));
}
@@ -191,7 +191,7 @@
TEST(FlagsJSArguments1b) {
SetFlagsToDefault();
const char* str = "--testing-int-flag 42 -- testing-float-flag 7";
- CHECK_EQ(0, FlagList::SetFlagsFromString(str, strlen(str)));
+ CHECK_EQ(0, FlagList::SetFlagsFromString(str, StrLength(str)));
CHECK_EQ(42, FLAG_testing_int_flag);
CHECK_EQ(2.5, FLAG_testing_float_flag);
CHECK_EQ(2, FLAG_js_arguments.argc());
@@ -203,7 +203,7 @@
TEST(FlagsJSArguments2) {
SetFlagsToDefault();
const char* str = "--testing-int-flag 42 --js-arguments testing-float-flag 7";
- CHECK_EQ(0, FlagList::SetFlagsFromString(str, strlen(str)));
+ CHECK_EQ(0, FlagList::SetFlagsFromString(str, StrLength(str)));
CHECK_EQ(42, FLAG_testing_int_flag);
CHECK_EQ(2.5, FLAG_testing_float_flag);
CHECK_EQ(2, FLAG_js_arguments.argc());
@@ -215,7 +215,7 @@
TEST(FlagsJSArguments3) {
SetFlagsToDefault();
const char* str = "--testing-int-flag 42 --js-arguments=testing-float-flag 7";
- CHECK_EQ(0, FlagList::SetFlagsFromString(str, strlen(str)));
+ CHECK_EQ(0, FlagList::SetFlagsFromString(str, StrLength(str)));
CHECK_EQ(42, FLAG_testing_int_flag);
CHECK_EQ(2.5, FLAG_testing_float_flag);
CHECK_EQ(2, FLAG_js_arguments.argc());
@@ -227,7 +227,7 @@
TEST(FlagsJSArguments4) {
SetFlagsToDefault();
const char* str = "--testing-int-flag 42 --";
- CHECK_EQ(0, FlagList::SetFlagsFromString(str, strlen(str)));
+ CHECK_EQ(0, FlagList::SetFlagsFromString(str, StrLength(str)));
CHECK_EQ(42, FLAG_testing_int_flag);
CHECK_EQ(0, FLAG_js_arguments.argc());
}
diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc
index b199507..04e0037 100644
--- a/test/cctest/test-heap-profiler.cc
+++ b/test/cctest/test-heap-profiler.cc
@@ -384,8 +384,8 @@
const char* retainers_of_a = printer.GetRetainers("A");
// The order of retainers is unspecified, so we check string length, and
// verify each retainer separately.
- CHECK_EQ(static_cast<int>(strlen("(global property);1,B;2,C;2")),
- static_cast<int>(strlen(retainers_of_a)));
+ CHECK_EQ(i::StrLength("(global property);1,B;2,C;2"),
+ i::StrLength(retainers_of_a));
CHECK(strstr(retainers_of_a, "(global property);1") != NULL);
CHECK(strstr(retainers_of_a, "B;2") != NULL);
CHECK(strstr(retainers_of_a, "C;2") != NULL);
diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
index 9911ce4..17bee5b 100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -37,8 +37,7 @@
CheckMap(Heap::meta_map(), MAP_TYPE, Map::kSize);
CheckMap(Heap::heap_number_map(), HEAP_NUMBER_TYPE, HeapNumber::kSize);
CheckMap(Heap::fixed_array_map(), FIXED_ARRAY_TYPE, FixedArray::kHeaderSize);
- CheckMap(Heap::long_string_map(), LONG_STRING_TYPE,
- SeqTwoByteString::kAlignedSize);
+ CheckMap(Heap::string_map(), STRING_TYPE, SeqTwoByteString::kAlignedSize);
}
@@ -262,7 +261,7 @@
static void VerifyStringAllocation(const char* string) {
String* s = String::cast(Heap::AllocateStringFromUtf8(CStrVector(string)));
- CHECK_EQ(static_cast<int>(strlen(string)), s->length());
+ CHECK_EQ(StrLength(string), s->length());
for (int index = 0; index < s->length(); index++) {
CHECK_EQ(static_cast<uint16_t>(string[index]), s->Get(index)); }
}
@@ -285,7 +284,7 @@
v8::HandleScope scope;
const char* name = "Kasper the spunky";
Handle<String> string = Factory::NewStringFromAscii(CStrVector(name));
- CHECK_EQ(static_cast<int>(strlen(name)), string->length());
+ CHECK_EQ(StrLength(name), string->length());
}
diff --git a/test/cctest/test-log-stack-tracer.cc b/test/cctest/test-log-stack-tracer.cc
index 43df6ba..68cbc26 100644
--- a/test/cctest/test-log-stack-tracer.cc
+++ b/test/cctest/test-log-stack-tracer.cc
@@ -163,11 +163,6 @@
}
-static void CompileRun(const char* source) {
- Script::Compile(String::New(source))->Run();
-}
-
-
v8::Handle<v8::Value> TraceExtension::JSEntrySPLevel2(
const v8::Arguments& args) {
v8::HandleScope scope;
@@ -329,17 +324,16 @@
}
-static void CFuncDoTrace() {
+static void CFuncDoTrace(byte dummy_parameter) {
Address fp;
#ifdef __GNUC__
fp = reinterpret_cast<Address>(__builtin_frame_address(0));
-#elif defined _MSC_VER && defined V8_TARGET_ARCH_IA32
- __asm mov [fp], ebp // NOLINT
-#elif defined _MSC_VER && defined V8_TARGET_ARCH_X64
- // TODO(X64): __asm extension is not supported by the Microsoft Visual C++
- // 64-bit compiler.
- fp = 0;
- UNIMPLEMENTED();
+#elif defined _MSC_VER
+ // Approximate a frame pointer address. We compile without base pointers,
+ // so we can't trust ebp/rbp.
+ fp = &dummy_parameter - 2 * sizeof(void*); // NOLINT
+#else
+#error Unexpected platform.
#endif
DoTrace(fp);
}
@@ -347,7 +341,7 @@
static int CFunc(int depth) {
if (depth <= 0) {
- CFuncDoTrace();
+ CFuncDoTrace(0);
return 0;
} else {
return CFunc(depth - 1) + 1;
diff --git a/test/cctest/test-log-utils.cc b/test/cctest/test-log-utils.cc
index a08a0a1..c99d770 100644
--- a/test/cctest/test-log-utils.cc
+++ b/test/cctest/test-log-utils.cc
@@ -16,6 +16,7 @@
using v8::internal::MutableCStrVector;
using v8::internal::ScopedVector;
using v8::internal::Vector;
+using v8::internal::StrLength;
// Fills 'ref_buffer' with test data: a sequence of two-digit
// hex numbers: '0001020304...'. Then writes 'ref_buffer' contents to 'dynabuf'.
@@ -118,7 +119,7 @@
TEST(DynaBufSealing) {
const char* seal = "Sealed";
- const int seal_size = strlen(seal);
+ const int seal_size = StrLength(seal);
LogDynamicBuffer dynabuf(32, 128, seal, seal_size);
EmbeddedVector<char, 100> ref_buf;
WriteData(&dynabuf, &ref_buf);
diff --git a/test/cctest/test-log.cc b/test/cctest/test-log.cc
index 3983215..85ff331 100644
--- a/test/cctest/test-log.cc
+++ b/test/cctest/test-log.cc
@@ -19,6 +19,7 @@
using v8::internal::Address;
using v8::internal::EmbeddedVector;
using v8::internal::Logger;
+using v8::internal::StrLength;
namespace i = v8::internal;
@@ -55,7 +56,7 @@
CHECK_EQ(0, Logger::GetLogLines(0, log_lines, 3));
// See Logger::StringEvent.
const char* line_1 = "aaa,\"bbb\"\n";
- const int line_1_len = strlen(line_1);
+ const int line_1_len = StrLength(line_1);
// Still smaller than log message length.
CHECK_EQ(0, Logger::GetLogLines(0, log_lines, line_1_len - 1));
// The exact size.
@@ -68,7 +69,7 @@
CHECK_EQ(line_1, log_lines);
memset(log_lines, 0, sizeof(log_lines));
const char* line_2 = "cccc,\"dddd\"\n";
- const int line_2_len = strlen(line_2);
+ const int line_2_len = StrLength(line_2);
// Now start with line_2 beginning.
CHECK_EQ(0, Logger::GetLogLines(line_1_len, log_lines, 0));
CHECK_EQ(0, Logger::GetLogLines(line_1_len, log_lines, 3));
@@ -82,7 +83,7 @@
memset(log_lines, 0, sizeof(log_lines));
// Now get entire buffer contents.
const char* all_lines = "aaa,\"bbb\"\ncccc,\"dddd\"\n";
- const int all_lines_len = strlen(all_lines);
+ const int all_lines_len = StrLength(all_lines);
CHECK_EQ(all_lines_len, Logger::GetLogLines(0, log_lines, all_lines_len));
CHECK_EQ(all_lines, log_lines);
memset(log_lines, 0, sizeof(log_lines));
@@ -104,7 +105,7 @@
Logger::StringEvent("cccc", "dddd");
// See Logger::StringEvent.
const char* all_lines = "aaa,\"bbb\"\ncccc,\"dddd\"\n";
- const int all_lines_len = strlen(all_lines);
+ const int all_lines_len = StrLength(all_lines);
EmbeddedVector<char, 100> buffer;
const int beyond_write_pos = all_lines_len;
CHECK_EQ(0, Logger::GetLogLines(beyond_write_pos, buffer.start(), 1));
@@ -246,7 +247,7 @@
i::FLAG_logfile = "*";
// If tests are being run manually, V8 will be already initialized
- // by the test below.
+ // by the bottom test.
const bool need_to_set_up_logger = i::V8::IsRunning();
v8::HandleScope scope;
v8::Handle<v8::Context> env = v8::Context::New();
@@ -256,11 +257,10 @@
// No sampling should happen prior to resuming profiler.
CHECK(!LoggerTestHelper::IsSamplerActive());
- // Read initial logged data (static libs map).
EmbeddedVector<char, 102400> buffer;
+ // Nothing must be logged until profiling is resumed.
int log_pos = GetLogLines(0, &buffer);
- CHECK_GT(log_pos, 0);
- CHECK_GT(buffer.length(), log_pos);
+ CHECK_EQ(0, log_pos);
CompileAndRunScript("var a = (function(x) { return x + 1; })(10);");
@@ -438,7 +438,7 @@
class SimpleExternalString : public v8::String::ExternalStringResource {
public:
explicit SimpleExternalString(const char* source)
- : utf_source_(strlen(source)) {
+ : utf_source_(StrLength(source)) {
for (int i = 0; i < utf_source_.length(); ++i)
utf_source_[i] = source[i];
}
@@ -474,6 +474,145 @@
}
+static v8::Handle<v8::Value> ObjMethod1(const v8::Arguments& args) {
+ return v8::Handle<v8::Value>();
+}
+
+TEST(LogCallbacks) {
+ const bool saved_prof_lazy = i::FLAG_prof_lazy;
+ const bool saved_prof = i::FLAG_prof;
+ const bool saved_prof_auto = i::FLAG_prof_auto;
+ i::FLAG_prof = true;
+ i::FLAG_prof_lazy = false;
+ i::FLAG_prof_auto = false;
+ i::FLAG_logfile = "*";
+
+ // If tests are being run manually, V8 will be already initialized
+ // by the bottom test.
+ const bool need_to_set_up_logger = i::V8::IsRunning();
+ v8::HandleScope scope;
+ v8::Handle<v8::Context> env = v8::Context::New();
+ if (need_to_set_up_logger) Logger::Setup();
+ env->Enter();
+
+ // Skip all initially logged stuff.
+ EmbeddedVector<char, 102400> buffer;
+ int log_pos = GetLogLines(0, &buffer);
+
+ v8::Persistent<v8::FunctionTemplate> obj =
+ v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New());
+ obj->SetClassName(v8::String::New("Obj"));
+ v8::Handle<v8::ObjectTemplate> proto = obj->PrototypeTemplate();
+ v8::Local<v8::Signature> signature = v8::Signature::New(obj);
+ proto->Set(v8::String::New("method1"),
+ v8::FunctionTemplate::New(ObjMethod1,
+ v8::Handle<v8::Value>(),
+ signature),
+ static_cast<v8::PropertyAttribute>(v8::DontDelete));
+
+ env->Global()->Set(v8_str("Obj"), obj->GetFunction());
+ CompileAndRunScript("Obj.prototype.method1.toString();");
+
+ i::Logger::LogCompiledFunctions();
+ log_pos = GetLogLines(log_pos, &buffer);
+ CHECK_GT(log_pos, 0);
+ buffer[log_pos] = 0;
+
+ const char* callback_rec = "code-creation,Callback,";
+ char* pos = strstr(buffer.start(), callback_rec);
+ CHECK_NE(NULL, pos);
+ pos += strlen(callback_rec);
+ EmbeddedVector<char, 100> ref_data;
+ i::OS::SNPrintF(ref_data,
+ "0x%" V8PRIxPTR ",1,\"method1\"", ObjMethod1);
+ *(pos + strlen(ref_data.start())) = '\0';
+ CHECK_EQ(ref_data.start(), pos);
+
+ obj.Dispose();
+
+ env->Exit();
+ Logger::TearDown();
+ i::FLAG_prof_lazy = saved_prof_lazy;
+ i::FLAG_prof = saved_prof;
+ i::FLAG_prof_auto = saved_prof_auto;
+}
+
+
+static v8::Handle<v8::Value> Prop1Getter(v8::Local<v8::String> property,
+ const v8::AccessorInfo& info) {
+ return v8::Handle<v8::Value>();
+}
+
+static void Prop1Setter(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo& info) {
+}
+
+static v8::Handle<v8::Value> Prop2Getter(v8::Local<v8::String> property,
+ const v8::AccessorInfo& info) {
+ return v8::Handle<v8::Value>();
+}
+
+TEST(LogAccessorCallbacks) {
+ const bool saved_prof_lazy = i::FLAG_prof_lazy;
+ const bool saved_prof = i::FLAG_prof;
+ const bool saved_prof_auto = i::FLAG_prof_auto;
+ i::FLAG_prof = true;
+ i::FLAG_prof_lazy = false;
+ i::FLAG_prof_auto = false;
+ i::FLAG_logfile = "*";
+
+ // If tests are being run manually, V8 will be already initialized
+ // by the bottom test.
+ const bool need_to_set_up_logger = i::V8::IsRunning();
+ v8::HandleScope scope;
+ v8::Handle<v8::Context> env = v8::Context::New();
+ if (need_to_set_up_logger) Logger::Setup();
+ env->Enter();
+
+ // Skip all initially logged stuff.
+ EmbeddedVector<char, 102400> buffer;
+ int log_pos = GetLogLines(0, &buffer);
+
+ v8::Persistent<v8::FunctionTemplate> obj =
+ v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New());
+ obj->SetClassName(v8::String::New("Obj"));
+ v8::Handle<v8::ObjectTemplate> inst = obj->InstanceTemplate();
+ inst->SetAccessor(v8::String::New("prop1"), Prop1Getter, Prop1Setter);
+ inst->SetAccessor(v8::String::New("prop2"), Prop2Getter);
+
+ i::Logger::LogAccessorCallbacks();
+ log_pos = GetLogLines(log_pos, &buffer);
+ CHECK_GT(log_pos, 0);
+ buffer[log_pos] = 0;
+ printf("%s", buffer.start());
+
+ EmbeddedVector<char, 100> prop1_getter_record;
+ i::OS::SNPrintF(prop1_getter_record,
+ "code-creation,Callback,0x%" V8PRIxPTR ",1,\"get prop1\"",
+ Prop1Getter);
+ CHECK_NE(NULL, strstr(buffer.start(), prop1_getter_record.start()));
+ EmbeddedVector<char, 100> prop1_setter_record;
+ i::OS::SNPrintF(prop1_setter_record,
+ "code-creation,Callback,0x%" V8PRIxPTR ",1,\"set prop1\"",
+ Prop1Setter);
+ CHECK_NE(NULL, strstr(buffer.start(), prop1_setter_record.start()));
+ EmbeddedVector<char, 100> prop2_getter_record;
+ i::OS::SNPrintF(prop2_getter_record,
+ "code-creation,Callback,0x%" V8PRIxPTR ",1,\"get prop2\"",
+ Prop2Getter);
+ CHECK_NE(NULL, strstr(buffer.start(), prop2_getter_record.start()));
+
+ obj.Dispose();
+
+ env->Exit();
+ Logger::TearDown();
+ i::FLAG_prof_lazy = saved_prof_lazy;
+ i::FLAG_prof = saved_prof;
+ i::FLAG_prof_auto = saved_prof_auto;
+}
+
+
static inline bool IsStringEqualTo(const char* r, const char* s) {
return strncmp(r, s, strlen(r)) == 0;
}
@@ -593,7 +732,7 @@
entities[i] = NULL;
}
const size_t map_length = bounds.Length();
- entities_map = i::NewArray<int>(map_length);
+ entities_map = i::NewArray<int>(static_cast<int>(map_length));
for (size_t i = 0; i < map_length; ++i) {
entities_map[i] = -1;
}
@@ -769,7 +908,7 @@
const int max_len = 50;
if (entity != NULL) {
char* eol = strchr(entity, '\n');
- int len = eol - entity;
+ int len = static_cast<int>(eol - entity);
len = len <= max_len ? len : max_len;
printf("%-*.*s ", max_len, len, entity);
} else {
@@ -789,7 +928,7 @@
static inline int StrChrLen(const char* s, char c) {
- return strchr(s, c) - s;
+ return static_cast<int>(strchr(s, c) - s);
}
diff --git a/test/cctest/test-macro-assembler-x64.cc b/test/cctest/test-macro-assembler-x64.cc
index 9c1197f..511b933 100755
--- a/test/cctest/test-macro-assembler-x64.cc
+++ b/test/cctest/test-macro-assembler-x64.cc
@@ -57,7 +57,7 @@
using v8::internal::r8;
using v8::internal::r9;
using v8::internal::r11;
-using v8::internal::r12;
+using v8::internal::r12; // Remember: r12..r15 are callee save!
using v8::internal::r13;
using v8::internal::r14;
using v8::internal::r15;
@@ -133,7 +133,7 @@
true));
CHECK(buffer);
HandleScope handles;
- MacroAssembler assembler(buffer, actual_size);
+ MacroAssembler assembler(buffer, static_cast<int>(actual_size));
MacroAssembler* masm = &assembler; // Create a pointer for the __ macro.
masm->set_allow_stub_calls(false);
Label exit;
@@ -218,7 +218,7 @@
true));
CHECK(buffer);
HandleScope handles;
- MacroAssembler assembler(buffer, actual_size);
+ MacroAssembler assembler(buffer, static_cast<int>(actual_size));
MacroAssembler* masm = &assembler;
masm->set_allow_stub_calls(false);
@@ -265,7 +265,7 @@
true));
CHECK(buffer);
HandleScope handles;
- MacroAssembler assembler(buffer, actual_size);
+ MacroAssembler assembler(buffer, static_cast<int>(actual_size));
MacroAssembler* masm = &assembler;
masm->set_allow_stub_calls(false);
@@ -364,7 +364,7 @@
int64_t result = x + y;
ASSERT(Smi::IsValid(result));
__ movl(rax, Immediate(id));
- __ Move(r8, Smi::FromInt(result));
+ __ Move(r8, Smi::FromInt(static_cast<int>(result)));
__ movq(rcx, x, RelocInfo::NONE);
__ movq(r11, rcx);
__ Integer64PlusConstantToSmi(rdx, rcx, y);
@@ -390,7 +390,7 @@
true));
CHECK(buffer);
HandleScope handles;
- MacroAssembler assembler(buffer, actual_size);
+ MacroAssembler assembler(buffer, static_cast<int>(actual_size));
MacroAssembler* masm = &assembler;
masm->set_allow_stub_calls(false);
@@ -431,7 +431,7 @@
true));
CHECK(buffer);
HandleScope handles;
- MacroAssembler assembler(buffer, actual_size);
+ MacroAssembler assembler(buffer, static_cast<int>(actual_size));
MacroAssembler* masm = &assembler;
masm->set_allow_stub_calls(false);
@@ -676,7 +676,7 @@
true));
CHECK(buffer);
HandleScope handles;
- MacroAssembler assembler(buffer, actual_size);
+ MacroAssembler assembler(buffer, static_cast<int>(actual_size));
MacroAssembler* masm = &assembler;
masm->set_allow_stub_calls(false);
@@ -761,7 +761,7 @@
true));
CHECK(buffer);
HandleScope handles;
- MacroAssembler assembler(buffer, actual_size);
+ MacroAssembler assembler(buffer, static_cast<int>(actual_size));
MacroAssembler* masm = &assembler;
masm->set_allow_stub_calls(false);
@@ -948,7 +948,7 @@
true));
CHECK(buffer);
HandleScope handles;
- MacroAssembler assembler(buffer, actual_size);
+ MacroAssembler assembler(buffer, static_cast<int>(actual_size));
MacroAssembler* masm = &assembler;
masm->set_allow_stub_calls(false);
@@ -1035,7 +1035,7 @@
true));
CHECK(buffer);
HandleScope handles;
- MacroAssembler assembler(buffer, actual_size);
+ MacroAssembler assembler(buffer, static_cast<int>(actual_size));
MacroAssembler* masm = &assembler;
masm->set_allow_stub_calls(false);
@@ -1138,12 +1138,14 @@
true));
CHECK(buffer);
HandleScope handles;
- MacroAssembler assembler(buffer, actual_size);
+ MacroAssembler assembler(buffer, static_cast<int>(actual_size));
MacroAssembler* masm = &assembler;
masm->set_allow_stub_calls(false);
Label exit;
+ __ push(r12);
+ __ push(r15);
TestSmiDiv(masm, &exit, 0x10, 1, 1);
TestSmiDiv(masm, &exit, 0x20, 1, 0);
TestSmiDiv(masm, &exit, 0x30, -1, 0);
@@ -1168,6 +1170,8 @@
__ xor_(r15, r15); // Success.
__ bind(&exit);
__ movq(rax, r15);
+ __ pop(r15);
+ __ pop(r12);
__ ret(0);
CodeDesc desc;
@@ -1241,12 +1245,14 @@
true));
CHECK(buffer);
HandleScope handles;
- MacroAssembler assembler(buffer, actual_size);
+ MacroAssembler assembler(buffer, static_cast<int>(actual_size));
MacroAssembler* masm = &assembler;
masm->set_allow_stub_calls(false);
Label exit;
+ __ push(r12);
+ __ push(r15);
TestSmiMod(masm, &exit, 0x10, 1, 1);
TestSmiMod(masm, &exit, 0x20, 1, 0);
TestSmiMod(masm, &exit, 0x30, -1, 0);
@@ -1271,6 +1277,8 @@
__ xor_(r15, r15); // Success.
__ bind(&exit);
__ movq(rax, r15);
+ __ pop(r15);
+ __ pop(r12);
__ ret(0);
CodeDesc desc;
@@ -1330,7 +1338,7 @@
true));
CHECK(buffer);
HandleScope handles;
- MacroAssembler assembler(buffer, actual_size);
+ MacroAssembler assembler(buffer, static_cast<int>(actual_size));
MacroAssembler* masm = &assembler;
masm->set_allow_stub_calls(false);
@@ -1396,7 +1404,7 @@
true));
CHECK(buffer);
HandleScope handles;
- MacroAssembler assembler(buffer, actual_size);
+ MacroAssembler assembler(buffer, static_cast<int>(actual_size));
MacroAssembler* masm = &assembler;
masm->set_allow_stub_calls(false); // Avoid inline checks.
@@ -1472,7 +1480,7 @@
true));
CHECK(buffer);
HandleScope handles;
- MacroAssembler assembler(buffer, actual_size);
+ MacroAssembler assembler(buffer, static_cast<int>(actual_size));
MacroAssembler* masm = &assembler;
masm->set_allow_stub_calls(false);
@@ -1550,7 +1558,7 @@
true));
CHECK(buffer);
HandleScope handles;
- MacroAssembler assembler(buffer, actual_size);
+ MacroAssembler assembler(buffer, static_cast<int>(actual_size));
MacroAssembler* masm = &assembler;
masm->set_allow_stub_calls(false);
@@ -1630,7 +1638,7 @@
true));
CHECK(buffer);
HandleScope handles;
- MacroAssembler assembler(buffer, actual_size);
+ MacroAssembler assembler(buffer, static_cast<int>(actual_size));
MacroAssembler* masm = &assembler;
masm->set_allow_stub_calls(false);
@@ -1694,7 +1702,7 @@
true));
CHECK(buffer);
HandleScope handles;
- MacroAssembler assembler(buffer, actual_size);
+ MacroAssembler assembler(buffer, static_cast<int>(actual_size));
MacroAssembler* masm = &assembler;
masm->set_allow_stub_calls(false);
@@ -1835,7 +1843,7 @@
true));
CHECK(buffer);
HandleScope handles;
- MacroAssembler assembler(buffer, actual_size);
+ MacroAssembler assembler(buffer, static_cast<int>(actual_size));
MacroAssembler* masm = &assembler;
masm->set_allow_stub_calls(false);
@@ -1872,7 +1880,7 @@
int shift = shifts[i];
intptr_t result = static_cast<unsigned int>(x) >> shift;
if (Smi::IsValid(result)) {
- __ Move(r8, Smi::FromInt(result));
+ __ Move(r8, Smi::FromInt(static_cast<int>(result)));
__ Move(rcx, Smi::FromInt(x));
__ SmiShiftLogicalRightConstant(r9, rcx, shift, exit);
@@ -1938,7 +1946,7 @@
true));
CHECK(buffer);
HandleScope handles;
- MacroAssembler assembler(buffer, actual_size);
+ MacroAssembler assembler(buffer, static_cast<int>(actual_size));
MacroAssembler* masm = &assembler;
masm->set_allow_stub_calls(false);
@@ -2004,7 +2012,7 @@
true));
CHECK(buffer);
HandleScope handles;
- MacroAssembler assembler(buffer, actual_size);
+ MacroAssembler assembler(buffer, static_cast<int>(actual_size));
MacroAssembler* masm = &assembler;
masm->set_allow_stub_calls(false);
@@ -2065,7 +2073,7 @@
true));
CHECK(buffer);
HandleScope handles;
- MacroAssembler assembler(buffer, actual_size);
+ MacroAssembler assembler(buffer, static_cast<int>(actual_size));
MacroAssembler* masm = &assembler;
masm->set_allow_stub_calls(false);
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
new file mode 100755
index 0000000..d62b6a5
--- /dev/null
+++ b/test/cctest/test-parsing.cc
@@ -0,0 +1,129 @@
+// Copyright 2006-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.
+
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "token.h"
+#include "scanner.h"
+#include "utils.h"
+
+#include "cctest.h"
+
+namespace i = ::v8::internal;
+
+TEST(KeywordMatcher) {
+ struct KeywordToken {
+ const char* keyword;
+ i::Token::Value token;
+ };
+
+ static const KeywordToken keywords[] = {
+#define KEYWORD(t, s, d) { s, i::Token::t },
+#define IGNORE(t, s, d) /* */
+ TOKEN_LIST(IGNORE, KEYWORD, IGNORE)
+#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;
+ 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]);
+ }
+ 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]);
+ }
+ CHECK_EQ(i::Token::IDENTIFIER, matcher.token());
+ }
+
+ // 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());
+}
+
diff --git a/test/cctest/test-regexp.cc b/test/cctest/test-regexp.cc
index 81c2205..6aa0730 100644
--- a/test/cctest/test-regexp.cc
+++ b/test/cctest/test-regexp.cc
@@ -74,7 +74,7 @@
static bool CheckSimple(const char* input) {
V8::Initialize(NULL);
v8::HandleScope scope;
- unibrow::Utf8InputBuffer<> buffer(input, strlen(input));
+ unibrow::Utf8InputBuffer<> buffer(input, StrLength(input));
ZoneScope zone_scope(DELETE_ON_EXIT);
FlatStringReader reader(CStrVector(input));
RegExpCompileData result;
@@ -92,7 +92,7 @@
static MinMaxPair CheckMinMaxMatch(const char* input) {
V8::Initialize(NULL);
v8::HandleScope scope;
- unibrow::Utf8InputBuffer<> buffer(input, strlen(input));
+ unibrow::Utf8InputBuffer<> buffer(input, StrLength(input));
ZoneScope zone_scope(DELETE_ON_EXIT);
FlatStringReader reader(CStrVector(input));
RegExpCompileData result;
@@ -1466,7 +1466,7 @@
ZoneScope zone_scope(DELETE_ON_EXIT);
int count = expected.length();
ZoneList<CharacterRange>* list = new ZoneList<CharacterRange>(count);
- input.AddCaseEquivalents(list);
+ input.AddCaseEquivalents(list, false);
CHECK_EQ(count, list->length());
for (int i = 0; i < list->length(); i++) {
CHECK_EQ(expected[i].from(), list->at(i).from());
diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc
index db37eb3..8f4441a 100644
--- a/test/cctest/test-serialize.cc
+++ b/test/cctest/test-serialize.cc
@@ -123,13 +123,17 @@
ExternalReference::the_hole_value_location();
CHECK_EQ(make_code(UNCLASSIFIED, 2),
encoder.Encode(the_hole_value_location.address()));
- ExternalReference stack_guard_limit_address =
- ExternalReference::address_of_stack_guard_limit();
+ ExternalReference stack_limit_address =
+ ExternalReference::address_of_stack_limit();
CHECK_EQ(make_code(UNCLASSIFIED, 4),
- encoder.Encode(stack_guard_limit_address.address()));
- CHECK_EQ(make_code(UNCLASSIFIED, 10),
+ encoder.Encode(stack_limit_address.address()));
+ ExternalReference real_stack_limit_address =
+ ExternalReference::address_of_real_stack_limit();
+ CHECK_EQ(make_code(UNCLASSIFIED, 5),
+ encoder.Encode(real_stack_limit_address.address()));
+ CHECK_EQ(make_code(UNCLASSIFIED, 11),
encoder.Encode(ExternalReference::debug_break().address()));
- CHECK_EQ(make_code(UNCLASSIFIED, 6),
+ CHECK_EQ(make_code(UNCLASSIFIED, 7),
encoder.Encode(ExternalReference::new_space_start().address()));
CHECK_EQ(make_code(UNCLASSIFIED, 3),
encoder.Encode(ExternalReference::roots_address().address()));
@@ -158,74 +162,49 @@
decoder.Decode(make_code(UNCLASSIFIED, 1)));
CHECK_EQ(ExternalReference::the_hole_value_location().address(),
decoder.Decode(make_code(UNCLASSIFIED, 2)));
- CHECK_EQ(ExternalReference::address_of_stack_guard_limit().address(),
+ CHECK_EQ(ExternalReference::address_of_stack_limit().address(),
decoder.Decode(make_code(UNCLASSIFIED, 4)));
+ CHECK_EQ(ExternalReference::address_of_real_stack_limit().address(),
+ decoder.Decode(make_code(UNCLASSIFIED, 5)));
CHECK_EQ(ExternalReference::debug_break().address(),
- decoder.Decode(make_code(UNCLASSIFIED, 10)));
+ decoder.Decode(make_code(UNCLASSIFIED, 11)));
CHECK_EQ(ExternalReference::new_space_start().address(),
- decoder.Decode(make_code(UNCLASSIFIED, 6)));
+ decoder.Decode(make_code(UNCLASSIFIED, 7)));
}
static void Serialize() {
-#ifdef DEBUG
- FLAG_debug_serialization = true;
-#endif
- StatsTable::SetCounterFunction(counter_function);
-
- v8::HandleScope scope;
- const int kExtensionCount = 1;
- const char* extension_list[kExtensionCount] = { "v8/gc" };
- v8::ExtensionConfiguration extensions(kExtensionCount, extension_list);
- Serializer::Enable();
- v8::Persistent<v8::Context> env = v8::Context::New(&extensions);
- env->Enter();
-
+ // We have to create one context. One reason for this is so that the builtins
+ // can be loaded from v8natives.js and their addresses can be processed. This
+ // will clear the pending fixups array, which would otherwise contain GC roots
+ // that would confuse the serialization/deserialization process.
+ v8::Persistent<v8::Context> env = v8::Context::New();
+ env.Dispose();
Snapshot::WriteToFile(FLAG_testing_serialization_file);
}
-// Test that the whole heap can be serialized when running from the
-// internal snapshot.
-// (Smoke test.)
-TEST(SerializeInternal) {
- Snapshot::Initialize(NULL);
- Serialize();
-}
-
-
-// Test that the whole heap can be serialized when running from a
-// bootstrapped heap.
-// (Smoke test.)
+// Test that the whole heap can be serialized.
TEST(Serialize) {
- if (Snapshot::IsEnabled()) return;
+ Serializer::Enable();
+ v8::V8::Initialize();
Serialize();
}
-// Test that the heap isn't destroyed after a serialization.
-TEST(SerializeNondestructive) {
- if (Snapshot::IsEnabled()) return;
- StatsTable::SetCounterFunction(counter_function);
- v8::HandleScope scope;
+// Test that heap serialization is non-destructive.
+TEST(SerializeTwice) {
Serializer::Enable();
- v8::Persistent<v8::Context> env = v8::Context::New();
- v8::Context::Scope context_scope(env);
- Serializer().Serialize();
- const char* c_source = "\"abcd\".charAt(2) == 'c'";
- v8::Local<v8::String> source = v8::String::New(c_source);
- v8::Local<v8::Script> script = v8::Script::Compile(source);
- v8::Local<v8::Value> value = script->Run();
- CHECK(value->BooleanValue());
+ v8::V8::Initialize();
+ Serialize();
+ Serialize();
}
+
//----------------------------------------------------------------------------
// Tests that the heap can be deserialized.
static void Deserialize() {
-#ifdef DEBUG
- FLAG_debug_serialization = true;
-#endif
CHECK(Snapshot::Initialize(FLAG_testing_serialization_file));
}
@@ -248,14 +227,33 @@
Deserialize();
+ v8::Persistent<v8::Context> env = v8::Context::New();
+ env->Enter();
+
SanityCheck();
}
-DEPENDENT_TEST(DeserializeAndRunScript, Serialize) {
+
+DEPENDENT_TEST(DeserializeFromSecondSerialization, SerializeTwice) {
v8::HandleScope scope;
Deserialize();
+ v8::Persistent<v8::Context> env = v8::Context::New();
+ env->Enter();
+
+ SanityCheck();
+}
+
+
+DEPENDENT_TEST(DeserializeAndRunScript2, Serialize) {
+ v8::HandleScope scope;
+
+ Deserialize();
+
+ v8::Persistent<v8::Context> env = v8::Context::New();
+ env->Enter();
+
const char* c_source = "\"1234\".length";
v8::Local<v8::String> source = v8::String::New(c_source);
v8::Local<v8::Script> script = v8::Script::Compile(source);
@@ -263,34 +261,22 @@
}
-DEPENDENT_TEST(DeserializeNatives, Serialize) {
+DEPENDENT_TEST(DeserializeFromSecondSerializationAndRunScript2,
+ SerializeTwice) {
v8::HandleScope scope;
Deserialize();
- const char* c_source = "\"abcd\".charAt(2) == 'c'";
+ v8::Persistent<v8::Context> env = v8::Context::New();
+ env->Enter();
+
+ const char* c_source = "\"1234\".length";
v8::Local<v8::String> source = v8::String::New(c_source);
v8::Local<v8::Script> script = v8::Script::Compile(source);
- v8::Local<v8::Value> value = script->Run();
- CHECK(value->BooleanValue());
+ CHECK_EQ(4, script->Run()->Int32Value());
}
-DEPENDENT_TEST(DeserializeExtensions, Serialize) {
- v8::HandleScope scope;
-
- Deserialize();
- const char* c_source = "gc();";
- v8::Local<v8::String> source = v8::String::New(c_source);
- v8::Local<v8::Script> script = v8::Script::Compile(source);
- v8::Local<v8::Value> value = script->Run();
- CHECK(value->IsUndefined());
-}
-
-
-extern "C" void V8_Fatal(const char* file, int line, const char* format, ...);
-
-
TEST(TestThatAlwaysSucceeds) {
}
diff --git a/test/cctest/test-strings.cc b/test/cctest/test-strings.cc
index bb9a6f9..59a40af 100644
--- a/test/cctest/test-strings.cc
+++ b/test/cctest/test-strings.cc
@@ -63,6 +63,21 @@
};
+class AsciiResource: public v8::String::ExternalAsciiStringResource,
+ public ZoneObject {
+ public:
+ explicit AsciiResource(Vector<const char> string): data_(string.start()) {
+ length_ = string.length();
+ }
+ virtual const char* data() const { return data_; }
+ virtual size_t length() const { return length_; }
+
+ private:
+ const char* data_;
+ size_t length_;
+};
+
+
static void InitializeBuildingBlocks(
Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS]) {
// A list of pointers that we don't have any interest in cleaning up.
@@ -241,17 +256,6 @@
printf("6\n");
TraverseFirst(left_asymmetric, right_deep_asymmetric, 65536);
printf("7\n");
- Handle<String> right_deep_slice =
- Factory::NewStringSlice(left_deep_asymmetric,
- left_deep_asymmetric->length() - 1050,
- left_deep_asymmetric->length() - 50);
- Handle<String> left_deep_slice =
- Factory::NewStringSlice(right_deep_asymmetric,
- right_deep_asymmetric->length() - 1050,
- right_deep_asymmetric->length() - 50);
- printf("8\n");
- Traverse(right_deep_slice, left_deep_slice);
- printf("9\n");
FlattenString(left_asymmetric);
printf("10\n");
Traverse(flat, left_asymmetric);
@@ -269,60 +273,6 @@
}
-static Handle<String> SliceOf(Handle<String> underlying) {
- int start = gen() % underlying->length();
- int end = start + gen() % (underlying->length() - start);
- return Factory::NewStringSlice(underlying,
- start,
- end);
-}
-
-
-static Handle<String> ConstructSliceTree(
- Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS],
- int from,
- int to) {
- CHECK(to > from);
- if (to - from <= 1)
- return SliceOf(building_blocks[from % NUMBER_OF_BUILDING_BLOCKS]);
- if (to - from == 2) {
- Handle<String> lhs = building_blocks[from % NUMBER_OF_BUILDING_BLOCKS];
- if (gen() % 2 == 0)
- lhs = SliceOf(lhs);
- Handle<String> rhs = building_blocks[(from+1) % NUMBER_OF_BUILDING_BLOCKS];
- if (gen() % 2 == 0)
- rhs = SliceOf(rhs);
- return Factory::NewConsString(lhs, rhs);
- }
- Handle<String> part1 =
- ConstructBalancedHelper(building_blocks, from, from + ((to - from) / 2));
- Handle<String> part2 =
- ConstructBalancedHelper(building_blocks, from + ((to - from) / 2), to);
- Handle<String> branch = Factory::NewConsString(part1, part2);
- if (gen() % 2 == 0)
- return branch;
- return(SliceOf(branch));
-}
-
-
-TEST(Slice) {
- printf("TestSlice\n");
- InitializeVM();
- v8::HandleScope scope;
- Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS];
- ZoneScope zone(DELETE_ON_EXIT);
- InitializeBuildingBlocks(building_blocks);
-
- seed = 42;
- Handle<String> slice_tree =
- ConstructSliceTree(building_blocks, 0, DEEP_DEPTH);
- seed = 42;
- Handle<String> flat_slice_tree =
- ConstructSliceTree(building_blocks, 0, DEEP_DEPTH);
- FlattenString(flat_slice_tree);
- Traverse(flat_slice_tree, slice_tree);
-}
-
static const int DEEP_ASCII_DEPTH = 100000;
@@ -357,8 +307,10 @@
v8::HandleScope handle_scope;
// A simple ascii string
const char* ascii_string = "abcdef12345";
- int len = v8::String::New(ascii_string, strlen(ascii_string))->Utf8Length();
- CHECK_EQ(strlen(ascii_string), len);
+ int len =
+ v8::String::New(ascii_string,
+ StrLength(ascii_string))->Utf8Length();
+ CHECK_EQ(StrLength(ascii_string), len);
// A mixed ascii and non-ascii string
// U+02E4 -> CB A4
// U+0064 -> 64
@@ -392,127 +344,89 @@
}
-class TwoByteResource: public v8::String::ExternalStringResource {
- public:
- TwoByteResource(const uint16_t* data, size_t length, bool* destructed)
- : data_(data), length_(length), destructed_(destructed) {
- CHECK_NE(destructed, NULL);
- *destructed_ = false;
- }
+TEST(ExternalShortStringAdd) {
+ ZoneScope zone(DELETE_ON_EXIT);
- virtual ~TwoByteResource() {
- CHECK_NE(destructed_, NULL);
- CHECK(!*destructed_);
- *destructed_ = true;
- }
-
- const uint16_t* data() const { return data_; }
- size_t length() const { return length_; }
-
- private:
- const uint16_t* data_;
- size_t length_;
- bool* destructed_;
-};
-
-
-// Regression test case for http://crbug.com/9746. The problem was
-// that when we marked objects reachable only through weak pointers,
-// we ended up keeping a sliced symbol alive, even though we already
-// invoked the weak callback on the underlying external string thus
-// deleting its resource.
-TEST(Regress9746) {
InitializeVM();
+ v8::HandleScope handle_scope;
- // Setup lengths that guarantee we'll get slices instead of simple
- // flat strings.
- static const int kFullStringLength = String::kMinNonFlatLength * 2;
- static const int kSliceStringLength = String::kMinNonFlatLength + 1;
+ // Make sure we cover all always-flat lengths and at least one above.
+ static const int kMaxLength = 20;
+ CHECK_GT(kMaxLength, i::String::kMinNonFlatLength);
- uint16_t* source = new uint16_t[kFullStringLength];
- for (int i = 0; i < kFullStringLength; i++) source[i] = '1';
- char* key = new char[kSliceStringLength];
- for (int i = 0; i < kSliceStringLength; i++) key[i] = '1';
- Vector<const char> key_vector(key, kSliceStringLength);
+ // Allocate two JavaScript arrays for holding short strings.
+ v8::Handle<v8::Array> ascii_external_strings =
+ v8::Array::New(kMaxLength + 1);
+ v8::Handle<v8::Array> non_ascii_external_strings =
+ v8::Array::New(kMaxLength + 1);
- // Allocate an external string resource that keeps track of when it
- // is destructed.
- bool resource_destructed = false;
- TwoByteResource* resource =
- new TwoByteResource(source, kFullStringLength, &resource_destructed);
-
- {
- v8::HandleScope scope;
-
- // Allocate an external string resource and external string. We
- // have to go through the API to get the weak handle and the
- // automatic destruction going.
- Handle<String> string =
- v8::Utils::OpenHandle(*v8::String::NewExternal(resource));
-
- // Create a slice of the external string.
- Handle<String> slice =
- Factory::NewStringSlice(string, 0, kSliceStringLength);
- CHECK_EQ(kSliceStringLength, slice->length());
- CHECK(StringShape(*slice).IsSliced());
-
- // Make sure the slice ends up in old space so we can morph it
- // into a symbol.
- while (Heap::InNewSpace(*slice)) {
- Heap::PerformScavenge();
+ // Generate short ascii and non-ascii external strings.
+ for (int i = 0; i <= kMaxLength; i++) {
+ char* ascii = Zone::NewArray<char>(i + 1);
+ for (int j = 0; j < i; j++) {
+ ascii[j] = 'a';
}
+ // Terminating '\0' is left out on purpose. It is not required for external
+ // string data.
+ AsciiResource* ascii_resource =
+ new AsciiResource(Vector<const char>(ascii, i));
+ v8::Local<v8::String> ascii_external_string =
+ v8::String::NewExternal(ascii_resource);
- // Force the slice into the symbol table.
- slice = Factory::SymbolFromString(slice);
- CHECK(slice->IsSymbol());
- CHECK(StringShape(*slice).IsSliced());
-
- Handle<String> buffer(Handle<SlicedString>::cast(slice)->buffer());
- CHECK(StringShape(*buffer).IsExternal());
- CHECK(buffer->IsTwoByteRepresentation());
-
- // Finally, base a script on the slice of the external string and
- // get its wrapper. This allocates yet another weak handle that
- // indirectly refers to the external string.
- Handle<Script> script = Factory::NewScript(slice);
- Handle<JSObject> wrapper = GetScriptWrapper(script);
+ ascii_external_strings->Set(v8::Integer::New(i), ascii_external_string);
+ uc16* non_ascii = Zone::NewArray<uc16>(i + 1);
+ for (int j = 0; j < i; j++) {
+ non_ascii[j] = 0x1234;
+ }
+ // Terminating '\0' is left out on purpose. It is not required for external
+ // string data.
+ Resource* resource = new Resource(Vector<const uc16>(non_ascii, i));
+ v8::Local<v8::String> non_ascii_external_string =
+ v8::String::NewExternal(resource);
+ non_ascii_external_strings->Set(v8::Integer::New(i),
+ non_ascii_external_string);
}
- // When we collect all garbage, we cannot get rid of the sliced
- // symbol entry in the symbol table because it is used by the script
- // kept alive by the weak wrapper. Make sure we don't destruct the
- // external string.
- Heap::CollectAllGarbage(false);
- CHECK(!resource_destructed);
+ // Add the arrays with the short external strings in the global object.
+ v8::Handle<v8::Object> global = env->Global();
+ global->Set(v8_str("external_ascii"), ascii_external_strings);
+ global->Set(v8_str("external_non_ascii"), non_ascii_external_strings);
+ global->Set(v8_str("max_length"), v8::Integer::New(kMaxLength));
- {
- v8::HandleScope scope;
-
- // Make sure the sliced symbol is still in the table.
- Handle<String> symbol = Factory::LookupSymbol(key_vector);
- CHECK(StringShape(*symbol).IsSliced());
-
- // Make sure the buffer is still a two-byte external string.
- Handle<String> buffer(Handle<SlicedString>::cast(symbol)->buffer());
- CHECK(StringShape(*buffer).IsExternal());
- CHECK(buffer->IsTwoByteRepresentation());
- }
-
- // Forcing another garbage collection should let us get rid of the
- // slice from the symbol table. The external string remains in the
- // heap until the next GC.
- Heap::CollectAllGarbage(false);
- CHECK(!resource_destructed);
- v8::HandleScope scope;
- Handle<String> key_string = Factory::NewStringFromAscii(key_vector);
- String* out;
- CHECK(!Heap::LookupSymbolIfExists(*key_string, &out));
-
- // Forcing yet another garbage collection must allow us to finally
- // get rid of the external string.
- Heap::CollectAllGarbage(false);
- CHECK(resource_destructed);
-
- delete[] source;
- delete[] key;
+ // Add short external ascii and non-ascii strings checking the result.
+ static const char* source =
+ "function test() {"
+ " var ascii_chars = 'aaaaaaaaaaaaaaaaaaaa';"
+ " var non_ascii_chars = '\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234';" //NOLINT
+ " if (ascii_chars.length != max_length) return 1;"
+ " if (non_ascii_chars.length != max_length) return 2;"
+ " var ascii = Array(max_length + 1);"
+ " var non_ascii = Array(max_length + 1);"
+ " for (var i = 0; i <= max_length; i++) {"
+ " ascii[i] = ascii_chars.substring(0, i);"
+ " non_ascii[i] = non_ascii_chars.substring(0, i);"
+ " };"
+ " for (var i = 0; i <= max_length; i++) {"
+ " if (ascii[i] != external_ascii[i]) return 3;"
+ " if (non_ascii[i] != external_non_ascii[i]) return 4;"
+ " for (var j = 0; j < i; j++) {"
+ " if (external_ascii[i] !="
+ " (external_ascii[j] + external_ascii[i - j])) return 5;"
+ " if (external_non_ascii[i] !="
+ " (external_non_ascii[j] + external_non_ascii[i - j])) return 6;"
+ " if (non_ascii[i] != (non_ascii[j] + non_ascii[i - j])) return 7;"
+ " if (ascii[i] != (ascii[j] + ascii[i - j])) return 8;"
+ " if (ascii[i] != (external_ascii[j] + ascii[i - j])) return 9;"
+ " if (ascii[i] != (ascii[j] + external_ascii[i - j])) return 10;"
+ " if (non_ascii[i] !="
+ " (external_non_ascii[j] + non_ascii[i - j])) return 11;"
+ " if (non_ascii[i] !="
+ " (non_ascii[j] + external_non_ascii[i - j])) return 12;"
+ " }"
+ " }"
+ " return 0;"
+ "};"
+ "test()";
+ CHECK_EQ(0,
+ v8::Script::Compile(v8::String::New(source))->Run()->Int32Value());
}
diff --git a/test/cctest/test-thread-termination.cc b/test/cctest/test-thread-termination.cc
index 552f49d..1e8102e 100644
--- a/test/cctest/test-thread-termination.cc
+++ b/test/cctest/test-thread-termination.cc
@@ -82,14 +82,30 @@
}
+v8::Handle<v8::Value> DoLoopNoCall(const v8::Arguments& args) {
+ v8::TryCatch try_catch;
+ v8::Script::Compile(v8::String::New("var term = true;"
+ "while(true) {"
+ " if (term) terminate();"
+ " term = false;"
+ "}"))->Run();
+ CHECK(try_catch.HasCaught());
+ CHECK(try_catch.Exception()->IsNull());
+ CHECK(try_catch.Message().IsEmpty());
+ CHECK(!try_catch.CanContinue());
+ return v8::Undefined();
+}
+
+
v8::Handle<v8::ObjectTemplate> CreateGlobalTemplate(
- v8::InvocationCallback terminate) {
+ v8::InvocationCallback terminate,
+ v8::InvocationCallback doloop) {
v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
global->Set(v8::String::New("terminate"),
v8::FunctionTemplate::New(terminate));
global->Set(v8::String::New("fail"), v8::FunctionTemplate::New(Fail));
global->Set(v8::String::New("loop"), v8::FunctionTemplate::New(Loop));
- global->Set(v8::String::New("doloop"), v8::FunctionTemplate::New(DoLoop));
+ global->Set(v8::String::New("doloop"), v8::FunctionTemplate::New(doloop));
return global;
}
@@ -99,7 +115,25 @@
TEST(TerminateOnlyV8ThreadFromThreadItself) {
v8::HandleScope scope;
v8::Handle<v8::ObjectTemplate> global =
- CreateGlobalTemplate(TerminateCurrentThread);
+ CreateGlobalTemplate(TerminateCurrentThread, DoLoop);
+ v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);
+ v8::Context::Scope context_scope(context);
+ // Run a loop that will be infinite if thread termination does not work.
+ v8::Handle<v8::String> source =
+ v8::String::New("try { loop(); fail(); } catch(e) { fail(); }");
+ v8::Script::Compile(source)->Run();
+ // Test that we can run the code again after thread termination.
+ v8::Script::Compile(source)->Run();
+ context.Dispose();
+}
+
+
+// Test that a single thread of JavaScript execution can terminate
+// itself in a loop that performs no calls.
+TEST(TerminateOnlyV8ThreadFromThreadItselfNoLoop) {
+ v8::HandleScope scope;
+ v8::Handle<v8::ObjectTemplate> global =
+ CreateGlobalTemplate(TerminateCurrentThread, DoLoopNoCall);
v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);
v8::Context::Scope context_scope(context);
// Run a loop that will be infinite if thread termination does not work.
@@ -128,7 +162,7 @@
thread.Start();
v8::HandleScope scope;
- v8::Handle<v8::ObjectTemplate> global = CreateGlobalTemplate(Signal);
+ v8::Handle<v8::ObjectTemplate> global = CreateGlobalTemplate(Signal, DoLoop);
v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);
v8::Context::Scope context_scope(context);
// Run a loop that will be infinite if thread termination does not work.
@@ -149,7 +183,8 @@
v8::Locker locker;
v8::HandleScope scope;
v8_thread_id_ = v8::V8::GetCurrentThreadId();
- v8::Handle<v8::ObjectTemplate> global = CreateGlobalTemplate(Signal);
+ v8::Handle<v8::ObjectTemplate> global =
+ CreateGlobalTemplate(Signal, DoLoop);
v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);
v8::Context::Scope context_scope(context);
// Run a loop that will be infinite if thread termination does not work.
diff --git a/test/cctest/test-utils.cc b/test/cctest/test-utils.cc
index ffcaf8a..1d65e68 100644
--- a/test/cctest/test-utils.cc
+++ b/test/cctest/test-utils.cc
@@ -166,7 +166,7 @@
// Make sure that strings that are truncated because of too small
// buffers are zero-terminated anyway.
const char* s = "the quick lazy .... oh forget it!";
- int length = strlen(s);
+ int length = StrLength(s);
for (int i = 1; i < length * 2; i++) {
static const char kMarker = static_cast<char>(42);
Vector<char> buffer = Vector<char>::New(i + 1);
@@ -177,9 +177,9 @@
CHECK_EQ(0, strncmp(buffer.start(), s, i - 1));
CHECK_EQ(kMarker, buffer[i]);
if (i <= length) {
- CHECK_EQ(i - 1, strlen(buffer.start()));
+ CHECK_EQ(i - 1, StrLength(buffer.start()));
} else {
- CHECK_EQ(length, strlen(buffer.start()));
+ CHECK_EQ(length, StrLength(buffer.start()));
}
buffer.Dispose();
}
diff --git a/test/mjsunit/arguments-read-and-assignment.js b/test/mjsunit/arguments-read-and-assignment.js
new file mode 100644
index 0000000..c5d34bf
--- /dev/null
+++ b/test/mjsunit/arguments-read-and-assignment.js
@@ -0,0 +1,164 @@
+// 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.
+// Testing basic functionality of the arguments object.
+// Introduced to ensure that the fast compiler does the right thing.
+// The arguments object itself.
+assertEquals(42, function(){ return arguments;}(42)[0],
+ "return arguments value");
+assertEquals(42, function(){ return arguments;}(42)[0],
+ "arguments in plain value context");
+assertEquals(42, function(){ arguments;return 42}(37),
+ "arguments in effect context");
+assertEquals(42, function(){ if(arguments)return 42;}(),
+ "arguments in a boolean context");
+assertEquals(42, function(){ return arguments || true;}(42)[0],
+ "arguments in a short-circuit boolean context - or");
+assertEquals(true, function(){ return arguments && [true];}(42)[0],
+ "arguments in a short-circuit boolean context - and");
+assertEquals(42, function(){ arguments = 42; return 42;}(),
+ "arguments assignment");
+// Properties of the arguments object.
+assertEquals(42, function(){ return arguments[0]; }(42),
+ "args[0] value returned");
+assertEquals(42, function(){ arguments[0]; return 42}(),
+ "args[0] value ignored");
+assertEquals(42, function(){ if (arguments[0]) return 42; }(37),
+ "args[0] to boolean");
+assertEquals(42, function(){ return arguments[0] || "no"; }(42),
+ "args[0] short-circuit boolean or true");
+assertEquals(42, function(){ return arguments[0] || 42; }(0),
+ "args[0] short-circuit boolean or false");
+assertEquals(37, function(){ return arguments[0] && 37; }(42),
+ "args[0] short-circuit boolean and true");
+assertEquals(0, function(){ return arguments[0] && 42; }(0),
+ "args[0] short-circuit boolean and false");
+assertEquals(42, function(){ arguments[0] = 42; return arguments[0]; }(37),
+ "args[0] assignment");
+// Link between arguments and parameters.
+assertEquals(42, function(a) { arguments[0] = 42; return a; }(37),
+ "assign args[0]->a");
+assertEquals(42, function(a) { a = 42; return arguments[0]; }(37),
+ "assign a->args[0]");
+assertEquals(54, function(a, b) { arguments[1] = 54; return b; }(42, 37),
+ "assign args[1]->b:b");
+assertEquals(54, function(a, b) { b = 54; return arguments[1]; }(42, 47),
+ "assign b->args[1]:b");
+assertEquals(42, function(a, b) { arguments[1] = 54; return a; }(42, 37),
+ "assign args[1]->b:a");
+assertEquals(42, function(a, b) { b = 54; return arguments[0]; }(42, 47),
+ "assign b->args[1]:a");
+
+// Capture parameters in nested contexts.
+assertEquals(33,
+ function(a,b) {
+ return a + arguments[0] +
+ function(b){ return a + b + arguments[0]; }(b); }(7,6),
+ "captured parameters");
+assertEquals(42, function(a) {
+ arguments[0] = 42;
+ return function(b){ return a; }();
+ }(37),
+ "capture value returned");
+assertEquals(42,
+ function(a) {
+ arguments[0] = 26;
+ return function(b){ a; return 42; }();
+ }(37),
+ "capture value ignored");
+assertEquals(42,
+ function(a) {
+ arguments[0] = 26;
+ return function(b){ if (a) return 42; }();
+ }(37),
+ "capture to boolean");
+assertEquals(42,
+ function(a) {
+ arguments[0] = 42;
+ return function(b){ return a || "no"; }();
+ }(37),
+ "capture short-circuit boolean or true");
+assertEquals(0,
+ function(a) {
+ arguments[0] = 0;
+ return function(b){ return a && 42; }();
+ }(37),
+ "capture short-circuit boolean and false");
+// Deeply nested.
+assertEquals(42,
+ function(a,b) {
+ return arguments[2] +
+ function(){
+ return b +
+ function() {
+ return a;
+ }();
+ }();
+ }(7,14,21),
+ "deep nested capture");
+
+// Assignment to captured parameters.
+assertEquals(42, function(a,b) {
+ arguments[1] = 11;
+ return a + function(){ a = b; return a; }() + a;
+ }(20, 37), "captured assignment");
+
+// Inside non-function scopes.
+assertEquals(42,
+ function(a) {
+ arguments[0] = 20;
+ with ({ b : 22 }) { return a + b; }
+ }(37),
+ "a in with");
+assertEquals(42,
+ function(a) {
+ with ({ b : 22 }) { return arguments[0] + b; }
+ }(20),
+ "args in with");
+assertEquals(42,
+ function(a) {
+ arguments[0] = 20;
+ with ({ b : 22 }) {
+ return function() { return a; }() + b; }
+ }(37),
+ "captured a in with");
+assertEquals(42,
+ function(a) {
+ arguments[0] = 12;
+ with ({ b : 22 }) {
+ return function f() {
+ try { throw 8 } catch(e) { return e + a };
+ }() + b;
+ }
+ }(37),
+ "in a catch in a named function captured a in with ");
+// Escaping arguments.
+function weirdargs(a,b,c) { if (!a) return arguments;
+ return [b[2],c]; }
+var args1 = weirdargs(false, null, 40);
+var res = weirdargs(true, args1, 15);
+assertEquals(40, res[0], "return old args element");
+assertEquals(15, res[1], "return own args element");
\ No newline at end of file
diff --git a/test/mjsunit/compiler/function-call.js b/test/mjsunit/compiler/function-call.js
new file mode 100644
index 0000000..b2e0702
--- /dev/null
+++ b/test/mjsunit/compiler/function-call.js
@@ -0,0 +1,52 @@
+// 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.
+
+// Test of function calls.
+
+function f(x) { return x; }
+
+var a;
+
+// Call on global object.
+a = f(8);
+assertEquals(8, a);
+
+// Call on a named property.
+var b;
+b = {x:f};
+a = b.x(9);
+assertEquals(9, a);
+
+// Call on a keyed property.
+c = "x";
+a = b[c](10);
+assertEquals(10, a);
+
+// Call on a function expression
+function g() { return f; }
+a = g()(8);
+assertEquals(8, a);
diff --git a/test/mjsunit/compiler/globals.js b/test/mjsunit/compiler/globals.js
index 066f927..0abd5dd 100644
--- a/test/mjsunit/compiler/globals.js
+++ b/test/mjsunit/compiler/globals.js
@@ -53,3 +53,13 @@
// Test a second load.
g = 3;
assertEquals(3, eval('g'));
+
+// Test postfix count operation
+var t;
+t = g++;
+assertEquals(3, t);
+assertEquals(4, g);
+
+code = "g--; 1";
+assertEquals(1, eval(code));
+assertEquals(3, g);
diff --git a/test/mjsunit/compiler/jsnatives.js b/test/mjsunit/compiler/jsnatives.js
new file mode 100644
index 0000000..f5d6ac4
--- /dev/null
+++ b/test/mjsunit/compiler/jsnatives.js
@@ -0,0 +1,33 @@
+// 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: --allow-natives-syntax
+
+// Test call of JS runtime functions.
+
+var a = %GlobalParseInt("21", 16);
+assertEquals(33, a);
diff --git a/test/mjsunit/compiler/literals-assignment.js b/test/mjsunit/compiler/literals-assignment.js
index 932bfa7..d2996c7 100644
--- a/test/mjsunit/compiler/literals-assignment.js
+++ b/test/mjsunit/compiler/literals-assignment.js
@@ -69,3 +69,36 @@
})()";
assertEquals(8, eval(code));
+// Test object literals.
+var a, b;
+code = "a = {x:8}";
+eval(code);
+assertEquals(8, a.x);
+
+code = "b = {x:a, y:'abc'}";
+eval(code);
+assertEquals(a, b.x);
+assertEquals(8, b.x.x);
+assertEquals("abc", b.y);
+
+code = "({x:8, y:9}); 10";
+assertEquals(10, eval(code));
+
+code = "({x:8, y:9})";
+eval(code);
+assertEquals(9, eval(code+".y"));
+
+code = "a = {2:8, x:9}";
+eval(code);
+assertEquals(8, a[2]);
+assertEquals(8, a["2"]);
+assertEquals(9, a["x"]);
+
+// Test regexp literals.
+
+a = /abc/;
+
+assertEquals(/abc/, a);
+
+code = "/abc/; 8";
+assertEquals(8, eval(code));
diff --git a/test/mjsunit/compiler/loops.js b/test/mjsunit/compiler/loops.js
new file mode 100644
index 0000000..4de45e7
--- /dev/null
+++ b/test/mjsunit/compiler/loops.js
@@ -0,0 +1,35 @@
+// 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.
+
+// Test compilation of loops.
+
+var n = 1;
+for (var i = 1; (6 - i); i++) {
+ // Factorial!
+ n = n * i;
+}
+assertEquals(120, n);
diff --git a/test/mjsunit/compiler/objectliterals.js b/test/mjsunit/compiler/objectliterals.js
new file mode 100644
index 0000000..788acb4
--- /dev/null
+++ b/test/mjsunit/compiler/objectliterals.js
@@ -0,0 +1,57 @@
+// 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.
+
+// Test object literals with getter, setter and prototype properties.
+
+var o = { x: 41, get bar() { return {x:42} } };
+
+assertEquals(41, o.x);
+assertEquals(42, o.bar.x);
+
+o = { f: function() { return 41 },
+ get bar() { return this.x },
+ x:0,
+ set bar(t) { this.x = t },
+ g: function() { return 43 }
+};
+o.bar = 7;
+assertEquals(7, o.bar);
+assertEquals(7, o.x);
+assertEquals(41, o.f());
+assertEquals(43, o.g());
+
+p = {x:42};
+o = {get foo() { return this.x; },
+ f: function() { return this.foo + 1 },
+ set bar(t) { this.x = t; },
+ __proto__: p,
+};
+assertEquals(42, o.x);
+assertEquals(42, o.foo);
+assertEquals(43, o.f());
+o.bar = 44;
+assertEquals(44, o.foo);
diff --git a/test/mjsunit/compiler/property-simple.js b/test/mjsunit/compiler/property-simple.js
new file mode 100644
index 0000000..b0f0ffa
--- /dev/null
+++ b/test/mjsunit/compiler/property-simple.js
@@ -0,0 +1,39 @@
+// 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.
+
+// Test for property access
+
+var a;
+var b;
+
+code = "a = {x:8, y:9}; a.x";
+
+assertEquals(8, eval(code));
+
+code = "b = {z:a}; b.z.y";
+
+assertEquals(9, eval(code));
diff --git a/test/mjsunit/compiler/thisfunction.js b/test/mjsunit/compiler/thisfunction.js
new file mode 100644
index 0000000..2af846f
--- /dev/null
+++ b/test/mjsunit/compiler/thisfunction.js
@@ -0,0 +1,35 @@
+// 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: --always_fast_compiler
+
+// Test reference to this-function.
+
+var g = (function f(x) {
+ if (x == 1) return 42; else return f(1);
+ })(0);
+assertEquals(42, g);
diff --git a/test/mjsunit/cyrillic.js b/test/mjsunit/cyrillic.js
new file mode 100644
index 0000000..c5712e6
--- /dev/null
+++ b/test/mjsunit/cyrillic.js
@@ -0,0 +1,199 @@
+// 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.
+
+// Test Unicode character ranges in regexps.
+
+
+// Cyrillic.
+var cyrillic = {
+ FIRST: "\u0410", // A
+ first: "\u0430", // a
+ LAST: "\u042f", // YA
+ last: "\u044f", // ya
+ MIDDLE: "\u0427", // CHE
+ middle: "\u0447", // che
+ // Actually no characters are between the cases in Cyrillic.
+ BetweenCases: false};
+
+var SIGMA = "\u03a3";
+var sigma = "\u03c3";
+var alternative_sigma = "\u03c2";
+
+// Greek.
+var greek = {
+ FIRST: "\u0391", // ALPHA
+ first: "\u03b1", // alpha
+ LAST: "\u03a9", // OMEGA
+ last: "\u03c9", // omega
+ MIDDLE: SIGMA, // SIGMA
+ middle: sigma, // sigma
+ // Epsilon acute is between ALPHA-OMEGA and alpha-omega, ie it
+ // is between OMEGA and alpha.
+ BetweenCases: "\u03ad"};
+
+
+function Range(from, to, flags) {
+ return new RegExp("[" + from + "-" + to + "]", flags);
+}
+
+// Test Cyrillic and Greek separately.
+for (var lang = 0; lang < 2; lang++) {
+ var chars = (lang == 0) ? cyrillic : greek;
+
+ for (var i = 0; i < 2; i++) {
+ var lc = (i == 0); // Lower case.
+ var first = lc ? chars.first : chars.FIRST;
+ var middle = lc ? chars.middle : chars.MIDDLE;
+ var last = lc ? chars.last : chars.LAST;
+ var first_other_case = lc ? chars.FIRST : chars.first;
+ var middle_other_case = lc ? chars.MIDDLE : chars.middle;
+ var last_other_case = lc ? chars.LAST : chars.last;
+
+ assertTrue(Range(first, last).test(first), 1);
+ assertTrue(Range(first, last).test(middle), 2);
+ assertTrue(Range(first, last).test(last), 3);
+
+ assertFalse(Range(first, last).test(first_other_case), 4);
+ assertFalse(Range(first, last).test(middle_other_case), 5);
+ assertFalse(Range(first, last).test(last_other_case), 6);
+
+ assertTrue(Range(first, last, "i").test(first), 7);
+ assertTrue(Range(first, last, "i").test(middle), 8);
+ assertTrue(Range(first, last, "i").test(last), 9);
+
+ assertTrue(Range(first, last, "i").test(first_other_case), 10);
+ assertTrue(Range(first, last, "i").test(middle_other_case), 11);
+ assertTrue(Range(first, last, "i").test(last_other_case), 12);
+
+ if (chars.BetweenCases) {
+ assertFalse(Range(first, last).test(chars.BetweenCases), 13);
+ assertFalse(Range(first, last, "i").test(chars.BetweenCases), 14);
+ }
+ }
+ if (chars.BetweenCases) {
+ assertTrue(Range(chars.FIRST, chars.last).test(chars.BetweenCases), 15);
+ assertTrue(Range(chars.FIRST, chars.last, "i").test(chars.BetweenCases), 16);
+ }
+}
+
+// Test range that covers both greek and cyrillic characters.
+for (key in greek) {
+ assertTrue(Range(greek.FIRST, cyrillic.last).test(greek[key]), 17 + key);
+ if (cyrillic[key]) {
+ assertTrue(Range(greek.FIRST, cyrillic.last).test(cyrillic[key]), 18 + key);
+ }
+}
+
+for (var i = 0; i < 2; i++) {
+ var ignore_case = (i == 0);
+ var flag = ignore_case ? "i" : "";
+ assertTrue(Range(greek.first, cyrillic.LAST, flag).test(greek.first), 19);
+ assertTrue(Range(greek.first, cyrillic.LAST, flag).test(greek.middle), 20);
+ assertTrue(Range(greek.first, cyrillic.LAST, flag).test(greek.last), 21);
+
+ assertTrue(Range(greek.first, cyrillic.LAST, flag).test(cyrillic.FIRST), 22);
+ assertTrue(Range(greek.first, cyrillic.LAST, flag).test(cyrillic.MIDDLE), 23);
+ assertTrue(Range(greek.first, cyrillic.LAST, flag).test(cyrillic.LAST), 24);
+
+ // A range that covers the lower case greek letters and the upper case cyrillic
+ // letters.
+ assertEquals(ignore_case, Range(greek.first, cyrillic.LAST, flag).test(greek.FIRST), 25);
+ assertEquals(ignore_case, Range(greek.first, cyrillic.LAST, flag).test(greek.MIDDLE), 26);
+ assertEquals(ignore_case, Range(greek.first, cyrillic.LAST, flag).test(greek.LAST), 27);
+
+ assertEquals(ignore_case, Range(greek.first, cyrillic.LAST, flag).test(cyrillic.first), 28);
+ assertEquals(ignore_case, Range(greek.first, cyrillic.LAST, flag).test(cyrillic.middle), 29);
+ assertEquals(ignore_case, Range(greek.first, cyrillic.LAST, flag).test(cyrillic.last), 30);
+}
+
+
+// Sigma is special because there are two lower case versions of the same upper
+// case character. JS requires that case independece means that you should
+// convert everything to upper case, so the two sigma variants are equal to each
+// other in a case independt comparison.
+for (var i = 0; i < 2; i++) {
+ var simple = (i != 0);
+ var name = simple ? "" : "[]";
+ var regex = simple ? SIGMA : "[" + SIGMA + "]";
+
+ assertFalse(new RegExp(regex).test(sigma), 31 + name);
+ assertFalse(new RegExp(regex).test(alternative_sigma), 32 + name);
+ assertTrue(new RegExp(regex).test(SIGMA), 33 + name);
+
+ assertTrue(new RegExp(regex, "i").test(sigma), 34 + name);
+ // JSC and Tracemonkey fail this one.
+ assertTrue(new RegExp(regex, "i").test(alternative_sigma), 35 + name);
+ assertTrue(new RegExp(regex, "i").test(SIGMA), 36 + name);
+
+ regex = simple ? sigma : "[" + sigma + "]";
+
+ assertTrue(new RegExp(regex).test(sigma), 41 + name);
+ assertFalse(new RegExp(regex).test(alternative_sigma), 42 + name);
+ assertFalse(new RegExp(regex).test(SIGMA), 43 + name);
+
+ assertTrue(new RegExp(regex, "i").test(sigma), 44 + name);
+ // JSC and Tracemonkey fail this one.
+ assertTrue(new RegExp(regex, "i").test(alternative_sigma), 45 + name);
+ assertTrue(new RegExp(regex, "i").test(SIGMA), 46 + name);
+
+ regex = simple ? alternative_sigma : "[" + alternative_sigma + "]";
+
+ assertFalse(new RegExp(regex).test(sigma), 51 + name);
+ assertTrue(new RegExp(regex).test(alternative_sigma), 52 + name);
+ assertFalse(new RegExp(regex).test(SIGMA), 53 + name);
+
+ // JSC and Tracemonkey fail this one.
+ assertTrue(new RegExp(regex, "i").test(sigma), 54 + name);
+ assertTrue(new RegExp(regex, "i").test(alternative_sigma), 55 + name);
+ // JSC and Tracemonkey fail this one.
+ assertTrue(new RegExp(regex, "i").test(SIGMA), 56 + name);
+}
+
+
+for (var add_non_ascii_character_to_subject = 0;
+ add_non_ascii_character_to_subject < 2;
+ add_non_ascii_character_to_subject++) {
+ var suffix = add_non_ascii_character_to_subject ? "\ufffe" : "";
+ // A range that covers both ASCII and non-ASCII.
+ for (var i = 0; i < 2; i++) {
+ var full = (i != 0);
+ var mixed = full ? "[a-\uffff]" : "[a-" + cyrillic.LAST + "]";
+ var f = full ? "f" : "c";
+ for (var j = 0; j < 2; j++) {
+ var ignore_case = (j == 0);
+ var flag = ignore_case ? "i" : "";
+ var re = new RegExp(mixed, flag);
+ assertEquals(ignore_case || (full && add_non_ascii_character_to_subject),
+ re.test("A" + suffix),
+ 58 + flag + f);
+ assertTrue(re.test("a" + suffix), 59 + flag + f);
+ assertTrue(re.test("~" + suffix), 60 + flag + f);
+ assertTrue(re.test(cyrillic.MIDDLE), 61 + flag + f);
+ assertEquals(ignore_case || full, re.test(cyrillic.middle), 62 + flag + f);
+ }
+ }
+}
diff --git a/test/mjsunit/debug-stepnext-do-while.js b/test/mjsunit/debug-stepnext-do-while.js
new file mode 100644
index 0000000..17058a7
--- /dev/null
+++ b/test/mjsunit/debug-stepnext-do-while.js
@@ -0,0 +1,79 @@
+// 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: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+var exception = null;
+var break_break_point_hit_count = 0;
+
+function listener(event, exec_state, event_data, data) {
+ try {
+ if (event == Debug.DebugEvent.Break) {
+ if (break_break_point_hit_count == 0) {
+ assertEquals(' debugger;',
+ event_data.sourceLineText());
+ assertEquals('runDoWhile', event_data.func().name());
+ } else if (break_break_point_hit_count == 1) {
+ assertEquals(' } while(condition());',
+ event_data.sourceLineText());
+ assertEquals('runDoWhile', event_data.func().name());
+ }
+
+ break_break_point_hit_count++;
+ // Continue stepping until returned to bottom frame.
+ if (exec_state.frameCount() > 1) {
+ exec_state.prepareStep(Debug.StepAction.StepNext);
+ }
+
+ }
+ } catch(e) {
+ exception = e;
+ }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function condition() {
+ return false;
+}
+
+function runDoWhile() {
+ do {
+ debugger;
+ } while(condition());
+};
+
+break_break_point_hit_count = 0;
+runDoWhile();
+assertNull(exception);
+assertEquals(4, break_break_point_hit_count);
+
+// Get rid of the debug event listener.
+Debug.setListener(null);
diff --git a/test/mjsunit/deep-recursion.js b/test/mjsunit/deep-recursion.js
index a8093eb..588b5d6 100644
--- a/test/mjsunit/deep-recursion.js
+++ b/test/mjsunit/deep-recursion.js
@@ -30,9 +30,7 @@
* cause stack overflows.
*/
-var depth = 110000;
-
-function newdeep(start) {
+function newdeep(start, depth) {
var d = start;
for (var i = 0; i < depth; i++) {
d = d + "f";
@@ -40,23 +38,27 @@
return d;
}
-var deep = newdeep("foo");
+var default_depth = 110000;
+
+var deep = newdeep("foo", default_depth);
assertEquals('f', deep[0]);
-var cmp1 = newdeep("a");
-var cmp2 = newdeep("b");
+var cmp1 = newdeep("a", default_depth);
+var cmp2 = newdeep("b", default_depth);
assertEquals(-1, cmp1.localeCompare(cmp2), "ab");
-var cmp2empty = newdeep("c");
+var cmp2empty = newdeep("c", default_depth);
assertTrue(cmp2empty.localeCompare("") > 0, "c");
-var cmp3empty = newdeep("d");
+var cmp3empty = newdeep("d", default_depth);
assertTrue("".localeCompare(cmp3empty) < 0), "d";
-var slicer = newdeep("slice");
+var slicer_depth = 1100;
-for (i = 0; i < depth + 4; i += 2) {
+var slicer = newdeep("slice", slicer_depth);
+
+for (i = 0; i < slicer_depth + 4; i += 2) {
slicer = slicer.slice(1, -1);
}
diff --git a/test/mjsunit/eval-typeof-non-existing.js b/test/mjsunit/eval-typeof-non-existing.js
index 3513767..8cc6d0b 100644
--- a/test/mjsunit/eval-typeof-non-existing.js
+++ b/test/mjsunit/eval-typeof-non-existing.js
@@ -25,8 +25,11 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Typeof expression must resolve to undefined when it used on a
+// Typeof expression must resolve to 'undefined' when it used on a
// non-existing property. It is *not* allowed to throw a
// ReferenceError.
assertEquals('undefined', typeof xxx);
assertEquals('undefined', eval('typeof xxx'));
+
+assertThrows('typeof(true ? xxx : yyy)', ReferenceError);
+assertThrows('with ({}) { typeof(true ? xxx : yyy) }', ReferenceError);
diff --git a/test/mjsunit/fuzz-natives.js b/test/mjsunit/fuzz-natives.js
index cdf58a5..f495c72 100644
--- a/test/mjsunit/fuzz-natives.js
+++ b/test/mjsunit/fuzz-natives.js
@@ -129,7 +129,9 @@
"Log": true,
"DeclareGlobals": true,
- "CollectStackTrace": true
+ "CollectStackTrace": true,
+ "PromoteScheduledException": true,
+ "DeleteHandleScopeExtensions": true
};
var currentlyUncallable = {
diff --git a/test/mjsunit/math-min-max.js b/test/mjsunit/math-min-max.js
index 0ed9912..1a98d44 100644
--- a/test/mjsunit/math-min-max.js
+++ b/test/mjsunit/math-min-max.js
@@ -34,11 +34,15 @@
assertEquals(1, Math.min(1, 2, 3));
assertEquals(1, Math.min(3, 2, 1));
assertEquals(1, Math.min(2, 3, 1));
+assertEquals(1.1, Math.min(1.1, 2.2, 3.3));
+assertEquals(1.1, Math.min(3.3, 2.2, 1.1));
+assertEquals(1.1, Math.min(2.2, 3.3, 1.1));
var o = {};
o.valueOf = function() { return 1; };
assertEquals(1, Math.min(2, 3, '1'));
assertEquals(1, Math.min(3, o, 2));
+assertEquals(1, Math.min(o, 2));
assertEquals(Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY / Math.min(-0, +0));
assertEquals(Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY / Math.min(+0, -0));
assertEquals(Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY / Math.min(+0, -0, 1));
@@ -46,7 +50,9 @@
assertEquals(-1, Math.min(-1, +0, -0));
assertEquals(-1, Math.min(+0, -1, -0));
assertEquals(-1, Math.min(-0, -1, +0));
-
+assertNaN(Math.min('oxen'));
+assertNaN(Math.min('oxen', 1));
+assertNaN(Math.min(1, 'oxen'));
// Test Math.max().
@@ -58,15 +64,22 @@
assertEquals(3, Math.max(1, 2, 3));
assertEquals(3, Math.max(3, 2, 1));
assertEquals(3, Math.max(2, 3, 1));
+assertEquals(3.3, Math.max(1.1, 2.2, 3.3));
+assertEquals(3.3, Math.max(3.3, 2.2, 1.1));
+assertEquals(3.3, Math.max(2.2, 3.3, 1.1));
var o = {};
o.valueOf = function() { return 3; };
assertEquals(3, Math.max(2, '3', 1));
assertEquals(3, Math.max(1, o, 2));
+assertEquals(3, Math.max(o, 1));
assertEquals(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY / Math.max(-0, +0));
assertEquals(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY / Math.max(+0, -0));
assertEquals(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY / Math.max(+0, -0, -1));
assertEquals(1, Math.max(+0, -0, +1));
assertEquals(1, Math.max(+1, +0, -0));
assertEquals(1, Math.max(+0, +1, -0));
-assertEquals(1, Math.max(-0, +1, +0));
\ No newline at end of file
+assertEquals(1, Math.max(-0, +1, +0));
+assertNaN(Math.max('oxen'));
+assertNaN(Math.max('oxen', 1));
+assertNaN(Math.max(1, 'oxen'));
diff --git a/test/mjsunit/mjsunit.js b/test/mjsunit/mjsunit.js
index 1fb3f02..8ced011 100644
--- a/test/mjsunit/mjsunit.js
+++ b/test/mjsunit/mjsunit.js
@@ -75,6 +75,9 @@
if (typeof a == "number" && typeof b == "number" && isNaN(a) && isNaN(b)) {
return true;
}
+ if (a.constructor === RegExp || b.constructor === RegExp) {
+ return (a.constructor === b.constructor) && (a.toString === b.toString);
+ }
if ((typeof a) !== 'object' || (typeof b) !== 'object' ||
(a === null) || (b === null))
return false;
diff --git a/test/mjsunit/mjsunit.status b/test/mjsunit/mjsunit.status
index 0b069cc..8eb59b7 100644
--- a/test/mjsunit/mjsunit.status
+++ b/test/mjsunit/mjsunit.status
@@ -34,8 +34,18 @@
# too long to run in debug mode on ARM.
fuzz-natives: PASS, SKIP if ($mode == release || $arch == arm)
+# Issue 494: new snapshot code breaks mjsunit/apply on mac debug snapshot.
+apply: PASS, FAIL if ($system == macos && $mode == debug)
+
big-object-literal: PASS, SKIP if ($arch == arm)
+# Issue 488: this test sometimes times out.
+array-constructor: PASS || TIMEOUT
+
+# Very slow on ARM, contains no architecture dependent code.
+unicode-case-overoptimization: PASS, TIMEOUT if ($arch == arm)
+
+
[ $arch == arm ]
# Slow tests which times out in debug mode.
@@ -46,9 +56,9 @@
# Flaky test that can hit compilation-time stack overflow in debug mode.
unicode-test: PASS, (PASS || FAIL) if $mode == debug
-# Bug number 130 http://code.google.com/p/v8/issues/detail?id=130
-# Fails on real ARM hardware but not on the simulator.
-string-compare-alignment: PASS || FAIL
-
# Times out often in release mode on ARM.
array-splice: PASS || TIMEOUT
+
+# Skip long running test in debug mode on ARM.
+string-indexof-2: PASS, SKIP if $mode == debug
+
diff --git a/test/mjsunit/parse-int-float.js b/test/mjsunit/parse-int-float.js
index ad2275e..b9620ff 100644
--- a/test/mjsunit/parse-int-float.js
+++ b/test/mjsunit/parse-int-float.js
@@ -36,9 +36,12 @@
assertEquals(3, parseInt('11', 2));
assertEquals(4, parseInt('11', 3));
+assertEquals(4, parseInt('11', 3.8));
assertEquals(0x12, parseInt('0x12'));
assertEquals(0x12, parseInt('0x12', 16));
+assertEquals(0x12, parseInt('0x12', 16.1));
+assertEquals(0x12, parseInt('0x12', NaN));
assertEquals(12, parseInt('12aaa'));
diff --git a/test/mjsunit/regress/regress-124.js b/test/mjsunit/regress/regress-124.js
index 81526b0..0b3aae5 100644
--- a/test/mjsunit/regress/regress-124.js
+++ b/test/mjsunit/regress/regress-124.js
@@ -48,9 +48,9 @@
assertEquals("[object global]", eval("f()"));
// Receiver should be the arguments object here.
- assertEquals("[object Object]", eval("arguments[0]()"));
+ assertEquals("[object Arguments]", eval("arguments[0]()"));
with (arguments) {
- assertEquals("[object Object]", toString());
+ assertEquals("[object Arguments]", toString());
}
}
diff --git a/test/mjsunit/regress/regress-2249423.js b/test/mjsunit/regress/regress-2249423.js
new file mode 100644
index 0000000..a590f33
--- /dev/null
+++ b/test/mjsunit/regress/regress-2249423.js
@@ -0,0 +1,40 @@
+// 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.
+
+// See http://code.google.com/p/chromium/issues/detail?id=27227
+// Regression test for stack corruption issue.
+
+function top() {
+ function g(a, b) {}
+ function t() {
+ for (var i=0; i<1; ++i) {
+ g(32768, g());
+ }
+ }
+ t();
+}
+top();
diff --git a/test/mjsunit/regress/regress-485.js b/test/mjsunit/regress/regress-485.js
new file mode 100755
index 0000000..62c6fb9
--- /dev/null
+++ b/test/mjsunit/regress/regress-485.js
@@ -0,0 +1,64 @@
+// 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.
+
+// See: http://code.google.com/p/v8/issues/detail?id=485
+
+// Ensure that we don't expose the builtins object when calling
+// builtin functions that use or return "this".
+
+var global = this;
+var global2 = (function(){return this;})();
+assertEquals(global, global2, "direct call to local function returns global");
+
+var builtin = Object.prototype.valueOf; // Builtin function that returns this.
+
+assertEquals(global, builtin(), "Direct call to builtin");
+
+assertEquals(global, builtin.call(), "call() to builtin");
+assertEquals(global, builtin.call(null), "call(null) to builtin");
+assertEquals(global, builtin.call(undefined), "call(undefined) to builtin");
+
+assertEquals(global, builtin.apply(), "apply() to builtin");
+assertEquals(global, builtin.apply(null), "apply(null) to builtin");
+assertEquals(global, builtin.apply(undefined), "apply(undefined) to builtin");
+
+assertEquals(global, builtin.call.call(builtin), "call.call() to builtin");
+assertEquals(global, builtin.call.apply(builtin), "call.apply() to builtin");
+assertEquals(global, builtin.apply.call(builtin), "apply.call() to builtin");
+assertEquals(global, builtin.apply.apply(builtin), "apply.apply() to builtin");
+
+
+// Builtin that depends on value of this to compute result.
+var builtin2 = Object.prototype.toString;
+
+// Global object has class "Object" according to Object.prototype.toString.
+// Builtins object displays as "[object builtins]".
+assertTrue("[object builtins]" != builtin2(), "Direct call to toString");
+assertTrue("[object builtins]" != builtin2.call(), "call() to toString");
+assertTrue("[object builtins]" != builtin2.apply(), "call() to toString");
+assertTrue("[object builtins]" != builtin2.call.call(builtin2),
+ "call.call() to toString");
diff --git a/test/mjsunit/regress/regress-486.js b/test/mjsunit/regress/regress-486.js
new file mode 100644
index 0000000..c1e29a6
--- /dev/null
+++ b/test/mjsunit/regress/regress-486.js
@@ -0,0 +1,30 @@
+// 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.
+
+var st = "\u0422\u0435\u0441\u0442"; // Test in Cyrillic characters.
+var cyrillicMatch = /^[\u0430-\u044fa-z]+$/i.test(st); // a-ja a-z.
+assertTrue(cyrillicMatch);
diff --git a/test/mjsunit/regress/regress-490.js b/test/mjsunit/regress/regress-490.js
new file mode 100644
index 0000000..8dd8959
--- /dev/null
+++ b/test/mjsunit/regress/regress-490.js
@@ -0,0 +1,48 @@
+// 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.
+
+// See: http://code.google.com/p/v8/issues/detail?id=490
+
+var kXXX = 11
+// Build a string longer than 2^11. See StringBuilderConcatHelper and
+// Runtime_StringBuilderConcat in runtime.cc and
+// ReplaceResultBuilder.prototype.addSpecialSlice in string.js.
+var a = '';
+while (a.length < (2 << 11)) { a+= 'x'; }
+
+// Test specific for bug introduced in r3153.
+a.replace(/^(.*)/, '$1$1$1');
+
+// More generalized test.
+for (var i = 0; i < 10; i++) {
+ var b = '';
+ for (var j = 0; j < 10; j++) {
+ b += '$1';
+ a.replace(/^(.*)/, b);
+ }
+ a += a;
+}
diff --git a/test/mjsunit/regress/regress-491.js b/test/mjsunit/regress/regress-491.js
new file mode 100644
index 0000000..2cf5e20
--- /dev/null
+++ b/test/mjsunit/regress/regress-491.js
@@ -0,0 +1,47 @@
+// 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.
+
+// See: http://code.google.com/p/v8/issues/detail?id=491
+// This should not hit any asserts in debug mode on ARM.
+
+function function_with_n_strings(n) {
+ var source = '(function f(){';
+ for (var i = 0; i < n; i++) {
+ if (i != 0) source += ';';
+ source += '"x"';
+ }
+ source += '})()';
+ eval(source);
+}
+
+var i;
+for (i = 500; i < 600; i++) {
+ function_with_n_strings(i);
+}
+for (i = 1100; i < 1200; i++) {
+ function_with_n_strings(i);
+}
diff --git a/test/mjsunit/regress/regress-492.js b/test/mjsunit/regress/regress-492.js
new file mode 100644
index 0000000..a8b783b
--- /dev/null
+++ b/test/mjsunit/regress/regress-492.js
@@ -0,0 +1,52 @@
+// 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.
+
+// See: http://code.google.com/p/v8/issues/detail?id=492
+// This should not hit any asserts in debug mode on ARM.
+
+function function_with_n_args(n) {
+ var source = '(function f(';
+ for (var arg = 0; arg < n; arg++) {
+ if (arg != 0) source += ',';
+ source += 'arg' + arg;
+ }
+ source += ') { })()';
+ eval(source);
+}
+
+var args;
+for (args = 250; args < 270; args++) {
+ function_with_n_args(args);
+}
+
+for (args = 500; args < 520; args++) {
+ function_with_n_args(args);
+}
+
+for (args = 1019; args < 1041; args++) {
+ function_with_n_args(args);
+}
diff --git a/test/mjsunit/regress/regress-496.js b/test/mjsunit/regress/regress-496.js
new file mode 100644
index 0000000..33c1a67
--- /dev/null
+++ b/test/mjsunit/regress/regress-496.js
@@ -0,0 +1,39 @@
+// 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.
+
+// Regression test for http://code.google.com/p/v8/issues/detail?id=496.
+//
+// Tests that we do not treat the unaliased eval call in g as an
+// aliased call to eval.
+
+function h() {
+ function f() { return eval; }
+ function g() { var x = 44; return eval("x"); }
+ assertEquals(44, g());
+}
+
+h();
diff --git a/test/mjsunit/regress/regress-502.js b/test/mjsunit/regress/regress-502.js
new file mode 100644
index 0000000..d3c9381
--- /dev/null
+++ b/test/mjsunit/regress/regress-502.js
@@ -0,0 +1,38 @@
+// 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.
+
+// Regression test for http://code.google.com/p/v8/issues/detail?id=502.
+//
+// Test that we do not generate an inlined version of the constructor
+// function C.
+
+var X = 'x';
+function C() { this[X] = 42; }
+var a = new C();
+var b = new C();
+assertEquals(42, a.x);
+assertEquals(42, b.x);
diff --git a/test/mjsunit/regress/regress-503.js b/test/mjsunit/regress/regress-503.js
new file mode 100644
index 0000000..5b156b2
--- /dev/null
+++ b/test/mjsunit/regress/regress-503.js
@@ -0,0 +1,63 @@
+// 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.
+
+assertTrue(undefined == undefined, 1);
+assertFalse(undefined <= undefined, 2);
+assertFalse(undefined >= undefined, 3);
+assertFalse(undefined < undefined, 4);
+assertFalse(undefined > undefined, 5);
+
+assertTrue(null == null, 6);
+assertTrue(null <= null, 7);
+assertTrue(null >= null, 8);
+assertFalse(null < null, 9);
+assertFalse(null > null, 10);
+
+assertTrue(void 0 == void 0, 11);
+assertFalse(void 0 <= void 0, 12);
+assertFalse(void 0 >= void 0, 13);
+assertFalse(void 0 < void 0, 14);
+assertFalse(void 0 > void 0, 15);
+
+var x = void 0;
+
+assertTrue(x == x, 16);
+assertFalse(x <= x, 17);
+assertFalse(x >= x, 18);
+assertFalse(x < x, 19);
+assertFalse(x > x, 20);
+
+var not_undefined = [null, 0, 1, 1/0, -1/0, "", true, false];
+for (var i = 0; i < not_undefined.length; i++) {
+ x = not_undefined[i];
+
+ assertTrue(x == x, "" + 21 + x);
+ assertTrue(x <= x, "" + 22 + x);
+ assertTrue(x >= x, "" + 23 + x);
+ assertFalse(x < x, "" + 24 + x);
+ assertFalse(x > x, "" + 25 + x);
+}
diff --git a/test/mjsunit/regress/regress-515.js b/test/mjsunit/regress/regress-515.js
new file mode 100644
index 0000000..7675fe1
--- /dev/null
+++ b/test/mjsunit/regress/regress-515.js
@@ -0,0 +1,40 @@
+// 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.
+
+// Regression test for http://code.google.com/p/v8/issues/detail?id=515.
+//
+// The test passes if it does not crash.
+
+var length = 2048;
+var s = "";
+for (var i = 0; i < 2048; i++) {
+ s += '.';
+}
+
+var string = s + 'x' + s + 'x' + s;
+
+string.replace(/x/g, "")
diff --git a/test/mjsunit/regress/regress-526.js b/test/mjsunit/regress/regress-526.js
new file mode 100644
index 0000000..0cae97a
--- /dev/null
+++ b/test/mjsunit/regress/regress-526.js
@@ -0,0 +1,32 @@
+// 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.
+
+// Test object literals with computed property and getter.
+
+var o = { foo: function() { }, get bar() { return {x:42} } };
+
+assertEquals(42, o.bar.x);
diff --git a/test/mjsunit/regress/regress-540.js b/test/mjsunit/regress/regress-540.js
new file mode 100644
index 0000000..c40fa2c
--- /dev/null
+++ b/test/mjsunit/regress/regress-540.js
@@ -0,0 +1,47 @@
+// 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.
+
+// Test context slot declarations in the arguments object.
+// See http://code.google.com/p/v8/issues/detail?id=540
+
+function f(x, y) { eval(x); return y(); }
+var result = f("function y() { return 1; }", function () { return 0; })
+assertEquals(1, result);
+
+result =
+ (function (x) {
+ function x() { return 3; }
+ return x();
+ })(function () { return 2; });
+assertEquals(3, result);
+
+result =
+ (function (x) {
+ function x() { return 5; }
+ return arguments[0]();
+ })(function () { return 4; });
+assertEquals(5, result);
diff --git a/test/mjsunit/regress/regress-r3391.js b/test/mjsunit/regress/regress-r3391.js
new file mode 100644
index 0000000..d557284
--- /dev/null
+++ b/test/mjsunit/regress/regress-r3391.js
@@ -0,0 +1,77 @@
+// 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.
+
+// Check what we do if toLocaleString doesn't return a string when we are
+// calling Array.prototype.toLocaleString. The standard is somewhat
+// vague on this point. This test is now passed by both V8 and JSC.
+
+var evil_called = 0;
+var evil_locale_called = 0;
+var exception_thrown = 0;
+
+function evil_to_string() {
+ evil_called++;
+ return this;
+}
+
+function evil_to_locale_string() {
+ evil_locale_called++;
+ return this;
+}
+
+var o = {toString: evil_to_string, toLocaleString: evil_to_locale_string};
+
+try {
+ [o].toLocaleString();
+} catch(e) {
+ exception_thrown++;
+}
+
+assertEquals(1, evil_called, "evil1");
+assertEquals(1, evil_locale_called, "local1");
+assertEquals(1, exception_thrown, "exception1");
+
+try {
+ [o].toString();
+} catch(e) {
+ exception_thrown++;
+}
+
+assertEquals(2, evil_called, "evil2");
+assertEquals(1, evil_locale_called, "local2");
+assertEquals(2, exception_thrown, "exception2");
+
+try {
+ [o].join(o);
+} catch(e) {
+ exception_thrown++;
+}
+
+assertEquals(3, evil_called, "evil3");
+assertEquals(1, evil_locale_called, "local3");
+assertEquals(3, exception_thrown, "exception3");
+print("ok");
diff --git a/test/mjsunit/string-add.js b/test/mjsunit/string-add.js
index c42cf79..f226ca1 100644
--- a/test/mjsunit/string-add.js
+++ b/test/mjsunit/string-add.js
@@ -173,3 +173,23 @@
assertEquals("42strz", reswz, "swwz");
assertEquals(84, resww, "swww");
})(1);
+
+// Generate ascii and non ascii strings from length 0 to 20.
+var ascii = 'aaaaaaaaaaaaaaaaaaaa';
+var non_ascii = '\u1234\u1234\u1234\u1234\u1234\u1234\u1234\u1234\u1234\u1234\u1234\u1234\u1234\u1234\u1234\u1234\u1234\u1234\u1234\u1234';
+assertEquals(20, ascii.length);
+assertEquals(20, non_ascii.length);
+var a = Array(21);
+var b = Array(21);
+for (var i = 0; i <= 20; i++) {
+ a[i] = ascii.substring(0, i);
+ b[i] = non_ascii.substring(0, i);
+}
+
+// Add ascii and non-ascii strings generating strings with length from 0 to 20.
+for (var i = 0; i <= 20; i++) {
+ for (var j = 0; j < i; j++) {
+ assertEquals(a[i], a[j] + a[i - j])
+ assertEquals(b[i], b[j] + b[i - j])
+ }
+}
diff --git a/test/mjsunit/string-charcodeat.js b/test/mjsunit/string-charcodeat.js
index f66dd3e..3927557 100644
--- a/test/mjsunit/string-charcodeat.js
+++ b/test/mjsunit/string-charcodeat.js
@@ -30,7 +30,7 @@
*/
function Cons() {
- return "Te" + "st";
+ return "Te" + "st testing 123";
}
@@ -38,22 +38,22 @@
var a = "T";
a += "e";
a += "s";
- a += "t";
+ a += "ting testing 123";
return a;
}
function Slice() {
- return "testing Testing".substring(8, 12);
+ return "testing Testing testing 123456789012345".substring(8, 22);
}
function Flat() {
- return "Test";
+ return "Testing testing 123";
}
function Cons16() {
- return "Te" + "\u1234t";
+ return "Te" + "\u1234t testing 123";
}
@@ -61,18 +61,18 @@
var a = "T";
a += "e";
a += "\u1234";
- a += "t";
+ a += "ting testing 123";
return a;
}
function Slice16Beginning() {
- return "Te\u1234t test".substring(0, 4);
+ return "Te\u1234t testing testing 123".substring(0, 14);
}
function Slice16Middle() {
- return "test Te\u1234t test".substring(5, 9);
+ return "test Te\u1234t testing testing 123".substring(5, 19);
}
@@ -82,7 +82,7 @@
function Flat16() {
- return "Te\u1234t";
+ return "Te\u1234ting testing 123";
}
@@ -108,32 +108,35 @@
function TestStringType(generator, sixteen) {
var g = generator;
- assertTrue(isNaN(g().charCodeAt(-1e19)));
- assertTrue(isNaN(g().charCodeAt(-0x80000001)));
- assertTrue(isNaN(g().charCodeAt(-0x80000000)));
- assertTrue(isNaN(g().charCodeAt(-0x40000000)));
- assertTrue(isNaN(g().charCodeAt(-1)));
- assertTrue(isNaN(g().charCodeAt(4)));
- assertTrue(isNaN(g().charCodeAt(5)));
- assertTrue(isNaN(g().charCodeAt(0x3fffffff)));
- assertTrue(isNaN(g().charCodeAt(0x7fffffff)));
- assertTrue(isNaN(g().charCodeAt(0x80000000)));
- assertTrue(isNaN(g().charCodeAt(1e9)));
- assertEquals(84, g().charCodeAt(0));
- assertEquals(84, g().charCodeAt("test"));
- assertEquals(84, g().charCodeAt(""));
- assertEquals(84, g().charCodeAt(null));
- assertEquals(84, g().charCodeAt(undefined));
- assertEquals(84, g().charCodeAt());
- assertEquals(84, g().charCodeAt(void 0));
- assertEquals(84, g().charCodeAt(false));
- assertEquals(101, g().charCodeAt(true));
- assertEquals(101, g().charCodeAt(1));
- assertEquals(sixteen ? 0x1234 : 115, g().charCodeAt(2));
- assertEquals(116, g().charCodeAt(3));
- assertEquals(101, g().charCodeAt(1.1));
- assertEquals(sixteen ? 0x1234 : 115, g().charCodeAt(2.1718));
- assertEquals(116, g().charCodeAt(3.14159));
+ var len = g().toString().length;
+ var t = sixteen ? "t" : "f"
+ t += generator.name;
+ assertTrue(isNaN(g().charCodeAt(-1e19)), 1 + t);
+ assertTrue(isNaN(g().charCodeAt(-0x80000001)), 2 + t);
+ assertTrue(isNaN(g().charCodeAt(-0x80000000)), 3 + t);
+ assertTrue(isNaN(g().charCodeAt(-0x40000000)), 4 + t);
+ assertTrue(isNaN(g().charCodeAt(-1)), 5 + t);
+ assertTrue(isNaN(g().charCodeAt(len)), 6 + t);
+ assertTrue(isNaN(g().charCodeAt(len + 1)), 7 + t);
+ assertTrue(isNaN(g().charCodeAt(0x3fffffff)), 8 + t);
+ assertTrue(isNaN(g().charCodeAt(0x7fffffff)), 9 + t);
+ assertTrue(isNaN(g().charCodeAt(0x80000000)), 10 + t);
+ assertTrue(isNaN(g().charCodeAt(1e9)), 11 + t);
+ assertEquals(84, g().charCodeAt(0), 12 + t);
+ assertEquals(84, g().charCodeAt("test"), 13 + t);
+ assertEquals(84, g().charCodeAt(""), 14 + t);
+ assertEquals(84, g().charCodeAt(null), 15 + t);
+ assertEquals(84, g().charCodeAt(undefined), 16 + t);
+ assertEquals(84, g().charCodeAt(), 17 + t);
+ assertEquals(84, g().charCodeAt(void 0), 18 + t);
+ assertEquals(84, g().charCodeAt(false), 19 + t);
+ assertEquals(101, g().charCodeAt(true), 20 + t);
+ assertEquals(101, g().charCodeAt(1), 21 + t);
+ assertEquals(sixteen ? 0x1234 : 115, g().charCodeAt(2), 22 + t);
+ assertEquals(116, g().charCodeAt(3), 23 + t);
+ assertEquals(101, g().charCodeAt(1.1), 24 + t);
+ assertEquals(sixteen ? 0x1234 : 115, g().charCodeAt(2.1718), 25 + t);
+ assertEquals(116, g().charCodeAt(3.14159), 26 + t);
}
@@ -157,10 +160,10 @@
this.charCodeAt = String.prototype.charCodeAt;
}
-assertEquals(52, new StupidThing().charCodeAt(0));
-assertEquals(50, new StupidThing().charCodeAt(1));
-assertTrue(isNaN(new StupidThing().charCodeAt(2)));
-assertTrue(isNaN(new StupidThing().charCodeAt(-1)));
+assertEquals(52, new StupidThing().charCodeAt(0), 27);
+assertEquals(50, new StupidThing().charCodeAt(1), 28);
+assertTrue(isNaN(new StupidThing().charCodeAt(2)), 29);
+assertTrue(isNaN(new StupidThing().charCodeAt(-1)), 30);
// Medium (>255) and long (>65535) strings.
@@ -178,12 +181,12 @@
long += long + long + long; // 16384.
long += long + long + long; // 65536.
-assertTrue(isNaN(medium.charCodeAt(-1)));
-assertEquals(49, medium.charCodeAt(0));
-assertEquals(56, medium.charCodeAt(255));
-assertTrue(isNaN(medium.charCodeAt(256)));
+assertTrue(isNaN(medium.charCodeAt(-1)), 31);
+assertEquals(49, medium.charCodeAt(0), 32);
+assertEquals(56, medium.charCodeAt(255), 33);
+assertTrue(isNaN(medium.charCodeAt(256)), 34);
-assertTrue(isNaN(long.charCodeAt(-1)));
-assertEquals(49, long.charCodeAt(0));
-assertEquals(56, long.charCodeAt(65535));
-assertTrue(isNaN(long.charCodeAt(65536)));
+assertTrue(isNaN(long.charCodeAt(-1)), 35);
+assertEquals(49, long.charCodeAt(0), 36);
+assertEquals(56, long.charCodeAt(65535), 37);
+assertTrue(isNaN(long.charCodeAt(65536)), 38);
diff --git a/test/mjsunit/string-indexof.js b/test/mjsunit/string-indexof-1.js
similarity index 63%
rename from test/mjsunit/string-indexof.js
rename to test/mjsunit/string-indexof-1.js
index 2018da7..c7dcdb8 100644
--- a/test/mjsunit/string-indexof.js
+++ b/test/mjsunit/string-indexof-1.js
@@ -97,46 +97,3 @@
pattern = "JABACABADABACABA";
assertEquals(511, long.indexOf(pattern), "Long JABACABA..., First J");
assertEquals(1535, long.indexOf(pattern, 512), "Long JABACABA..., Second J");
-
-
-var lipsum = "lorem ipsum per se esse fugiendum. itaque aiunt hanc quasi "
- + "naturalem atque insitam in animis nostris inesse notionem, ut "
- + "alterum esse appetendum, alterum aspernandum sentiamus. Alii autem,"
- + " quibus ego assentior, cum a philosophis compluribus permulta "
- + "dicantur, cur nec voluptas in bonis sit numeranda nec in malis "
- + "dolor, non existimant oportere nimium nos causae confidere, sed et"
- + " argumentandum et accurate disserendum et rationibus conquisitis de"
- + " voluptate et dolore disputandum putant.\n"
- + "Sed ut perspiciatis, unde omnis iste natus error sit voluptatem "
- + "accusantium doloremque laudantium, totam rem aperiam eaque ipsa,"
- + "quae ab illo inventore veritatis et quasi architecto beatae vitae "
- + "dicta sunt, explicabo. nemo enim ipsam voluptatem, quia voluptas"
- + "sit, aspernatur aut odit aut fugit, sed quia consequuntur magni"
- + " dolores eos, qui ratione voluptatem sequi nesciunt, neque porro"
- + " quisquam est, qui dolorem ipsum, quia dolor sit, amet, "
- + "consectetur, adipisci velit, sed quia non numquam eius modi"
- + " tempora incidunt, ut labore et dolore magnam aliquam quaerat "
- + "voluptatem. ut enim ad minima veniam, quis nostrum exercitationem "
- + "ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi "
- + "consequatur? quis autem vel eum iure reprehenderit, qui in ea "
- + "voluptate velit esse, quam nihil molestiae consequatur, vel illum, "
- + "qui dolorem eum fugiat, quo voluptas nulla pariatur?\n";
-
-assertEquals(893, lipsum.indexOf("lorem ipsum, quia dolor sit, amet"),
- "Lipsum");
-// test a lot of substrings of differing length and start-position.
-for(var i = 0; i < lipsum.length; i += 3) {
- for(var len = 1; i + len < lipsum.length; len += 7) {
- var substring = lipsum.substring(i, i + len);
- var index = -1;
- do {
- index = lipsum.indexOf(substring, index + 1);
- assertTrue(index != -1,
- "Lipsum substring " + i + ".." + (i + len-1) + " not found");
- assertEquals(lipsum.substring(index, index + len), substring,
- "Wrong lipsum substring found: " + i + ".." + (i + len - 1) + "/" +
- index + ".." + (index + len - 1));
- } while (index >= 0 && index < i);
- assertEquals(i, index, "Lipsum match at " + i + ".." + (i + len - 1));
- }
-}
diff --git a/test/mjsunit/string-indexof.js b/test/mjsunit/string-indexof-2.js
similarity index 60%
copy from test/mjsunit/string-indexof.js
copy to test/mjsunit/string-indexof-2.js
index 2018da7..a7c3f60 100644
--- a/test/mjsunit/string-indexof.js
+++ b/test/mjsunit/string-indexof-2.js
@@ -25,80 +25,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-var s = "test test test";
-
-assertEquals(0, s.indexOf("t"));
-assertEquals(3, s.indexOf("t", 1));
-assertEquals(5, s.indexOf("t", 4));
-assertEquals(1, s.indexOf("e"));
-assertEquals(2, s.indexOf("s"));
-
-assertEquals(5, s.indexOf("test", 4));
-assertEquals(5, s.indexOf("test", 5));
-assertEquals(10, s.indexOf("test", 6));
-assertEquals(0, s.indexOf("test", 0));
-assertEquals(0, s.indexOf("test", -1));
-assertEquals(0, s.indexOf("test"));
-assertEquals(-1, s.indexOf("notpresent"));
-assertEquals(-1, s.indexOf());
-
-for (var i = 0; i < s.length+10; i++) {
- var expected = i < s.length ? i : s.length;
- assertEquals(expected, s.indexOf("", i));
-}
-
-var reString = "asdf[a-z]+(asdf)?";
-
-assertEquals(4, reString.indexOf("[a-z]+"));
-assertEquals(10, reString.indexOf("(asdf)?"));
-
-assertEquals(1, String.prototype.indexOf.length);
-
-// Random greek letters
-var twoByteString = "\u039a\u0391\u03a3\u03a3\u0395";
-
-// Test single char pattern
-assertEquals(0, twoByteString.indexOf("\u039a"), "Lamda");
-assertEquals(1, twoByteString.indexOf("\u0391"), "Alpha");
-assertEquals(2, twoByteString.indexOf("\u03a3"), "First Sigma");
-assertEquals(3, twoByteString.indexOf("\u03a3",3), "Second Sigma");
-assertEquals(4, twoByteString.indexOf("\u0395"), "Epsilon");
-assertEquals(-1, twoByteString.indexOf("\u0392"), "Not beta");
-
-// Test multi-char pattern
-assertEquals(0, twoByteString.indexOf("\u039a\u0391"), "lambda Alpha");
-assertEquals(1, twoByteString.indexOf("\u0391\u03a3"), "Alpha Sigma");
-assertEquals(2, twoByteString.indexOf("\u03a3\u03a3"), "Sigma Sigma");
-assertEquals(3, twoByteString.indexOf("\u03a3\u0395"), "Sigma Epsilon");
-
-assertEquals(-1, twoByteString.indexOf("\u0391\u03a3\u0395"),
- "Not Alpha Sigma Epsilon");
-
-//single char pattern
-assertEquals(4, twoByteString.indexOf("\u0395"));
-
-// Test complex string indexOf algorithms. Only trigger for long strings.
-
-// Long string that isn't a simple repeat of a shorter string.
-var long = "A";
-for(var i = 66; i < 76; i++) { // from 'B' to 'K'
- long = long + String.fromCharCode(i) + long;
-}
-
-// pattern of 15 chars, repeated every 16 chars in long
-var pattern = "ABACABADABACABA";
-for(var i = 0; i < long.length - pattern.length; i+= 7) {
- var index = long.indexOf(pattern, i);
- assertEquals((i + 15) & ~0xf, index, "Long ABACABA...-string at index " + i);
-}
-assertEquals(510, long.indexOf("AJABACA"), "Long AJABACA, First J");
-assertEquals(1534, long.indexOf("AJABACA", 511), "Long AJABACA, Second J");
-
-pattern = "JABACABADABACABA";
-assertEquals(511, long.indexOf(pattern), "Long JABACABA..., First J");
-assertEquals(1535, long.indexOf(pattern, 512), "Long JABACABA..., Second J");
-
-
var lipsum = "lorem ipsum per se esse fugiendum. itaque aiunt hanc quasi "
+ "naturalem atque insitam in animis nostris inesse notionem, ut "
+ "alterum esse appetendum, alterum aspernandum sentiamus. Alii autem,"
diff --git a/test/mjsunit/typeof.js b/test/mjsunit/typeof.js
new file mode 100644
index 0000000..b460fbb
--- /dev/null
+++ b/test/mjsunit/typeof.js
@@ -0,0 +1,40 @@
+// 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: --nofast-compiler
+
+// The type of a regular expression should be 'function', including in
+// the context of string equality comparisons.
+
+var r = new RegExp;
+assertEquals('function', typeof r);
+assertTrue(typeof r == 'function');
+
+function test(x, y) { return x == y; }
+assertFalse(test('object', typeof r));
+
+assertFalse(typeof r == 'object');
diff --git a/test/mjsunit/unicode-case-overoptimization.js b/test/mjsunit/unicode-case-overoptimization.js
new file mode 100644
index 0000000..bfda48c
--- /dev/null
+++ b/test/mjsunit/unicode-case-overoptimization.js
@@ -0,0 +1,35 @@
+// 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.
+
+// Test all non-ASCII characters individually to ensure that our optimizations
+// didn't break anything.
+for (var i = 0x80; i <= 0xfffe; i++) {
+ var c = String.fromCharCode(i);
+ var c2 = String.fromCharCode(i + 1);
+ var re = new RegExp("[" + c + "-" + c2 + "]", "i");
+ assertTrue(re.test(c), i);
+}
diff --git a/test/mozilla/testcfg.py b/test/mozilla/testcfg.py
index 477b2b2..d1c1767 100644
--- a/test/mozilla/testcfg.py
+++ b/test/mozilla/testcfg.py
@@ -103,6 +103,7 @@
for excluded in EXCLUDED:
if excluded in dirs:
dirs.remove(excluded)
+ dirs.sort()
root_path = root[len(self.root):].split(os.path.sep)
root_path = current_path + [x for x in root_path if x]
framework = []
@@ -113,6 +114,7 @@
if exists(script):
framework.append(script)
framework.reverse()
+ files.sort()
for file in files:
if (not file in FRAMEWORK) and file.endswith('.js'):
full_path = root_path + [file[:-3]]
diff --git a/test/sputnik/README b/test/sputnik/README
new file mode 100644
index 0000000..3d39a67
--- /dev/null
+++ b/test/sputnik/README
@@ -0,0 +1,6 @@
+To run the sputniktests you must check out the test suite from
+googlecode.com. The test expectations are currently relative to
+version 28. To get the tests run the following command within
+v8/tests/sputnik/
+
+ svn co http://sputniktests.googlecode.com/svn/trunk/ -r28 sputniktests
diff --git a/test/sputnik/sputnik.status b/test/sputnik/sputnik.status
new file mode 100644
index 0000000..16a44c5
--- /dev/null
+++ b/test/sputnik/sputnik.status
@@ -0,0 +1,318 @@
+# 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.
+
+prefix sputnik
+def FAIL_OK = FAIL, OKAY
+
+##################### DELIBERATE INCOMPATIBILITIES #####################
+
+# 900066: Deleting elements in .arguments should disconnect the
+# element from the actual arguments. Implementing this is nontrivial
+# and we have no indication that anything on the web depends on this
+# feature.
+S13_A13_T1: FAIL_OK
+S13_A13_T2: FAIL_OK
+S13_A13_T3: FAIL_OK
+
+# This tests precision of trignometric functions. We're slightly off
+# from the implementation in libc (~ 1e-17) but it's not clear if we
+# or they are closer to the right answer, or if it even matters.
+S15.8.2.16_A7: PASS || FAIL_OK
+S15.8.2.18_A7: PASS || FAIL_OK
+S15.8.2.13_A23: PASS || FAIL_OK
+
+# We allow calls to regexp exec() with no arguments to fail for
+# compatibility reasons.
+S15.10.6.2_A1_T16: FAIL_OK
+S15.10.6.3_A1_T16: FAIL_OK
+
+# We allow regexps to be called as functions for compatibility reasons.
+S15.10.7_A1_T1: FAIL_OK
+S15.10.7_A1_T2: FAIL_OK
+
+# We allow construct calls to built-in functions, and we allow built-in
+# functions to have prototypes.
+S15.1.2.1_A4.6: FAIL_OK
+S15.1.2.1_A4.7: FAIL_OK
+S15.1.2.2_A9.6: FAIL_OK
+S15.1.2.2_A9.7: FAIL_OK
+S15.1.2.3_A7.6: FAIL_OK
+S15.1.2.3_A7.7: FAIL_OK
+S15.1.2.4_A2.6: FAIL_OK
+S15.1.2.4_A2.7: FAIL_OK
+S15.1.2.5_A2.6: FAIL_OK
+S15.1.2.5_A2.7: FAIL_OK
+S15.1.3.1_A5.6: FAIL_OK
+S15.1.3.1_A5.7: FAIL_OK
+S15.1.3.2_A5.6: FAIL_OK
+S15.1.3.2_A5.7: FAIL_OK
+S15.1.3.3_A5.6: FAIL_OK
+S15.1.3.3_A5.7: FAIL_OK
+S15.1.3.4_A5.6: FAIL_OK
+S15.1.3.4_A5.7: FAIL_OK
+S15.10.6.2_A6: FAIL_OK
+S15.10.6.3_A6: FAIL_OK
+S15.10.6.4_A6: FAIL_OK
+S15.10.6.4_A7: FAIL_OK
+S15.2.4.2_A6: FAIL_OK
+S15.2.4.3_A6: FAIL_OK
+S15.2.4.4_A6: FAIL_OK
+S15.2.4.5_A6: FAIL_OK
+S15.2.4.6_A6: FAIL_OK
+S15.2.4.7_A6: FAIL_OK
+S15.3.4.2_A6: FAIL_OK
+S15.4.4.10_A5.6: FAIL_OK
+S15.4.4.10_A5.7: FAIL_OK
+S15.4.4.11_A7.6: FAIL_OK
+S15.4.4.11_A7.7: FAIL_OK
+S15.4.4.12_A5.6: FAIL_OK
+S15.4.4.12_A5.7: FAIL_OK
+S15.4.4.13_A5.6: FAIL_OK
+S15.4.4.13_A5.7: FAIL_OK
+S15.4.4.2_A4.6: FAIL_OK
+S15.4.4.3_A4.6: FAIL_OK
+S15.4.4.3_A4.6: FAIL_OK
+S15.4.4.4_A4.6: FAIL_OK
+S15.4.4.4_A4.7: FAIL_OK
+S15.4.4.5_A6.6: FAIL_OK
+S15.4.4.5_A6.7: FAIL_OK
+S15.4.4.6_A5.6: FAIL_OK
+S15.4.4.6_A5.7: FAIL_OK
+S15.4.4.7_A6.6: FAIL_OK
+S15.4.4.7_A6.7: FAIL_OK
+S15.4.4.8_A5.6: FAIL_OK
+S15.4.4.8_A5.7: FAIL_OK
+S15.4.4.9_A5.6: FAIL_OK
+S15.4.4.9_A5.7: FAIL_OK
+S15.5.4.10_A6: FAIL_OK
+S15.5.4.11_A6: FAIL_OK
+S15.5.4.12_A6: FAIL_OK
+S15.5.4.13_A6: FAIL_OK
+S15.5.4.14_A6: FAIL_OK
+S15.5.4.15_A6: FAIL_OK
+S15.5.4.16_A6: FAIL_OK
+S15.5.4.17_A6: FAIL_OK
+S15.5.4.18_A6: FAIL_OK
+S15.5.4.19_A6: FAIL_OK
+S15.5.4.4_A6: FAIL_OK
+S15.5.4.5_A6: FAIL_OK
+S15.5.4.6_A6: FAIL_OK
+S15.5.4.7_A6: FAIL_OK
+S15.5.4.9_A6: FAIL_OK
+S15.3.4.3_A12: FAIL_OK
+S15.3.4.4_A12: FAIL_OK
+S15.5.4.8_A6: FAIL_OK
+
+# We are silent in some regexp cases where the spec wants us to give
+# errors, for compatibility.
+S15.10.2.11_A1_T2: FAIL
+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.
+S7.8.4_A4.3_T2: FAIL_OK
+S7.8.4_A4.3_T2: FAIL_OK
+S7.8.4_A6.2_T2: FAIL_OK
+S7.8.4_A6.1_T4: FAIL_OK
+S7.8.4_A4.3_T4: FAIL_OK
+S7.8.4_A7.2_T2: FAIL_OK
+S7.8.4_A7.1_T4: FAIL_OK
+S7.8.4_A6.4_T2: FAIL_OK
+S7.8.4_A7.4_T2: FAIL_OK
+S7.8.4_A7.2_T4: FAIL_OK
+S7.8.4_A4.3_T6: FAIL_OK
+S7.8.4_A7.2_T6: FAIL_OK
+S7.8.4_A4.3_T1: FAIL_OK
+S7.8.4_A6.2_T1: FAIL_OK
+S7.8.4_A4.3_T3: FAIL_OK
+S7.8.4_A7.2_T1: FAIL_OK
+S7.8.4_A6.4_T1: FAIL_OK
+S7.8.4_A7.2_T3: FAIL_OK
+S7.8.4_A7.4_T1: FAIL_OK
+S7.8.4_A4.3_T5: FAIL_OK
+S7.8.4_A7.2_T5: FAIL_OK
+S7.8.4_A4.3_T1: FAIL_OK
+S7.8.4_A6.2_T1: FAIL_OK
+S7.8.4_A4.3_T3: FAIL_OK
+S7.8.4_A7.2_T1: FAIL_OK
+S7.8.4_A6.4_T1: FAIL_OK
+S7.8.4_A7.2_T3: FAIL_OK
+S7.8.4_A7.4_T1: FAIL_OK
+S7.8.4_A4.3_T5: FAIL_OK
+S7.8.4_A7.2_T5: FAIL_OK
+
+# We allow some keywords to be used as identifiers
+S7.5.3_A1.17: FAIL_OK
+S7.5.3_A1.26: FAIL_OK
+S7.5.3_A1.18: FAIL_OK
+S7.5.3_A1.27: FAIL_OK
+S7.5.3_A1.28: FAIL_OK
+S7.5.3_A1.19: FAIL_OK
+S7.5.3_A1.29: FAIL_OK
+S7.5.3_A1.1: FAIL_OK
+S7.5.3_A1.2: FAIL_OK
+S7.5.3_A1.3: FAIL_OK
+S7.5.3_A1.4: FAIL_OK
+S7.5.3_A1.5: FAIL_OK
+S7.5.3_A1.8: FAIL_OK
+S7.5.3_A1.9: FAIL_OK
+S7.5.3_A1.10: FAIL_OK
+S7.5.3_A1.11: FAIL_OK
+S7.5.3_A1.21: FAIL_OK
+S7.5.3_A1.12: FAIL_OK
+S7.5.3_A1.30: FAIL_OK
+S7.5.3_A1.31: FAIL_OK
+S7.5.3_A1.13: FAIL_OK
+S7.5.3_A1.22: FAIL_OK
+S7.5.3_A1.23: FAIL_OK
+S7.5.3_A1.14: FAIL_OK
+S7.5.3_A1.15: FAIL_OK
+S7.5.3_A1.24: FAIL_OK
+S7.5.3_A1.25: FAIL_OK
+S7.5.3_A1.16: FAIL_OK
+
+# This checks for non-262 behavior
+S12.6.4_A14_T1: PASS || FAIL_OK
+S12.6.4_R1: PASS || FAIL_OK
+S12.6.4_R2: PASS || FAIL_OK
+S8.4_D2.1: PASS || FAIL_OK
+S8.4_D2.2: PASS || FAIL_OK
+S8.4_D2.3: PASS || FAIL_OK
+S8.4_D2.4: PASS || FAIL_OK
+S8.4_D2.5: PASS || FAIL_OK
+S8.4_D2.6: PASS || FAIL_OK
+S8.4_D2.7: PASS || FAIL_OK
+S8.4_D1.1: PASS || FAIL_OK
+S13.2_D1.2: PASS || FAIL_OK
+S11.4.3_D1.2: PASS || FAIL_OK
+S7.6_D1: PASS || FAIL_OK
+S7.6_D2: PASS || FAIL_OK
+S15.1.2.2_D1.2: PASS || FAIL_OK
+S13_D1_T1: PASS || FAIL_OK
+S14_D4_T3: PASS || FAIL_OK
+S14_D7: PASS || FAIL_OK
+S15.5.4.11_D1.1_T2: PASS || FAIL_OK
+S15.5.4.11_D1.1_T4: PASS || FAIL_OK
+S15.5.2_D2: PASS || FAIL_OK
+S15.5.4.11_D1.1_T1: PASS || FAIL_OK
+S15.5.4.11_D1.1_T3: PASS || FAIL_OK
+S12.6.4_D1: PASS || FAIL_OK
+
+# We deliberately don't throw type errors when iterating through the
+# undefined object
+S9.9_A1: FAIL_OK
+S9.9_A2: FAIL_OK
+
+# We allow function declarations within statements
+S12.5_A9_T1: FAIL_OK
+S12.5_A9_T2: FAIL_OK
+# S12.6.2_A13_T3: FAIL_OK
+# S12.5_A9_T3: FAIL_OK
+# S12.6.1_A13_T3: FAIL_OK
+S12.1_A1: FAIL_OK
+S12.6.2_A13_T1: FAIL_OK
+S12.6.2_A13_T2: FAIL_OK
+S12.6.1_A13_T1: FAIL_OK
+S12.6.1_A13_T2: FAIL_OK
+S12.6.4_A13_T1: FAIL_OK
+S12.6.4_A13_T2: FAIL_OK
+#S12.6.4_A13_T3: FAIL_OK
+S15.3.4.2_A1_T1: FAIL_OK
+
+# Linux and Mac defaults to extended 80 bit floating point format in the FPU.
+# We follow the other major JS engines by keeping this default.
+S8.5_A2.2: PASS, FAIL if $system == linux, FAIL if $system == macos
+S8.5_A2.1: PASS, FAIL if $system == linux, FAIL if $system == macos
+
+##################### SKIPPED TESTS #####################
+
+# These tests take a looong time to run in debug mode.
+S15.1.3.2_A2.5_T1: PASS, SKIP if $mode == debug
+S15.1.3.1_A2.5_T1: PASS, SKIP if $mode == debug
+
+
+# These tests fail because we had to add bugs to be compatible with JSC. See
+# http://code.google.com/p/chromium/issues/detail?id=1717
+S15.4.4_A1.1_T2: FAIL_OK
+S15.5.4.1_A1_T2: FAIL_OK
+S15.5.4_A1: FAIL_OK
+S15.5.4_A3: FAIL_OK
+S15.9.5.10_A1_T2: FAIL_OK
+S15.9.5.11_A1_T2: FAIL_OK
+S15.9.5.12_A1_T2: FAIL_OK
+S15.9.5.13_A1_T2: FAIL_OK
+S15.9.5.14_A1_T2: FAIL_OK
+S15.9.5.15_A1_T2: FAIL_OK
+S15.9.5.16_A1_T2: FAIL_OK
+S15.9.5.17_A1_T2: FAIL_OK
+S15.9.5.18_A1_T2: FAIL_OK
+S15.9.5.19_A1_T2: FAIL_OK
+S15.9.5.20_A1_T2: FAIL_OK
+S15.9.5.21_A1_T2: FAIL_OK
+S15.9.5.22_A1_T2: FAIL_OK
+S15.9.5.23_A1_T2: FAIL_OK
+S15.9.5.24_A1_T2: FAIL_OK
+S15.9.5.25_A1_T2: FAIL_OK
+S15.9.5.26_A1_T2: FAIL_OK
+S15.9.5.27_A1_T2: FAIL_OK
+S15.9.5.28_A1_T2: FAIL_OK
+S15.9.5.29_A1_T2: FAIL_OK
+S15.9.5.2_A1_T2: FAIL_OK
+S15.9.5.30_A1_T2: FAIL_OK
+S15.9.5.31_A1_T2: FAIL_OK
+S15.9.5.32_A1_T2: FAIL_OK
+S15.9.5.33_A1_T2: FAIL_OK
+S15.9.5.34_A1_T2: FAIL_OK
+S15.9.5.35_A1_T2: FAIL_OK
+S15.9.5.36_A1_T2: FAIL_OK
+S15.9.5.37_A1_T2: FAIL_OK
+S15.9.5.38_A1_T2: FAIL_OK
+S15.9.5.39_A1_T2: FAIL_OK
+S15.9.5.3_A1_T2: FAIL_OK
+S15.9.5.40_A1_T2: FAIL_OK
+S15.9.5.41_A1_T2: FAIL_OK
+S15.9.5.42_A1_T2: FAIL_OK
+S15.9.5.4_A1_T2: FAIL_OK
+S15.9.5.5_A1_T2: FAIL_OK
+S15.9.5.6_A1_T2: FAIL_OK
+S15.9.5.7_A1_T2: FAIL_OK
+S15.9.5.8_A1_T2: FAIL_OK
+S15.9.5.9_A1_T2: FAIL_OK
+
+# Regexps have type "function", not "object".
+S11.4.3_A3.6: FAIL_OK
+S15.10.7_A3_T2: FAIL_OK
+S15.10.7_A3_T1: FAIL_OK
diff --git a/test/sputnik/testcfg.py b/test/sputnik/testcfg.py
new file mode 100644
index 0000000..6592382
--- /dev/null
+++ b/test/sputnik/testcfg.py
@@ -0,0 +1,112 @@
+# 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.
+
+
+import os
+from os.path import join, exists
+import sys
+import test
+import time
+
+
+class SputnikTestCase(test.TestCase):
+
+ def __init__(self, case, path, context, mode):
+ super(SputnikTestCase, self).__init__(context, path)
+ self.case = case
+ self.mode = mode
+ self.tmpfile = None
+ self.source = None
+
+ def IsNegative(self):
+ return '@negative' in self.GetSource()
+
+ def IsFailureOutput(self, output):
+ if output.exit_code != 0:
+ return True
+ out = output.stdout
+ return "SputnikError" in out
+
+ def BeforeRun(self):
+ self.tmpfile = sputnik.TempFile(suffix='.js', prefix='sputnik-', text=True)
+ self.tmpfile.Write(self.GetSource())
+ self.tmpfile.Close()
+
+ def AfterRun(self):
+ self.tmpfile.Dispose()
+ self.tmpfile = None
+
+ def GetCommand(self):
+ result = [self.context.GetVm(self.mode)]
+ result.append(self.tmpfile.name)
+ return result
+
+ def GetLabel(self):
+ return "%s sputnik %s" % (self.mode, self.GetName())
+
+ def GetName(self):
+ return self.path[-1]
+
+ def GetSource(self):
+ if not self.source:
+ self.source = self.case.GetSource()
+ return self.source
+
+class SputnikTestConfiguration(test.TestConfiguration):
+
+ def __init__(self, context, root):
+ super(SputnikTestConfiguration, self).__init__(context, root)
+
+ def ListTests(self, current_path, path, mode):
+ # Import the sputnik test runner script as a module
+ testroot = join(self.root, 'sputniktests')
+ modroot = join(testroot, 'tools')
+ sys.path.append(modroot)
+ import sputnik
+ globals()['sputnik'] = sputnik
+ test_suite = sputnik.TestSuite(testroot)
+ test_suite.Validate()
+ tests = test_suite.EnumerateTests([])
+ result = []
+ for test in tests:
+ full_path = current_path + [test.GetPath()[-1]]
+ if self.Contains(path, full_path):
+ case = SputnikTestCase(test, full_path, self.context, mode)
+ result.append(case)
+ return result
+
+ def GetBuildRequirements(self):
+ return ['sample', 'sample=shell']
+
+ def GetTestStatus(self, sections, defs):
+ status_file = join(self.root, 'sputnik.status')
+ if exists(status_file):
+ test.ReadConfigurationInto(status_file, sections, defs)
+
+
+def GetConfiguration(context, root):
+ return SputnikTestConfiguration(context, root)