deps: update v8 to 4.3.61.21
[platform/upstream/nodejs.git] / deps / v8 / test / cctest / test-func-name-inference.cc
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
4 // met:
5 //
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.
15 //
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.
27
28
29 #include "src/v8.h"
30
31 #include "src/api.h"
32 #include "src/debug.h"
33 #include "src/string-search.h"
34 #include "test/cctest/cctest.h"
35
36
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;
50
51
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();
56
57   // Get script source.
58   Handle<Object> obj = v8::Utils::OpenHandle(*script);
59   Handle<SharedFunctionInfo> shared_function;
60   if (obj->IsSharedFunctionInfo()) {
61     shared_function =
62         Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(*obj));
63   } else {
64     shared_function =
65         Handle<SharedFunctionInfo>(JSFunction::cast(*obj)->shared());
66   }
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()));
70
71   // Find the position of a given func source substring in the source.
72   int func_pos;
73   {
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(),
78                             func_pos_str, 0);
79   }
80   CHECK_NE(0, func_pos);
81
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));
87
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()));
92 }
93
94
95 static v8::Handle<v8::Script> Compile(v8::Isolate* isolate, const char* src) {
96   return v8::Script::Compile(v8::String::NewFromUtf8(isolate, src));
97 }
98
99
100 TEST(GlobalProperty) {
101   CcTest::InitializeVM();
102   v8::HandleScope scope(CcTest::isolate());
103
104   v8::Handle<v8::Script> script = Compile(
105       CcTest::isolate(),
106       "fun1 = function() { return 1; }\n"
107       "fun2 = function() { return 2; }\n");
108   CheckFunctionName(script, "return 1", "fun1");
109   CheckFunctionName(script, "return 2", "fun2");
110 }
111
112
113 TEST(GlobalVar) {
114   CcTest::InitializeVM();
115   v8::HandleScope scope(CcTest::isolate());
116
117   v8::Handle<v8::Script> script = Compile(
118       CcTest::isolate(),
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");
123 }
124
125
126 TEST(LocalVar) {
127   CcTest::InitializeVM();
128   v8::HandleScope scope(CcTest::isolate());
129
130   v8::Handle<v8::Script> script = Compile(
131       CcTest::isolate(),
132       "function outer() {\n"
133       "  var fun1 = function() { return 1; }\n"
134       "  var fun2 = function() { return 2; }\n"
135       "}");
136   CheckFunctionName(script, "return 1", "fun1");
137   CheckFunctionName(script, "return 2", "fun2");
138 }
139
140
141 TEST(InConstructor) {
142   CcTest::InitializeVM();
143   v8::HandleScope scope(CcTest::isolate());
144
145   v8::Handle<v8::Script> script = Compile(
146       CcTest::isolate(),
147       "function MyClass() {\n"
148       "  this.method1 = function() { return 1; }\n"
149       "  this.method2 = function() { return 2; }\n"
150       "}");
151   CheckFunctionName(script, "return 1", "MyClass.method1");
152   CheckFunctionName(script, "return 2", "MyClass.method2");
153 }
154
155
156 TEST(Factory) {
157   CcTest::InitializeVM();
158   v8::HandleScope scope(CcTest::isolate());
159
160   v8::Handle<v8::Script> script = Compile(
161       CcTest::isolate(),
162       "function createMyObj() {\n"
163       "  var obj = {};\n"
164       "  obj.method1 = function() { return 1; }\n"
165       "  obj.method2 = function() { return 2; }\n"
166       "  return obj;\n"
167       "}");
168   CheckFunctionName(script, "return 1", "obj.method1");
169   CheckFunctionName(script, "return 2", "obj.method2");
170 }
171
172
173 TEST(Static) {
174   CcTest::InitializeVM();
175   v8::HandleScope scope(CcTest::isolate());
176
177   v8::Handle<v8::Script> script = Compile(
178       CcTest::isolate(),
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");
189 }
190
191
192 TEST(Prototype) {
193   CcTest::InitializeVM();
194   v8::HandleScope scope(CcTest::isolate());
195
196   v8::Handle<v8::Script> script = Compile(
197       CcTest::isolate(),
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");
208 }
209
210
211 TEST(ObjectLiteral) {
212   CcTest::InitializeVM();
213   v8::HandleScope scope(CcTest::isolate());
214
215   v8::Handle<v8::Script> script = Compile(
216       CcTest::isolate(),
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");
223 }
224
225
226 TEST(AsParameter) {
227   CcTest::InitializeVM();
228   v8::HandleScope scope(CcTest::isolate());
229
230   v8::Handle<v8::Script> script = Compile(
231       CcTest::isolate(),
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", "");
240 }
241
242
243 TEST(MultipleFuncsConditional) {
244   CcTest::InitializeVM();
245   v8::HandleScope scope(CcTest::isolate());
246
247   v8::Handle<v8::Script> script = Compile(
248       CcTest::isolate(),
249       "fun1 = 0 ?\n"
250       "    function() { return 1; } :\n"
251       "    function() { return 2; }");
252   CheckFunctionName(script, "return 1", "fun1");
253   CheckFunctionName(script, "return 2", "fun1");
254 }
255
256
257 TEST(MultipleFuncsInLiteral) {
258   CcTest::InitializeVM();
259   v8::HandleScope scope(CcTest::isolate());
260
261   v8::Handle<v8::Script> script = Compile(
262       CcTest::isolate(),
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");
269 }
270
271
272 TEST(AnonymousInAnonymousClosure1) {
273   CcTest::InitializeVM();
274   v8::HandleScope scope(CcTest::isolate());
275
276   v8::Handle<v8::Script> script = Compile(
277       CcTest::isolate(),
278       "(function() {\n"
279       "  (function() {\n"
280       "      var a = 1;\n"
281       "      return;\n"
282       "  })();\n"
283       "  var b = function() {\n"
284       "      var c = 1;\n"
285       "      return;\n"
286       "  };\n"
287       "})();");
288   CheckFunctionName(script, "return", "");
289 }
290
291
292 TEST(AnonymousInAnonymousClosure2) {
293   CcTest::InitializeVM();
294   v8::HandleScope scope(CcTest::isolate());
295
296   v8::Handle<v8::Script> script = Compile(
297       CcTest::isolate(),
298       "(function() {\n"
299       "  (function() {\n"
300       "      var a = 1;\n"
301       "      return;\n"
302       "  })();\n"
303       "  var c = 1;\n"
304       "})();");
305   CheckFunctionName(script, "return", "");
306 }
307
308
309 TEST(NamedInAnonymousClosure) {
310   CcTest::InitializeVM();
311   v8::HandleScope scope(CcTest::isolate());
312
313   v8::Handle<v8::Script> script = Compile(
314       CcTest::isolate(),
315       "var foo = function() {\n"
316       "  (function named() {\n"
317       "      var a = 1;\n"
318       "  })();\n"
319       "  var c = 1;\n"
320       "  return;\n"
321       "};");
322   CheckFunctionName(script, "return", "foo");
323 }
324
325
326 // See http://code.google.com/p/v8/issues/detail?id=380
327 TEST(Issue380) {
328   CcTest::InitializeVM();
329   v8::HandleScope scope(CcTest::isolate());
330
331   v8::Handle<v8::Script> script = Compile(
332       CcTest::isolate(),
333       "function a() {\n"
334       "var result = function(p,a,c,k,e,d)"
335       "{return p}(\"if blah blah\",62,1976,\'a|b\'.split(\'|\'),0,{})\n"
336       "}");
337   CheckFunctionName(script, "return p", "");
338 }
339
340
341 TEST(MultipleAssignments) {
342   CcTest::InitializeVM();
343   v8::HandleScope scope(CcTest::isolate());
344
345   v8::Handle<v8::Script> script = Compile(
346       CcTest::isolate(),
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");
355 }
356
357
358 TEST(AsConstructorParameter) {
359   CcTest::InitializeVM();
360   v8::HandleScope scope(CcTest::isolate());
361
362   v8::Handle<v8::Script> script = Compile(
363       CcTest::isolate(),
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", "");
370 }
371
372
373 TEST(FactoryHashmap) {
374   CcTest::InitializeVM();
375   v8::HandleScope scope(CcTest::isolate());
376
377   v8::Handle<v8::Script> script = Compile(
378       CcTest::isolate(),
379       "function createMyObj() {\n"
380       "  var obj = {};\n"
381       "  obj[\"method1\"] = function() { return 1; }\n"
382       "  obj[\"method2\"] = function() { return 2; }\n"
383       "  return obj;\n"
384       "}");
385   CheckFunctionName(script, "return 1", "obj.method1");
386   CheckFunctionName(script, "return 2", "obj.method2");
387 }
388
389
390 TEST(FactoryHashmapVariable) {
391   CcTest::InitializeVM();
392   v8::HandleScope scope(CcTest::isolate());
393
394   v8::Handle<v8::Script> script = Compile(
395       CcTest::isolate(),
396       "function createMyObj() {\n"
397       "  var obj = {};\n"
398       "  var methodName = \"method1\";\n"
399       "  obj[methodName] = function() { return 1; }\n"
400       "  methodName = \"method2\";\n"
401       "  obj[methodName] = function() { return 2; }\n"
402       "  return obj;\n"
403       "}");
404   // Can't infer function names statically.
405   CheckFunctionName(script, "return 1", "obj.(anonymous function)");
406   CheckFunctionName(script, "return 2", "obj.(anonymous function)");
407 }
408
409
410 TEST(FactoryHashmapConditional) {
411   CcTest::InitializeVM();
412   v8::HandleScope scope(CcTest::isolate());
413
414   v8::Handle<v8::Script> script = Compile(
415       CcTest::isolate(),
416       "function createMyObj() {\n"
417       "  var obj = {};\n"
418       "  obj[0 ? \"method1\" : \"method2\"] = function() { return 1; }\n"
419       "  return obj;\n"
420       "}");
421   // Can't infer the function name statically.
422   CheckFunctionName(script, "return 1", "obj.(anonymous function)");
423 }
424
425
426 TEST(GlobalAssignmentAndCall) {
427   CcTest::InitializeVM();
428   v8::HandleScope scope(CcTest::isolate());
429
430   v8::Handle<v8::Script> script = Compile(
431       CcTest::isolate(),
432       "var Foo = function() {\n"
433       "  return 1;\n"
434       "}();\n"
435       "var Baz = Bar = function() {\n"
436       "  return 2;\n"
437       "}");
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");
442 }
443
444
445 TEST(AssignmentAndCall) {
446   CcTest::InitializeVM();
447   v8::HandleScope scope(CcTest::isolate());
448
449   v8::Handle<v8::Script> script = Compile(
450       CcTest::isolate(),
451       "(function Enclosing() {\n"
452       "  var Foo;\n"
453       "  Foo = function() {\n"
454       "    return 1;\n"
455       "  }();\n"
456       "  var Baz = Bar = function() {\n"
457       "    return 2;\n"
458       "  }\n"
459       "})();");
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");
466 }
467
468
469 TEST(MethodAssignmentInAnonymousFunctionCall) {
470   CcTest::InitializeVM();
471   v8::HandleScope scope(CcTest::isolate());
472
473   v8::Handle<v8::Script> script = Compile(
474       CcTest::isolate(),
475       "(function () {\n"
476       "    var EventSource = function () { };\n"
477       "    EventSource.prototype.addListener = function () {\n"
478       "        return 2012;\n"
479       "    };\n"
480       "    this.PublicEventSource = EventSource;\n"
481       "})();");
482   CheckFunctionName(script, "return 2012", "EventSource.addListener");
483 }
484
485
486 TEST(ReturnAnonymousFunction) {
487   CcTest::InitializeVM();
488   v8::HandleScope scope(CcTest::isolate());
489
490   v8::Handle<v8::Script> script = Compile(
491       CcTest::isolate(),
492       "(function() {\n"
493       "  function wrapCode() {\n"
494       "    return function () {\n"
495       "      return 2012;\n"
496       "    };\n"
497       "  };\n"
498       "  var foo = 10;\n"
499       "  function f() {\n"
500       "    return wrapCode();\n"
501       "  }\n"
502       "  this.ref = f;\n"
503       "})()");
504   script->Run();
505   CheckFunctionName(script, "return 2012", "");
506 }