| Index: test/cctest/test-api.cc
|
| ===================================================================
|
| --- test/cctest/test-api.cc (revision 8778)
|
| +++ test/cctest/test-api.cc (working copy)
|
| @@ -1026,6 +1026,90 @@
|
| }
|
|
|
|
|
| +THREADED_TEST(IsNativeError) {
|
| + v8::HandleScope scope;
|
| + LocalContext env;
|
| + v8::Handle<Value> syntax_error = CompileRun(
|
| + "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
|
| + CHECK(syntax_error->IsNativeError());
|
| + v8::Handle<Value> not_error = CompileRun("{a:42}");
|
| + CHECK(!not_error->IsNativeError());
|
| + v8::Handle<Value> not_object = CompileRun("42");
|
| + CHECK(!not_object->IsNativeError());
|
| +}
|
| +
|
| +
|
| +THREADED_TEST(StringObject) {
|
| + v8::HandleScope scope;
|
| + LocalContext env;
|
| + v8::Handle<Value> boxed_string = CompileRun("new String(\"test\")");
|
| + CHECK(boxed_string->IsStringObject());
|
| + v8::Handle<Value> unboxed_string = CompileRun("\"test\"");
|
| + CHECK(!unboxed_string->IsStringObject());
|
| + v8::Handle<Value> boxed_not_string = CompileRun("new Number(42)");
|
| + CHECK(!boxed_not_string->IsStringObject());
|
| + v8::Handle<Value> not_object = CompileRun("0");
|
| + CHECK(!not_object->IsStringObject());
|
| + v8::Handle<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
|
| + CHECK(!as_boxed.IsEmpty());
|
| + Local<v8::String> the_string = as_boxed->StringValue();
|
| + CHECK(!the_string.IsEmpty());
|
| + ExpectObject("\"test\"", the_string);
|
| + v8::Handle<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
|
| + CHECK(new_boxed_string->IsStringObject());
|
| + as_boxed = new_boxed_string.As<v8::StringObject>();
|
| + the_string = as_boxed->StringValue();
|
| + CHECK(!the_string.IsEmpty());
|
| + ExpectObject("\"test\"", the_string);
|
| +}
|
| +
|
| +
|
| +THREADED_TEST(NumberObject) {
|
| + v8::HandleScope scope;
|
| + LocalContext env;
|
| + v8::Handle<Value> boxed_number = CompileRun("new Number(42)");
|
| + CHECK(boxed_number->IsNumberObject());
|
| + v8::Handle<Value> unboxed_number = CompileRun("42");
|
| + CHECK(!unboxed_number->IsNumberObject());
|
| + v8::Handle<Value> boxed_not_number = CompileRun("new Boolean(false)");
|
| + CHECK(!boxed_not_number->IsNumberObject());
|
| + v8::Handle<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
|
| + CHECK(!as_boxed.IsEmpty());
|
| + double the_number = as_boxed->NumberValue();
|
| + CHECK_EQ(42.0, the_number);
|
| + v8::Handle<v8::Value> new_boxed_number = v8::NumberObject::New(43);
|
| + CHECK(new_boxed_number->IsNumberObject());
|
| + as_boxed = new_boxed_number.As<v8::NumberObject>();
|
| + the_number = as_boxed->NumberValue();
|
| + CHECK_EQ(43.0, the_number);
|
| +}
|
| +
|
| +
|
| +THREADED_TEST(BooleanObject) {
|
| + v8::HandleScope scope;
|
| + LocalContext env;
|
| + v8::Handle<Value> boxed_boolean = CompileRun("new Boolean(true)");
|
| + CHECK(boxed_boolean->IsBooleanObject());
|
| + v8::Handle<Value> unboxed_boolean = CompileRun("true");
|
| + CHECK(!unboxed_boolean->IsBooleanObject());
|
| + v8::Handle<Value> boxed_not_boolean = CompileRun("new Number(42)");
|
| + CHECK(!boxed_not_boolean->IsBooleanObject());
|
| + v8::Handle<v8::BooleanObject> as_boxed =
|
| + boxed_boolean.As<v8::BooleanObject>();
|
| + CHECK(!as_boxed.IsEmpty());
|
| + bool the_boolean = as_boxed->BooleanValue();
|
| + CHECK_EQ(true, the_boolean);
|
| + v8::Handle<v8::Value> boxed_true = v8::BooleanObject::New(true);
|
| + v8::Handle<v8::Value> boxed_false = v8::BooleanObject::New(false);
|
| + CHECK(boxed_true->IsBooleanObject());
|
| + CHECK(boxed_false->IsBooleanObject());
|
| + as_boxed = boxed_true.As<v8::BooleanObject>();
|
| + CHECK_EQ(true, as_boxed->BooleanValue());
|
| + as_boxed = boxed_false.As<v8::BooleanObject>();
|
| + CHECK_EQ(false, as_boxed->BooleanValue());
|
| +}
|
| +
|
| +
|
| THREADED_TEST(Number) {
|
| v8::HandleScope scope;
|
| LocalContext env;
|
| @@ -2048,10 +2132,15 @@
|
| THREADED_TEST(PropertyAttributes) {
|
| v8::HandleScope scope;
|
| LocalContext context;
|
| + // none
|
| + Local<String> prop = v8_str("none");
|
| + context->Global()->Set(prop, v8_num(7));
|
| + CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
|
| // read-only
|
| - Local<String> prop = v8_str("read_only");
|
| + prop = v8_str("read_only");
|
| context->Global()->Set(prop, v8_num(7), v8::ReadOnly);
|
| CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
|
| + CHECK_EQ(v8::ReadOnly, context->Global()->GetPropertyAttributes(prop));
|
| Script::Compile(v8_str("read_only = 9"))->Run();
|
| CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
|
| context->Global()->Set(prop, v8_num(10));
|
| @@ -2062,6 +2151,25 @@
|
| CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
|
| Script::Compile(v8_str("delete dont_delete"))->Run();
|
| CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
|
| + CHECK_EQ(v8::DontDelete, context->Global()->GetPropertyAttributes(prop));
|
| + // dont-enum
|
| + prop = v8_str("dont_enum");
|
| + context->Global()->Set(prop, v8_num(28), v8::DontEnum);
|
| + CHECK_EQ(v8::DontEnum, context->Global()->GetPropertyAttributes(prop));
|
| + // absent
|
| + prop = v8_str("absent");
|
| + CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
|
| + Local<Value> fake_prop = v8_num(1);
|
| + CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(fake_prop));
|
| + // exception
|
| + TryCatch try_catch;
|
| + Local<Value> exception =
|
| + CompileRun("({ toString: function() { throw 'exception';} })");
|
| + CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(exception));
|
| + CHECK(try_catch.HasCaught());
|
| + String::AsciiValue exception_value(try_catch.Exception());
|
| + CHECK_EQ("exception", *exception_value);
|
| + try_catch.Reset();
|
| }
|
|
|
|
|
| @@ -3452,6 +3560,68 @@
|
| }
|
|
|
|
|
| +static v8::Handle<Value> UnboxedDoubleIndexedPropertyGetter(
|
| + uint32_t index,
|
| + const AccessorInfo& info) {
|
| + ApiTestFuzzer::Fuzz();
|
| + if (index < 25) {
|
| + return v8::Handle<Value>(v8_num(index));
|
| + }
|
| + return v8::Handle<Value>();
|
| +}
|
| +
|
| +
|
| +static v8::Handle<Value> UnboxedDoubleIndexedPropertySetter(
|
| + uint32_t index,
|
| + Local<Value> value,
|
| + const AccessorInfo& info) {
|
| + ApiTestFuzzer::Fuzz();
|
| + if (index < 25) {
|
| + return v8::Handle<Value>(v8_num(index));
|
| + }
|
| + return v8::Handle<Value>();
|
| +}
|
| +
|
| +
|
| +Handle<v8::Array> UnboxedDoubleIndexedPropertyEnumerator(
|
| + const AccessorInfo& info) {
|
| + // Force the list of returned keys to be stored in a FastDoubleArray.
|
| + Local<Script> indexed_property_names_script = Script::Compile(v8_str(
|
| + "keys = new Array(); keys[125000] = 1;"
|
| + "for(i = 0; i < 80000; i++) { keys[i] = i; };"
|
| + "keys.length = 25; keys;"));
|
| + Local<Value> result = indexed_property_names_script->Run();
|
| + return Local<v8::Array>(::v8::Array::Cast(*result));
|
| +}
|
| +
|
| +
|
| +// Make sure that the the interceptor code in the runtime properly handles
|
| +// merging property name lists for double-array-backed arrays.
|
| +THREADED_TEST(IndexedInterceptorUnboxedDoubleWithIndexedAccessor) {
|
| + v8::HandleScope scope;
|
| + Local<ObjectTemplate> templ = ObjectTemplate::New();
|
| + templ->SetIndexedPropertyHandler(UnboxedDoubleIndexedPropertyGetter,
|
| + UnboxedDoubleIndexedPropertySetter,
|
| + 0,
|
| + 0,
|
| + UnboxedDoubleIndexedPropertyEnumerator);
|
| + LocalContext context;
|
| + context->Global()->Set(v8_str("obj"), templ->NewInstance());
|
| + // When obj is created, force it to be Stored in a FastDoubleArray.
|
| + Local<Script> create_unboxed_double_script = Script::Compile(v8_str(
|
| + "obj[125000] = 1; for(i = 0; i < 80000; i+=2) { obj[i] = i; } "
|
| + "key_count = 0; "
|
| + "for (x in obj) {key_count++;};"
|
| + "obj;"));
|
| + Local<Value> result = create_unboxed_double_script->Run();
|
| + CHECK(result->ToObject()->HasRealIndexedProperty(2000));
|
| + Local<Script> key_count_check = Script::Compile(v8_str(
|
| + "key_count;"));
|
| + result = key_count_check->Run();
|
| + CHECK_EQ(v8_num(40013), result);
|
| +}
|
| +
|
| +
|
| static v8::Handle<Value> IdentityIndexedPropertyGetter(
|
| uint32_t index,
|
| const AccessorInfo& info) {
|
| @@ -6885,53 +7055,34 @@
|
| }
|
|
|
|
|
| -THREADED_TEST(SetPrototypeProperties) {
|
| +THREADED_TEST(FunctionReadOnlyPrototype) {
|
| v8::HandleScope handle_scope;
|
| LocalContext context;
|
|
|
| Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
|
| - t1->SetPrototypeAttributes(v8::DontDelete);
|
| + t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(42));
|
| + t1->ReadOnlyPrototype();
|
| context->Global()->Set(v8_str("func1"), t1->GetFunction());
|
| + // Configured value of ReadOnly flag.
|
| CHECK(CompileRun(
|
| "(function() {"
|
| " descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
|
| - " return (descriptor['writable'] == true) &&"
|
| - " (descriptor['enumerable'] == true) &&"
|
| - " (descriptor['configurable'] == false);"
|
| + " return (descriptor['writable'] == false);"
|
| "})()")->BooleanValue());
|
| + CHECK_EQ(42, CompileRun("func1.prototype.x")->Int32Value());
|
| + CHECK_EQ(42,
|
| + CompileRun("func1.prototype = {}; func1.prototype.x")->Int32Value());
|
|
|
| Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
|
| - t2->SetPrototypeAttributes(v8::DontEnum);
|
| + t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(42));
|
| context->Global()->Set(v8_str("func2"), t2->GetFunction());
|
| + // Default value of ReadOnly flag.
|
| CHECK(CompileRun(
|
| "(function() {"
|
| " descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
|
| - " return (descriptor['writable'] == true) &&"
|
| - " (descriptor['enumerable'] == false) &&"
|
| - " (descriptor['configurable'] == true);"
|
| + " return (descriptor['writable'] == true);"
|
| "})()")->BooleanValue());
|
| -
|
| - Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
|
| - t3->SetPrototypeAttributes(v8::ReadOnly);
|
| - context->Global()->Set(v8_str("func3"), t3->GetFunction());
|
| - CHECK(CompileRun(
|
| - "(function() {"
|
| - " descriptor = Object.getOwnPropertyDescriptor(func3, 'prototype');"
|
| - " return (descriptor['writable'] == false) &&"
|
| - " (descriptor['enumerable'] == true) &&"
|
| - " (descriptor['configurable'] == true);"
|
| - "})()")->BooleanValue());
|
| -
|
| - Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New();
|
| - t4->SetPrototypeAttributes(v8::ReadOnly | v8::DontEnum | v8::DontDelete);
|
| - context->Global()->Set(v8_str("func4"), t4->GetFunction());
|
| - CHECK(CompileRun(
|
| - "(function() {"
|
| - " descriptor = Object.getOwnPropertyDescriptor(func4, 'prototype');"
|
| - " return (descriptor['writable'] == false) &&"
|
| - " (descriptor['enumerable'] == false) &&"
|
| - " (descriptor['configurable'] == false);"
|
| - "})()")->BooleanValue());
|
| + CHECK_EQ(42, CompileRun("func2.prototype.x")->Int32Value());
|
| }
|
|
|
|
|
| @@ -12638,9 +12789,10 @@
|
| stackTrace->GetFrame(0));
|
| checkStackFrame(origin, "foo", 6, 3, false, false,
|
| stackTrace->GetFrame(1));
|
| - checkStackFrame(NULL, "", 1, 1, false, false,
|
| + // This is the source string inside the eval which has the call to foo.
|
| + checkStackFrame(NULL, "", 1, 5, false, false,
|
| stackTrace->GetFrame(2));
|
| - // The last frame is an anonymous function that has the initial call.
|
| + // The last frame is an anonymous function which has the initial eval call.
|
| checkStackFrame(origin, "", 8, 7, false, false,
|
| stackTrace->GetFrame(3));
|
|
|
| @@ -12659,9 +12811,10 @@
|
| bool is_eval = false;
|
| #endif // ENABLE_DEBUGGER_SUPPORT
|
|
|
| - checkStackFrame(NULL, "", 1, 1, is_eval, false,
|
| + // This is the source string inside the eval which has the call to baz.
|
| + checkStackFrame(NULL, "", 1, 5, is_eval, false,
|
| stackTrace->GetFrame(2));
|
| - // The last frame is an anonymous function that has the initial call to foo.
|
| + // The last frame is an anonymous function which has the initial eval call.
|
| checkStackFrame(origin, "", 10, 1, false, false,
|
| stackTrace->GetFrame(3));
|
|
|
|
|