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", "");