Add tests for FuncNameInferrer.

There were no explicit tests for FuncNameInferrer (though, some tests might
implicitly rely on it working properly in the common cases). Afaics, there were
no tests which would exercise inferring two byte function names or escaped
function names.

R=rossberg@chromium.org
BUG=

Review URL: https://codereview.chromium.org/310063002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21649 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
marja@chromium.org 2014-06-03 15:02:16 +00:00
parent e4bde5ca25
commit 350a3329ed
3 changed files with 141 additions and 52 deletions

View File

@ -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<uint16_t>(array_length);
for (int i = 0; i < array_length; i++) converted[i] = source[i];
return converted;
}
static inline v8::Local<v8::Value> v8_num(double x) {
return v8::Number::New(v8::Isolate::GetCurrent(), x);
}
@ -403,6 +412,52 @@ static inline v8::Local<v8::Value> CompileRunWithOrigin(
}
static inline void ExpectString(const char* code, const char* expected) {
v8::Local<v8::Value> 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<v8::Value> result = CompileRun(code);
CHECK(result->IsInt32());
CHECK_EQ(expected, result->Int32Value());
}
static inline void ExpectBoolean(const char* code, bool expected) {
v8::Local<v8::Value> 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<v8::Value> expected) {
v8::Local<v8::Value> result = CompileRun(code);
CHECK(result->SameValue(expected));
}
static inline void ExpectUndefined(const char* code) {
v8::Local<v8::Value> 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<int>(

View File

@ -99,50 +99,6 @@ void RunWithProfiler(void (*test)()) {
}
static void ExpectString(const char* code, const char* expected) {
Local<Value> result = CompileRun(code);
CHECK(result->IsString());
String::Utf8Value utf8(result);
CHECK_EQ(expected, *utf8);
}
static void ExpectInt32(const char* code, int expected) {
Local<Value> result = CompileRun(code);
CHECK(result->IsInt32());
CHECK_EQ(expected, result->Int32Value());
}
static void ExpectBoolean(const char* code, bool expected) {
Local<Value> result = CompileRun(code);
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<Value> expected) {
Local<Value> result = CompileRun(code);
CHECK(result->Equals(expected));
}
static void ExpectUndefined(const char* code) {
Local<Value> result = CompileRun(code);
CHECK(result->IsUndefined());
}
static int signature_callback_count;
static Local<Value> 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<uint16_t>(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)

View File

@ -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<v8::String> source =
v8::String::NewFromTwoByte(isolate, two_byte_source);
v8::Local<v8::Value> result = CompileRun(source);
CHECK(result->IsString());
v8::Local<v8::String> 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<v8::String> source =
v8::String::NewFromTwoByte(isolate, two_byte_source);
v8::Local<v8::Value> result = CompileRun(source);
CHECK(result->IsString());
v8::Local<v8::String> expected_name =
v8::String::NewFromTwoByte(isolate, two_byte_name);
CHECK(result->Equals(expected_name));
}