• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/runtime.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  
50  
CheckFunctionName(v8::Handle<v8::Script> script,const char * func_pos_src,const char * ref_inferred_name)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->NewStringFromAsciiChecked(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    // Obtain SharedFunctionInfo for the function.
81    isolate->debug()->PrepareForBreakPoints();
82    Object* shared_func_info_ptr =
83        isolate->debug()->FindSharedFunctionInfoInScript(i_script, func_pos);
84    CHECK(shared_func_info_ptr != CcTest::heap()->undefined_value());
85    Handle<SharedFunctionInfo> shared_func_info(
86        SharedFunctionInfo::cast(shared_func_info_ptr));
87  
88    // Verify inferred function name.
89    SmartArrayPointer<char> inferred_name =
90        shared_func_info->inferred_name()->ToCString();
91    CHECK_EQ(ref_inferred_name, inferred_name.get());
92  }
93  
94  
Compile(v8::Isolate * isolate,const char * src)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  
TEST(GlobalProperty)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  
TEST(GlobalVar)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  
TEST(LocalVar)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  
TEST(InConstructor)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  
TEST(Factory)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  
TEST(Static)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  
TEST(Prototype)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  
TEST(ObjectLiteral)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  
TEST(AsParameter)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  
TEST(MultipleFuncsConditional)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  
TEST(MultipleFuncsInLiteral)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  
TEST(AnonymousInAnonymousClosure1)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  
TEST(AnonymousInAnonymousClosure2)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  
TEST(NamedInAnonymousClosure)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
TEST(Issue380)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  
TEST(MultipleAssignments)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  
TEST(AsConstructorParameter)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  
TEST(FactoryHashmap)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  
TEST(FactoryHashmapVariable)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  
TEST(FactoryHashmapConditional)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  
TEST(GlobalAssignmentAndCall)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  
TEST(AssignmentAndCall)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  
TEST(MethodAssignmentInAnonymousFunctionCall)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  
TEST(ReturnAnonymousFunction)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  }
507