v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
test-func-name-inference.cc
Go to the documentation of this file.
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 "v8.h"
30 
31 #include "api.h"
32 #include "debug.h"
33 #include "runtime.h"
34 #include "cctest.h"
35 
36 
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;
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 
50 
51 static void CheckFunctionName(v8::Handle<v8::Script> script,
52  const char* func_pos_src,
53  const char* ref_inferred_name) {
54  Isolate* isolate = CcTest::i_isolate();
55  Factory* factory = isolate->factory();
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  Handle<String> func_pos_str =
73  factory->NewStringFromAscii(CStrVector(func_pos_src));
74  int func_pos = Runtime::StringMatch(isolate,
75  script_src,
76  func_pos_str,
77  0);
78  CHECK_NE(0, func_pos);
79 
80 #ifdef ENABLE_DEBUGGER_SUPPORT
81  // Obtain SharedFunctionInfo for the function.
82  isolate->debug()->PrepareForBreakPoints();
83  Object* shared_func_info_ptr =
84  isolate->debug()->FindSharedFunctionInfoInScript(i_script, func_pos);
85  CHECK(shared_func_info_ptr != CcTest::heap()->undefined_value());
86  Handle<SharedFunctionInfo> shared_func_info(
87  SharedFunctionInfo::cast(shared_func_info_ptr));
88 
89  // Verify inferred function name.
90  SmartArrayPointer<char> inferred_name =
91  shared_func_info->inferred_name()->ToCString();
92  CHECK_EQ(ref_inferred_name, inferred_name.get());
93 #endif // ENABLE_DEBUGGER_SUPPORT
94 }
95 
96 
97 static v8::Handle<v8::Script> Compile(v8::Isolate* isolate, const char* src) {
98  return v8::Script::Compile(v8::String::NewFromUtf8(isolate, src));
99 }
100 
101 
102 TEST(GlobalProperty) {
105 
106  v8::Handle<v8::Script> script = Compile(
107  CcTest::isolate(),
108  "fun1 = function() { return 1; }\n"
109  "fun2 = function() { return 2; }\n");
110  CheckFunctionName(script, "return 1", "fun1");
111  CheckFunctionName(script, "return 2", "fun2");
112 }
113 
114 
115 TEST(GlobalVar) {
118 
119  v8::Handle<v8::Script> script = Compile(
120  CcTest::isolate(),
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");
125 }
126 
127 
128 TEST(LocalVar) {
131 
132  v8::Handle<v8::Script> script = Compile(
133  CcTest::isolate(),
134  "function outer() {\n"
135  " var fun1 = function() { return 1; }\n"
136  " var fun2 = function() { return 2; }\n"
137  "}");
138  CheckFunctionName(script, "return 1", "fun1");
139  CheckFunctionName(script, "return 2", "fun2");
140 }
141 
142 
143 TEST(InConstructor) {
146 
147  v8::Handle<v8::Script> script = Compile(
148  CcTest::isolate(),
149  "function MyClass() {\n"
150  " this.method1 = function() { return 1; }\n"
151  " this.method2 = function() { return 2; }\n"
152  "}");
153  CheckFunctionName(script, "return 1", "MyClass.method1");
154  CheckFunctionName(script, "return 2", "MyClass.method2");
155 }
156 
157 
158 TEST(Factory) {
161 
162  v8::Handle<v8::Script> script = Compile(
163  CcTest::isolate(),
164  "function createMyObj() {\n"
165  " var obj = {};\n"
166  " obj.method1 = function() { return 1; }\n"
167  " obj.method2 = function() { return 2; }\n"
168  " return obj;\n"
169  "}");
170  CheckFunctionName(script, "return 1", "obj.method1");
171  CheckFunctionName(script, "return 2", "obj.method2");
172 }
173 
174 
175 TEST(Static) {
178 
179  v8::Handle<v8::Script> script = Compile(
180  CcTest::isolate(),
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");
191 }
192 
193 
194 TEST(Prototype) {
197 
198  v8::Handle<v8::Script> script = Compile(
199  CcTest::isolate(),
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");
210 }
211 
212 
213 TEST(ObjectLiteral) {
216 
217  v8::Handle<v8::Script> script = Compile(
218  CcTest::isolate(),
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");
225 }
226 
227 
228 TEST(AsParameter) {
231 
232  v8::Handle<v8::Script> script = Compile(
233  CcTest::isolate(),
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", "");
242 }
243 
244 
245 TEST(MultipleFuncsConditional) {
248 
249  v8::Handle<v8::Script> script = Compile(
250  CcTest::isolate(),
251  "fun1 = 0 ?\n"
252  " function() { return 1; } :\n"
253  " function() { return 2; }");
254  CheckFunctionName(script, "return 1", "fun1");
255  CheckFunctionName(script, "return 2", "fun1");
256 }
257 
258 
259 TEST(MultipleFuncsInLiteral) {
262 
263  v8::Handle<v8::Script> script = Compile(
264  CcTest::isolate(),
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");
271 }
272 
273 
274 TEST(AnonymousInAnonymousClosure1) {
277 
278  v8::Handle<v8::Script> script = Compile(
279  CcTest::isolate(),
280  "(function() {\n"
281  " (function() {\n"
282  " var a = 1;\n"
283  " return;\n"
284  " })();\n"
285  " var b = function() {\n"
286  " var c = 1;\n"
287  " return;\n"
288  " };\n"
289  "})();");
290  CheckFunctionName(script, "return", "");
291 }
292 
293 
294 TEST(AnonymousInAnonymousClosure2) {
297 
298  v8::Handle<v8::Script> script = Compile(
299  CcTest::isolate(),
300  "(function() {\n"
301  " (function() {\n"
302  " var a = 1;\n"
303  " return;\n"
304  " })();\n"
305  " var c = 1;\n"
306  "})();");
307  CheckFunctionName(script, "return", "");
308 }
309 
310 
311 TEST(NamedInAnonymousClosure) {
314 
315  v8::Handle<v8::Script> script = Compile(
316  CcTest::isolate(),
317  "var foo = function() {\n"
318  " (function named() {\n"
319  " var a = 1;\n"
320  " })();\n"
321  " var c = 1;\n"
322  " return;\n"
323  "};");
324  CheckFunctionName(script, "return", "foo");
325 }
326 
327 
328 // See http://code.google.com/p/v8/issues/detail?id=380
329 TEST(Issue380) {
332 
333  v8::Handle<v8::Script> script = Compile(
334  CcTest::isolate(),
335  "function a() {\n"
336  "var result = function(p,a,c,k,e,d)"
337  "{return p}(\"if blah blah\",62,1976,\'a|b\'.split(\'|\'),0,{})\n"
338  "}");
339  CheckFunctionName(script, "return p", "");
340 }
341 
342 
343 TEST(MultipleAssignments) {
346 
347  v8::Handle<v8::Script> script = Compile(
348  CcTest::isolate(),
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");
357 }
358 
359 
360 TEST(AsConstructorParameter) {
363 
364  v8::Handle<v8::Script> script = Compile(
365  CcTest::isolate(),
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", "");
372 }
373 
374 
375 TEST(FactoryHashmap) {
378 
379  v8::Handle<v8::Script> script = Compile(
380  CcTest::isolate(),
381  "function createMyObj() {\n"
382  " var obj = {};\n"
383  " obj[\"method1\"] = function() { return 1; }\n"
384  " obj[\"method2\"] = function() { return 2; }\n"
385  " return obj;\n"
386  "}");
387  CheckFunctionName(script, "return 1", "obj.method1");
388  CheckFunctionName(script, "return 2", "obj.method2");
389 }
390 
391 
392 TEST(FactoryHashmapVariable) {
395 
396  v8::Handle<v8::Script> script = Compile(
397  CcTest::isolate(),
398  "function createMyObj() {\n"
399  " var obj = {};\n"
400  " var methodName = \"method1\";\n"
401  " obj[methodName] = function() { return 1; }\n"
402  " methodName = \"method2\";\n"
403  " obj[methodName] = function() { return 2; }\n"
404  " return obj;\n"
405  "}");
406  // Can't infer function names statically.
407  CheckFunctionName(script, "return 1", "obj.(anonymous function)");
408  CheckFunctionName(script, "return 2", "obj.(anonymous function)");
409 }
410 
411 
412 TEST(FactoryHashmapConditional) {
415 
416  v8::Handle<v8::Script> script = Compile(
417  CcTest::isolate(),
418  "function createMyObj() {\n"
419  " var obj = {};\n"
420  " obj[0 ? \"method1\" : \"method2\"] = function() { return 1; }\n"
421  " return obj;\n"
422  "}");
423  // Can't infer the function name statically.
424  CheckFunctionName(script, "return 1", "obj.(anonymous function)");
425 }
426 
427 
428 TEST(GlobalAssignmentAndCall) {
431 
432  v8::Handle<v8::Script> script = Compile(
433  CcTest::isolate(),
434  "var Foo = function() {\n"
435  " return 1;\n"
436  "}();\n"
437  "var Baz = Bar = function() {\n"
438  " return 2;\n"
439  "}");
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");
444 }
445 
446 
447 TEST(AssignmentAndCall) {
450 
451  v8::Handle<v8::Script> script = Compile(
452  CcTest::isolate(),
453  "(function Enclosing() {\n"
454  " var Foo;\n"
455  " Foo = function() {\n"
456  " return 1;\n"
457  " }();\n"
458  " var Baz = Bar = function() {\n"
459  " return 2;\n"
460  " }\n"
461  "})();");
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");
468 }
469 
470 
471 TEST(MethodAssignmentInAnonymousFunctionCall) {
474 
475  v8::Handle<v8::Script> script = Compile(
476  CcTest::isolate(),
477  "(function () {\n"
478  " var EventSource = function () { };\n"
479  " EventSource.prototype.addListener = function () {\n"
480  " return 2012;\n"
481  " };\n"
482  " this.PublicEventSource = EventSource;\n"
483  "})();");
484  CheckFunctionName(script, "return 2012", "EventSource.addListener");
485 }
486 
487 
488 TEST(ReturnAnonymousFunction) {
491 
492  v8::Handle<v8::Script> script = Compile(
493  CcTest::isolate(),
494  "(function() {\n"
495  " function wrapCode() {\n"
496  " return function () {\n"
497  " return 2012;\n"
498  " };\n"
499  " };\n"
500  " var foo = 10;\n"
501  " function f() {\n"
502  " return wrapCode();\n"
503  " }\n"
504  " this.ref = f;\n"
505  "})()");
506  script->Run();
507  CheckFunctionName(script, "return 2012", "");
508 }
#define CHECK_EQ(expected, value)
Definition: checks.h:252
kSerializedDataOffset Object
Definition: objects-inl.h:5016
static i::Heap * heap()
Definition: cctest.h:106
#define CHECK(condition)
Definition: checks.h:75
TEST(GlobalProperty)
static Local< Script > Compile(Handle< String > source, ScriptOrigin *origin=NULL, ScriptData *script_data=NULL)
Definition: api.cc:1832
static i::Isolate * i_isolate()
Definition: cctest.h:102
static v8::internal::Handle< To > OpenHandle(v8::Local< From > handle)
Definition: api.h:308
#define CHECK_NE(unexpected, value)
Definition: checks.h:256
Vector< const char > CStrVector(const char *data)
Definition: utils.h:574
static void InitializeVM()
Definition: cctest.h:116
Local< Value > Run()
Definition: api.cc:1686
HeapObject * obj
static v8::Isolate * isolate()
Definition: cctest.h:96
static Local< String > NewFromUtf8(Isolate *isolate, const char *data, NewStringType type=kNormalString, int length=-1)
Definition: api.cc:5417