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 Object* shared_func_info_ptr =
85 isolate->debug()->FindSharedFunctionInfoInScript(i_script, func_pos);
86 CHECK(shared_func_info_ptr != CcTest::heap()->undefined_value());
87 Handle<SharedFunctionInfo> shared_func_info(
88 SharedFunctionInfo::cast(shared_func_info_ptr));
90 // Verify inferred function name.
91 SmartArrayPointer<char> inferred_name =
92 shared_func_info->inferred_name()->ToCString();
93 CHECK_EQ(0, strcmp(ref_inferred_name, inferred_name.get()));
97 static v8::Handle<v8::Script> Compile(v8::Isolate* isolate, const char* src) {
98 return v8::Script::Compile(v8::String::NewFromUtf8(isolate, src));
102 TEST(GlobalProperty) {
103 CcTest::InitializeVM();
104 v8::HandleScope scope(CcTest::isolate());
106 v8::Handle<v8::Script> script = Compile(
108 "fun1 = function() { return 1; }\n"
109 "fun2 = function() { return 2; }\n");
110 CheckFunctionName(script, "return 1", "fun1");
111 CheckFunctionName(script, "return 2", "fun2");
116 CcTest::InitializeVM();
117 v8::HandleScope scope(CcTest::isolate());
119 v8::Handle<v8::Script> script = Compile(
121 "var fun1 = function() { return 1; }\n"
122 "var fun2 = function() { return 2; }\n");
123 CheckFunctionName(script, "return 1", "fun1");
124 CheckFunctionName(script, "return 2", "fun2");
129 CcTest::InitializeVM();
130 v8::HandleScope scope(CcTest::isolate());
132 v8::Handle<v8::Script> script = Compile(
134 "function outer() {\n"
135 " var fun1 = function() { return 1; }\n"
136 " var fun2 = function() { return 2; }\n"
138 CheckFunctionName(script, "return 1", "fun1");
139 CheckFunctionName(script, "return 2", "fun2");
143 TEST(InConstructor) {
144 CcTest::InitializeVM();
145 v8::HandleScope scope(CcTest::isolate());
147 v8::Handle<v8::Script> script = Compile(
149 "function MyClass() {\n"
150 " this.method1 = function() { return 1; }\n"
151 " this.method2 = function() { return 2; }\n"
153 CheckFunctionName(script, "return 1", "MyClass.method1");
154 CheckFunctionName(script, "return 2", "MyClass.method2");
159 CcTest::InitializeVM();
160 v8::HandleScope scope(CcTest::isolate());
162 v8::Handle<v8::Script> script = Compile(
164 "function createMyObj() {\n"
166 " obj.method1 = function() { return 1; }\n"
167 " obj.method2 = function() { return 2; }\n"
170 CheckFunctionName(script, "return 1", "obj.method1");
171 CheckFunctionName(script, "return 2", "obj.method2");
176 CcTest::InitializeVM();
177 v8::HandleScope scope(CcTest::isolate());
179 v8::Handle<v8::Script> script = Compile(
181 "function MyClass() {}\n"
182 "MyClass.static1 = function() { return 1; }\n"
183 "MyClass.static2 = function() { return 2; }\n"
184 "MyClass.MyInnerClass = {}\n"
185 "MyClass.MyInnerClass.static3 = function() { return 3; }\n"
186 "MyClass.MyInnerClass.static4 = function() { return 4; }");
187 CheckFunctionName(script, "return 1", "MyClass.static1");
188 CheckFunctionName(script, "return 2", "MyClass.static2");
189 CheckFunctionName(script, "return 3", "MyClass.MyInnerClass.static3");
190 CheckFunctionName(script, "return 4", "MyClass.MyInnerClass.static4");
195 CcTest::InitializeVM();
196 v8::HandleScope scope(CcTest::isolate());
198 v8::Handle<v8::Script> script = Compile(
200 "function MyClass() {}\n"
201 "MyClass.prototype.method1 = function() { return 1; }\n"
202 "MyClass.prototype.method2 = function() { return 2; }\n"
203 "MyClass.MyInnerClass = function() {}\n"
204 "MyClass.MyInnerClass.prototype.method3 = function() { return 3; }\n"
205 "MyClass.MyInnerClass.prototype.method4 = function() { return 4; }");
206 CheckFunctionName(script, "return 1", "MyClass.method1");
207 CheckFunctionName(script, "return 2", "MyClass.method2");
208 CheckFunctionName(script, "return 3", "MyClass.MyInnerClass.method3");
209 CheckFunctionName(script, "return 4", "MyClass.MyInnerClass.method4");
213 TEST(ObjectLiteral) {
214 CcTest::InitializeVM();
215 v8::HandleScope scope(CcTest::isolate());
217 v8::Handle<v8::Script> script = Compile(
219 "function MyClass() {}\n"
220 "MyClass.prototype = {\n"
221 " method1: function() { return 1; },\n"
222 " method2: function() { return 2; } }");
223 CheckFunctionName(script, "return 1", "MyClass.method1");
224 CheckFunctionName(script, "return 2", "MyClass.method2");
229 CcTest::InitializeVM();
230 v8::HandleScope scope(CcTest::isolate());
232 v8::Handle<v8::Script> script = Compile(
234 "function f1(a) { return a(); }\n"
235 "function f2(a, b) { return a() + b(); }\n"
236 "var result1 = f1(function() { return 1; })\n"
237 "var result2 = f2(function() { return 2; }, function() { return 3; })");
238 // Can't infer names here.
239 CheckFunctionName(script, "return 1", "");
240 CheckFunctionName(script, "return 2", "");
241 CheckFunctionName(script, "return 3", "");
245 TEST(MultipleFuncsConditional) {
246 CcTest::InitializeVM();
247 v8::HandleScope scope(CcTest::isolate());
249 v8::Handle<v8::Script> script = Compile(
252 " function() { return 1; } :\n"
253 " function() { return 2; }");
254 CheckFunctionName(script, "return 1", "fun1");
255 CheckFunctionName(script, "return 2", "fun1");
259 TEST(MultipleFuncsInLiteral) {
260 CcTest::InitializeVM();
261 v8::HandleScope scope(CcTest::isolate());
263 v8::Handle<v8::Script> script = Compile(
265 "function MyClass() {}\n"
266 "MyClass.prototype = {\n"
267 " method1: 0 ? function() { return 1; } :\n"
268 " function() { return 2; } }");
269 CheckFunctionName(script, "return 1", "MyClass.method1");
270 CheckFunctionName(script, "return 2", "MyClass.method1");
274 TEST(AnonymousInAnonymousClosure1) {
275 CcTest::InitializeVM();
276 v8::HandleScope scope(CcTest::isolate());
278 v8::Handle<v8::Script> script = Compile(
285 " var b = function() {\n"
290 CheckFunctionName(script, "return", "");
294 TEST(AnonymousInAnonymousClosure2) {
295 CcTest::InitializeVM();
296 v8::HandleScope scope(CcTest::isolate());
298 v8::Handle<v8::Script> script = Compile(
307 CheckFunctionName(script, "return", "");
311 TEST(NamedInAnonymousClosure) {
312 CcTest::InitializeVM();
313 v8::HandleScope scope(CcTest::isolate());
315 v8::Handle<v8::Script> script = Compile(
317 "var foo = function() {\n"
318 " (function named() {\n"
324 CheckFunctionName(script, "return", "foo");
328 // See http://code.google.com/p/v8/issues/detail?id=380
330 CcTest::InitializeVM();
331 v8::HandleScope scope(CcTest::isolate());
333 v8::Handle<v8::Script> script = Compile(
336 "var result = function(p,a,c,k,e,d)"
337 "{return p}(\"if blah blah\",62,1976,\'a|b\'.split(\'|\'),0,{})\n"
339 CheckFunctionName(script, "return p", "");
343 TEST(MultipleAssignments) {
344 CcTest::InitializeVM();
345 v8::HandleScope scope(CcTest::isolate());
347 v8::Handle<v8::Script> script = Compile(
349 "var fun1 = fun2 = function () { return 1; }\n"
350 "var bar1 = bar2 = bar3 = function () { return 2; }\n"
351 "foo1 = foo2 = function () { return 3; }\n"
352 "baz1 = baz2 = baz3 = function () { return 4; }");
353 CheckFunctionName(script, "return 1", "fun2");
354 CheckFunctionName(script, "return 2", "bar3");
355 CheckFunctionName(script, "return 3", "foo2");
356 CheckFunctionName(script, "return 4", "baz3");
360 TEST(AsConstructorParameter) {
361 CcTest::InitializeVM();
362 v8::HandleScope scope(CcTest::isolate());
364 v8::Handle<v8::Script> script = Compile(
366 "function Foo() {}\n"
367 "var foo = new Foo(function() { return 1; })\n"
368 "var bar = new Foo(function() { return 2; }, function() { return 3; })");
369 CheckFunctionName(script, "return 1", "");
370 CheckFunctionName(script, "return 2", "");
371 CheckFunctionName(script, "return 3", "");
375 TEST(FactoryHashmap) {
376 CcTest::InitializeVM();
377 v8::HandleScope scope(CcTest::isolate());
379 v8::Handle<v8::Script> script = Compile(
381 "function createMyObj() {\n"
383 " obj[\"method1\"] = function() { return 1; }\n"
384 " obj[\"method2\"] = function() { return 2; }\n"
387 CheckFunctionName(script, "return 1", "obj.method1");
388 CheckFunctionName(script, "return 2", "obj.method2");
392 TEST(FactoryHashmapVariable) {
393 CcTest::InitializeVM();
394 v8::HandleScope scope(CcTest::isolate());
396 v8::Handle<v8::Script> script = Compile(
398 "function createMyObj() {\n"
400 " var methodName = \"method1\";\n"
401 " obj[methodName] = function() { return 1; }\n"
402 " methodName = \"method2\";\n"
403 " obj[methodName] = function() { return 2; }\n"
406 // Can't infer function names statically.
407 CheckFunctionName(script, "return 1", "obj.(anonymous function)");
408 CheckFunctionName(script, "return 2", "obj.(anonymous function)");
412 TEST(FactoryHashmapConditional) {
413 CcTest::InitializeVM();
414 v8::HandleScope scope(CcTest::isolate());
416 v8::Handle<v8::Script> script = Compile(
418 "function createMyObj() {\n"
420 " obj[0 ? \"method1\" : \"method2\"] = function() { return 1; }\n"
423 // Can't infer the function name statically.
424 CheckFunctionName(script, "return 1", "obj.(anonymous function)");
428 TEST(GlobalAssignmentAndCall) {
429 CcTest::InitializeVM();
430 v8::HandleScope scope(CcTest::isolate());
432 v8::Handle<v8::Script> script = Compile(
434 "var Foo = function() {\n"
437 "var Baz = Bar = function() {\n"
440 // The inferred name is empty, because this is an assignment of a result.
441 CheckFunctionName(script, "return 1", "");
442 // See MultipleAssignments test.
443 CheckFunctionName(script, "return 2", "Bar");
447 TEST(AssignmentAndCall) {
448 CcTest::InitializeVM();
449 v8::HandleScope scope(CcTest::isolate());
451 v8::Handle<v8::Script> script = Compile(
453 "(function Enclosing() {\n"
455 " Foo = function() {\n"
458 " var Baz = Bar = function() {\n"
462 // The inferred name is empty, because this is an assignment of a result.
463 CheckFunctionName(script, "return 1", "");
464 // See MultipleAssignments test.
465 // TODO(2276): Lazy compiling the enclosing outer closure would yield
466 // in "Enclosing.Bar" being the inferred name here.
467 CheckFunctionName(script, "return 2", "Bar");
471 TEST(MethodAssignmentInAnonymousFunctionCall) {
472 CcTest::InitializeVM();
473 v8::HandleScope scope(CcTest::isolate());
475 v8::Handle<v8::Script> script = Compile(
478 " var EventSource = function () { };\n"
479 " EventSource.prototype.addListener = function () {\n"
482 " this.PublicEventSource = EventSource;\n"
484 CheckFunctionName(script, "return 2012", "EventSource.addListener");
488 TEST(ReturnAnonymousFunction) {
489 CcTest::InitializeVM();
490 v8::HandleScope scope(CcTest::isolate());
492 v8::Handle<v8::Script> script = Compile(
495 " function wrapCode() {\n"
496 " return function () {\n"
502 " return wrapCode();\n"
507 CheckFunctionName(script, "return 2012", "");