1
// Copyright 2011 the V8 project authors. All rights reserved.
2
// Redistribution and use in source and binary forms, with or without
3
// modification, are permitted provided that the following conditions are
6
// * Redistributions of source code must retain the above copyright
7
// notice, this list of conditions and the following disclaimer.
8
// * Redistributions in binary form must reproduce the above
9
// copyright notice, this list of conditions and the following
10
// disclaimer in the documentation and/or other materials provided
11
// with the distribution.
12
// * Neither the name of Google Inc. nor the names of its
13
// contributors may be used to endorse or promote products derived
14
// from this software without specific prior written permission.
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
#include "src/debug.h"
33
#include "src/string-search.h"
34
#include "test/cctest/cctest.h"
37
using ::v8::internal::CStrVector;
38
using ::v8::internal::Factory;
39
using ::v8::internal::Handle;
40
using ::v8::internal::Heap;
41
using ::v8::internal::Isolate;
42
using ::v8::internal::JSFunction;
43
using ::v8::internal::Object;
44
using ::v8::internal::Runtime;
45
using ::v8::internal::Script;
46
using ::v8::internal::SmartArrayPointer;
47
using ::v8::internal::SharedFunctionInfo;
48
using ::v8::internal::String;
49
using ::v8::internal::Vector;
52
static void CheckFunctionName(v8::Handle<v8::Script> script,
53
const char* func_pos_src,
54
const char* ref_inferred_name) {
55
Isolate* isolate = CcTest::i_isolate();
58
Handle<Object> obj = v8::Utils::OpenHandle(*script);
59
Handle<SharedFunctionInfo> shared_function;
60
if (obj->IsSharedFunctionInfo()) {
62
Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(*obj));
65
Handle<SharedFunctionInfo>(JSFunction::cast(*obj)->shared());
67
Handle<Script> i_script(Script::cast(shared_function->script()));
68
CHECK(i_script->source()->IsString());
69
Handle<String> script_src(String::cast(i_script->source()));
71
// Find the position of a given func source substring in the source.
74
i::DisallowHeapAllocation no_gc;
75
Vector<const uint8_t> func_pos_str = i::OneByteVector(func_pos_src);
76
String::FlatContent script_content = script_src->GetFlatContent();
77
func_pos = SearchString(isolate, script_content.ToOneByteVector(),
80
CHECK_NE(0, func_pos);
82
// Obtain SharedFunctionInfo for the function.
83
isolate->debug()->PrepareForBreakPoints();
84
Handle<SharedFunctionInfo> shared_func_info =
85
Handle<SharedFunctionInfo>::cast(
86
isolate->debug()->FindSharedFunctionInfoInScript(i_script, func_pos));
88
// Verify inferred function name.
89
SmartArrayPointer<char> inferred_name =
90
shared_func_info->inferred_name()->ToCString();
91
CHECK_EQ(0, strcmp(ref_inferred_name, inferred_name.get()));
95
static v8::Handle<v8::Script> Compile(v8::Isolate* isolate, const char* src) {
96
return v8::Script::Compile(v8::String::NewFromUtf8(isolate, src));
100
TEST(GlobalProperty) {
101
CcTest::InitializeVM();
102
v8::HandleScope scope(CcTest::isolate());
104
v8::Handle<v8::Script> script = Compile(
106
"fun1 = function() { return 1; }\n"
107
"fun2 = function() { return 2; }\n");
108
CheckFunctionName(script, "return 1", "fun1");
109
CheckFunctionName(script, "return 2", "fun2");
114
CcTest::InitializeVM();
115
v8::HandleScope scope(CcTest::isolate());
117
v8::Handle<v8::Script> script = Compile(
119
"var fun1 = function() { return 1; }\n"
120
"var fun2 = function() { return 2; }\n");
121
CheckFunctionName(script, "return 1", "fun1");
122
CheckFunctionName(script, "return 2", "fun2");
127
CcTest::InitializeVM();
128
v8::HandleScope scope(CcTest::isolate());
130
v8::Handle<v8::Script> script = Compile(
132
"function outer() {\n"
133
" var fun1 = function() { return 1; }\n"
134
" var fun2 = function() { return 2; }\n"
136
CheckFunctionName(script, "return 1", "fun1");
137
CheckFunctionName(script, "return 2", "fun2");
141
TEST(InConstructor) {
142
CcTest::InitializeVM();
143
v8::HandleScope scope(CcTest::isolate());
145
v8::Handle<v8::Script> script = Compile(
147
"function MyClass() {\n"
148
" this.method1 = function() { return 1; }\n"
149
" this.method2 = function() { return 2; }\n"
151
CheckFunctionName(script, "return 1", "MyClass.method1");
152
CheckFunctionName(script, "return 2", "MyClass.method2");
157
CcTest::InitializeVM();
158
v8::HandleScope scope(CcTest::isolate());
160
v8::Handle<v8::Script> script = Compile(
162
"function createMyObj() {\n"
164
" obj.method1 = function() { return 1; }\n"
165
" obj.method2 = function() { return 2; }\n"
168
CheckFunctionName(script, "return 1", "obj.method1");
169
CheckFunctionName(script, "return 2", "obj.method2");
174
CcTest::InitializeVM();
175
v8::HandleScope scope(CcTest::isolate());
177
v8::Handle<v8::Script> script = Compile(
179
"function MyClass() {}\n"
180
"MyClass.static1 = function() { return 1; }\n"
181
"MyClass.static2 = function() { return 2; }\n"
182
"MyClass.MyInnerClass = {}\n"
183
"MyClass.MyInnerClass.static3 = function() { return 3; }\n"
184
"MyClass.MyInnerClass.static4 = function() { return 4; }");
185
CheckFunctionName(script, "return 1", "MyClass.static1");
186
CheckFunctionName(script, "return 2", "MyClass.static2");
187
CheckFunctionName(script, "return 3", "MyClass.MyInnerClass.static3");
188
CheckFunctionName(script, "return 4", "MyClass.MyInnerClass.static4");
193
CcTest::InitializeVM();
194
v8::HandleScope scope(CcTest::isolate());
196
v8::Handle<v8::Script> script = Compile(
198
"function MyClass() {}\n"
199
"MyClass.prototype.method1 = function() { return 1; }\n"
200
"MyClass.prototype.method2 = function() { return 2; }\n"
201
"MyClass.MyInnerClass = function() {}\n"
202
"MyClass.MyInnerClass.prototype.method3 = function() { return 3; }\n"
203
"MyClass.MyInnerClass.prototype.method4 = function() { return 4; }");
204
CheckFunctionName(script, "return 1", "MyClass.method1");
205
CheckFunctionName(script, "return 2", "MyClass.method2");
206
CheckFunctionName(script, "return 3", "MyClass.MyInnerClass.method3");
207
CheckFunctionName(script, "return 4", "MyClass.MyInnerClass.method4");
211
TEST(ObjectLiteral) {
212
CcTest::InitializeVM();
213
v8::HandleScope scope(CcTest::isolate());
215
v8::Handle<v8::Script> script = Compile(
217
"function MyClass() {}\n"
218
"MyClass.prototype = {\n"
219
" method1: function() { return 1; },\n"
220
" method2: function() { return 2; } }");
221
CheckFunctionName(script, "return 1", "MyClass.method1");
222
CheckFunctionName(script, "return 2", "MyClass.method2");
227
CcTest::InitializeVM();
228
v8::HandleScope scope(CcTest::isolate());
230
v8::Handle<v8::Script> script = Compile(
232
"function f1(a) { return a(); }\n"
233
"function f2(a, b) { return a() + b(); }\n"
234
"var result1 = f1(function() { return 1; })\n"
235
"var result2 = f2(function() { return 2; }, function() { return 3; })");
236
// Can't infer names here.
237
CheckFunctionName(script, "return 1", "");
238
CheckFunctionName(script, "return 2", "");
239
CheckFunctionName(script, "return 3", "");
243
TEST(MultipleFuncsConditional) {
244
CcTest::InitializeVM();
245
v8::HandleScope scope(CcTest::isolate());
247
v8::Handle<v8::Script> script = Compile(
250
" function() { return 1; } :\n"
251
" function() { return 2; }");
252
CheckFunctionName(script, "return 1", "fun1");
253
CheckFunctionName(script, "return 2", "fun1");
257
TEST(MultipleFuncsInLiteral) {
258
CcTest::InitializeVM();
259
v8::HandleScope scope(CcTest::isolate());
261
v8::Handle<v8::Script> script = Compile(
263
"function MyClass() {}\n"
264
"MyClass.prototype = {\n"
265
" method1: 0 ? function() { return 1; } :\n"
266
" function() { return 2; } }");
267
CheckFunctionName(script, "return 1", "MyClass.method1");
268
CheckFunctionName(script, "return 2", "MyClass.method1");
272
TEST(AnonymousInAnonymousClosure1) {
273
CcTest::InitializeVM();
274
v8::HandleScope scope(CcTest::isolate());
276
v8::Handle<v8::Script> script = Compile(
283
" var b = function() {\n"
288
CheckFunctionName(script, "return", "");
292
TEST(AnonymousInAnonymousClosure2) {
293
CcTest::InitializeVM();
294
v8::HandleScope scope(CcTest::isolate());
296
v8::Handle<v8::Script> script = Compile(
305
CheckFunctionName(script, "return", "");
309
TEST(NamedInAnonymousClosure) {
310
CcTest::InitializeVM();
311
v8::HandleScope scope(CcTest::isolate());
313
v8::Handle<v8::Script> script = Compile(
315
"var foo = function() {\n"
316
" (function named() {\n"
322
CheckFunctionName(script, "return", "foo");
326
// See http://code.google.com/p/v8/issues/detail?id=380
328
CcTest::InitializeVM();
329
v8::HandleScope scope(CcTest::isolate());
331
v8::Handle<v8::Script> script = Compile(
334
"var result = function(p,a,c,k,e,d)"
335
"{return p}(\"if blah blah\",62,1976,\'a|b\'.split(\'|\'),0,{})\n"
337
CheckFunctionName(script, "return p", "");
341
TEST(MultipleAssignments) {
342
CcTest::InitializeVM();
343
v8::HandleScope scope(CcTest::isolate());
345
v8::Handle<v8::Script> script = Compile(
347
"var fun1 = fun2 = function () { return 1; }\n"
348
"var bar1 = bar2 = bar3 = function () { return 2; }\n"
349
"foo1 = foo2 = function () { return 3; }\n"
350
"baz1 = baz2 = baz3 = function () { return 4; }");
351
CheckFunctionName(script, "return 1", "fun2");
352
CheckFunctionName(script, "return 2", "bar3");
353
CheckFunctionName(script, "return 3", "foo2");
354
CheckFunctionName(script, "return 4", "baz3");
358
TEST(AsConstructorParameter) {
359
CcTest::InitializeVM();
360
v8::HandleScope scope(CcTest::isolate());
362
v8::Handle<v8::Script> script = Compile(
364
"function Foo() {}\n"
365
"var foo = new Foo(function() { return 1; })\n"
366
"var bar = new Foo(function() { return 2; }, function() { return 3; })");
367
CheckFunctionName(script, "return 1", "");
368
CheckFunctionName(script, "return 2", "");
369
CheckFunctionName(script, "return 3", "");
373
TEST(FactoryHashmap) {
374
CcTest::InitializeVM();
375
v8::HandleScope scope(CcTest::isolate());
377
v8::Handle<v8::Script> script = Compile(
379
"function createMyObj() {\n"
381
" obj[\"method1\"] = function() { return 1; }\n"
382
" obj[\"method2\"] = function() { return 2; }\n"
385
CheckFunctionName(script, "return 1", "obj.method1");
386
CheckFunctionName(script, "return 2", "obj.method2");
390
TEST(FactoryHashmapVariable) {
391
CcTest::InitializeVM();
392
v8::HandleScope scope(CcTest::isolate());
394
v8::Handle<v8::Script> script = Compile(
396
"function createMyObj() {\n"
398
" var methodName = \"method1\";\n"
399
" obj[methodName] = function() { return 1; }\n"
400
" methodName = \"method2\";\n"
401
" obj[methodName] = function() { return 2; }\n"
404
// Can't infer function names statically.
405
CheckFunctionName(script, "return 1", "obj.(anonymous function)");
406
CheckFunctionName(script, "return 2", "obj.(anonymous function)");
410
TEST(FactoryHashmapConditional) {
411
CcTest::InitializeVM();
412
v8::HandleScope scope(CcTest::isolate());
414
v8::Handle<v8::Script> script = Compile(
416
"function createMyObj() {\n"
418
" obj[0 ? \"method1\" : \"method2\"] = function() { return 1; }\n"
421
// Can't infer the function name statically.
422
CheckFunctionName(script, "return 1", "obj.(anonymous function)");
426
TEST(GlobalAssignmentAndCall) {
427
CcTest::InitializeVM();
428
v8::HandleScope scope(CcTest::isolate());
430
v8::Handle<v8::Script> script = Compile(
432
"var Foo = function() {\n"
435
"var Baz = Bar = function() {\n"
438
// The inferred name is empty, because this is an assignment of a result.
439
CheckFunctionName(script, "return 1", "");
440
// See MultipleAssignments test.
441
CheckFunctionName(script, "return 2", "Bar");
445
TEST(AssignmentAndCall) {
446
CcTest::InitializeVM();
447
v8::HandleScope scope(CcTest::isolate());
449
v8::Handle<v8::Script> script = Compile(
451
"(function Enclosing() {\n"
453
" Foo = function() {\n"
456
" var Baz = Bar = function() {\n"
460
// The inferred name is empty, because this is an assignment of a result.
461
CheckFunctionName(script, "return 1", "");
462
// See MultipleAssignments test.
463
// TODO(2276): Lazy compiling the enclosing outer closure would yield
464
// in "Enclosing.Bar" being the inferred name here.
465
CheckFunctionName(script, "return 2", "Bar");
469
TEST(MethodAssignmentInAnonymousFunctionCall) {
470
CcTest::InitializeVM();
471
v8::HandleScope scope(CcTest::isolate());
473
v8::Handle<v8::Script> script = Compile(
476
" var EventSource = function () { };\n"
477
" EventSource.prototype.addListener = function () {\n"
480
" this.PublicEventSource = EventSource;\n"
482
CheckFunctionName(script, "return 2012", "EventSource.addListener");
486
TEST(ReturnAnonymousFunction) {
487
CcTest::InitializeVM();
488
v8::HandleScope scope(CcTest::isolate());
490
v8::Handle<v8::Script> script = Compile(
493
" function wrapCode() {\n"
494
" return function () {\n"
500
" return wrapCode();\n"
505
CheckFunctionName(script, "return 2012", "");