diff --git a/test/cctest/cctest.h b/test/cctest/cctest.h index edb1de9144..a357be4904 100644 --- a/test/cctest/cctest.h +++ b/test/cctest/cctest.h @@ -311,6 +311,15 @@ class LocalContext { v8::Isolate* isolate_; }; + +static inline uint16_t* AsciiToTwoByteString(const char* source) { + int array_length = i::StrLength(source) + 1; + uint16_t* converted = i::NewArray(array_length); + for (int i = 0; i < array_length; i++) converted[i] = source[i]; + return converted; +} + + static inline v8::Local v8_num(double x) { return v8::Number::New(v8::Isolate::GetCurrent(), x); } @@ -403,6 +412,52 @@ static inline v8::Local CompileRunWithOrigin( } + +static inline void ExpectString(const char* code, const char* expected) { + v8::Local result = CompileRun(code); + CHECK(result->IsString()); + v8::String::Utf8Value utf8(result); + CHECK_EQ(expected, *utf8); +} + + +static inline void ExpectInt32(const char* code, int expected) { + v8::Local result = CompileRun(code); + CHECK(result->IsInt32()); + CHECK_EQ(expected, result->Int32Value()); +} + + +static inline void ExpectBoolean(const char* code, bool expected) { + v8::Local result = CompileRun(code); + CHECK(result->IsBoolean()); + CHECK_EQ(expected, result->BooleanValue()); +} + + +static inline void ExpectTrue(const char* code) { + ExpectBoolean(code, true); +} + + +static inline void ExpectFalse(const char* code) { + ExpectBoolean(code, false); +} + + +static inline void ExpectObject(const char* code, + v8::Local expected) { + v8::Local result = CompileRun(code); + CHECK(result->SameValue(expected)); +} + + +static inline void ExpectUndefined(const char* code) { + v8::Local result = CompileRun(code); + CHECK(result->IsUndefined()); +} + + // Helper function that simulates a full new-space in the heap. static inline void SimulateFullSpace(v8::internal::NewSpace* space) { int new_linear_size = static_cast( diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index 54a9932ddd..2f39b3f81f 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -99,50 +99,6 @@ void RunWithProfiler(void (*test)()) { } -static void ExpectString(const char* code, const char* expected) { - Local result = CompileRun(code); - CHECK(result->IsString()); - String::Utf8Value utf8(result); - CHECK_EQ(expected, *utf8); -} - - -static void ExpectInt32(const char* code, int expected) { - Local result = CompileRun(code); - CHECK(result->IsInt32()); - CHECK_EQ(expected, result->Int32Value()); -} - - -static void ExpectBoolean(const char* code, bool expected) { - Local result = CompileRun(code); - CHECK(result->IsBoolean()); - CHECK_EQ(expected, result->BooleanValue()); -} - - -static void ExpectTrue(const char* code) { - ExpectBoolean(code, true); -} - - -static void ExpectFalse(const char* code) { - ExpectBoolean(code, false); -} - - -static void ExpectObject(const char* code, Local expected) { - Local result = CompileRun(code); - CHECK(result->Equals(expected)); -} - - -static void ExpectUndefined(const char* code) { - Local result = CompileRun(code); - CHECK(result->IsUndefined()); -} - - static int signature_callback_count; static Local signature_expected_receiver; static void IncrementingSignatureCallback( @@ -451,14 +407,6 @@ THREADED_TEST(Script) { } -static uint16_t* AsciiToTwoByteString(const char* source) { - int array_length = i::StrLength(source) + 1; - uint16_t* converted = i::NewArray(array_length); - for (int i = 0; i < array_length; i++) converted[i] = source[i]; - return converted; -} - - class TestResource: public String::ExternalStringResource { public: TestResource(uint16_t* data, int* counter = NULL, bool owning_data = true) diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc index 15fdbdc738..f6cf94eb72 100644 --- a/test/cctest/test-parsing.cc +++ b/test/cctest/test-parsing.cc @@ -2457,3 +2457,89 @@ TEST(InvalidLeftHandSide) { RunParserSyncTest(postfix_context_data, good_statement_data, kSuccess); RunParserSyncTest(postfix_context_data, bad_statement_data_common, kError); } + + +TEST(FuncNameInferrerBasic) { + // Tests that function names are inferred properly. + i::FLAG_allow_natives_syntax = true; + v8::Isolate* isolate = CcTest::isolate(); + v8::HandleScope scope(isolate); + LocalContext env; + CompileRun("var foo1 = function() {}; " + "var foo2 = function foo3() {}; " + "function not_ctor() { " + " var foo4 = function() {}; " + " return %FunctionGetInferredName(foo4); " + "} " + "function Ctor() { " + " var foo5 = function() {}; " + " return %FunctionGetInferredName(foo5); " + "} " + "var obj1 = { foo6: function() {} }; " + "var obj2 = { 'foo7': function() {} }; " + "var obj3 = {}; " + "obj3[1] = function() {}; " + "var obj4 = {}; " + "obj4[1] = function foo8() {}; " + "var obj5 = {}; " + "obj5['foo9'] = function() {}; " + "var obj6 = { obj7 : { foo10: function() {} } };"); + ExpectString("%FunctionGetInferredName(foo1)", "foo1"); + // foo2 is not unnamed -> its name is not inferred. + ExpectString("%FunctionGetInferredName(foo2)", ""); + ExpectString("not_ctor()", "foo4"); + ExpectString("Ctor()", "Ctor.foo5"); + ExpectString("%FunctionGetInferredName(obj1.foo6)", "obj1.foo6"); + ExpectString("%FunctionGetInferredName(obj2.foo7)", "obj2.foo7"); + ExpectString("%FunctionGetInferredName(obj3[1])", + "obj3.(anonymous function)"); + ExpectString("%FunctionGetInferredName(obj4[1])", ""); + ExpectString("%FunctionGetInferredName(obj5['foo9'])", "obj5.foo9"); + ExpectString("%FunctionGetInferredName(obj6.obj7.foo10)", "obj6.obj7.foo10"); +} + + +TEST(FuncNameInferrerTwoByte) { + // Tests function name inferring in cases where some parts of the inferred + // function name are two-byte strings. + i::FLAG_allow_natives_syntax = true; + v8::Isolate* isolate = CcTest::isolate(); + v8::HandleScope scope(isolate); + LocalContext env; + uint16_t* two_byte_source = AsciiToTwoByteString( + "var obj1 = { oXj2 : { foo1: function() {} } }; " + "%FunctionGetInferredName(obj1.oXj2.foo1)"); + uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1"); + // Make it really non-ASCII (replace the Xs with a non-ASCII character). + two_byte_source[14] = two_byte_source[78] = two_byte_name[6] = 0x010d; + v8::Local source = + v8::String::NewFromTwoByte(isolate, two_byte_source); + v8::Local result = CompileRun(source); + CHECK(result->IsString()); + v8::Local expected_name = + v8::String::NewFromTwoByte(isolate, two_byte_name); + CHECK(result->Equals(expected_name)); +} + + +TEST(FuncNameInferrerEscaped) { + // The same as FuncNameInferrerTwoByte, except that we express the two-byte + // character as a unicode escape. + i::FLAG_allow_natives_syntax = true; + v8::Isolate* isolate = CcTest::isolate(); + v8::HandleScope scope(isolate); + LocalContext env; + uint16_t* two_byte_source = AsciiToTwoByteString( + "var obj1 = { o\\u010dj2 : { foo1: function() {} } }; " + "%FunctionGetInferredName(obj1.o\\u010dj2.foo1)"); + uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1"); + // Fix to correspond to the non-ASCII name in two_byte_source. + two_byte_name[6] = 0x010d; + v8::Local source = + v8::String::NewFromTwoByte(isolate, two_byte_source); + v8::Local result = CompileRun(source); + CHECK(result->IsString()); + v8::Local expected_name = + v8::String::NewFromTwoByte(isolate, two_byte_name); + CHECK(result->Equals(expected_name)); +}