v8  3.14.5(node0.10.28)
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 #include "v8.h"
29 
30 #include "api.h"
31 #include "debug.h"
32 #include "runtime.h"
33 #include "cctest.h"
34 
35 
37 using ::v8::internal::Factory;
38 using ::v8::internal::Handle;
39 using ::v8::internal::Heap;
40 using ::v8::internal::Isolate;
41 using ::v8::internal::JSFunction;
43 using ::v8::internal::Runtime;
44 using ::v8::internal::Script;
45 using ::v8::internal::SmartArrayPointer;
46 using ::v8::internal::SharedFunctionInfo;
47 using ::v8::internal::String;
48 
49 
51 
52 
53 static void InitializeVM() {
54  if (env.IsEmpty()) {
55  v8::HandleScope scope;
56  env = v8::Context::New();
57  }
58  v8::HandleScope scope;
59  env->Enter();
60 }
61 
62 
63 static void CheckFunctionName(v8::Handle<v8::Script> script,
64  const char* func_pos_src,
65  const char* ref_inferred_name) {
66  // Get script source.
67  Handle<Object> obj = v8::Utils::OpenHandle(*script);
68  Handle<SharedFunctionInfo> shared_function;
69  if (obj->IsSharedFunctionInfo()) {
70  shared_function =
71  Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(*obj));
72  } else {
73  shared_function =
74  Handle<SharedFunctionInfo>(JSFunction::cast(*obj)->shared());
75  }
76  Handle<Script> i_script(Script::cast(shared_function->script()));
77  CHECK(i_script->source()->IsString());
78  Handle<String> script_src(String::cast(i_script->source()));
79 
80  // Find the position of a given func source substring in the source.
81  Handle<String> func_pos_str =
82  FACTORY->NewStringFromAscii(CStrVector(func_pos_src));
83  int func_pos = Runtime::StringMatch(Isolate::Current(),
84  script_src,
85  func_pos_str,
86  0);
87  CHECK_NE(0, func_pos);
88 
89 #ifdef ENABLE_DEBUGGER_SUPPORT
90  // Obtain SharedFunctionInfo for the function.
91  Isolate::Current()->debug()->PrepareForBreakPoints();
92  Object* shared_func_info_ptr =
93  Isolate::Current()->debug()->FindSharedFunctionInfoInScript(i_script,
94  func_pos);
95  CHECK(shared_func_info_ptr != HEAP->undefined_value());
96  Handle<SharedFunctionInfo> shared_func_info(
97  SharedFunctionInfo::cast(shared_func_info_ptr));
98 
99  // Verify inferred function name.
100  SmartArrayPointer<char> inferred_name =
101  shared_func_info->inferred_name()->ToCString();
102  CHECK_EQ(ref_inferred_name, *inferred_name);
103 #endif // ENABLE_DEBUGGER_SUPPORT
104 }
105 
106 
107 static v8::Handle<v8::Script> Compile(const char* src) {
109 }
110 
111 
112 TEST(GlobalProperty) {
113  InitializeVM();
114  v8::HandleScope scope;
115 
116  v8::Handle<v8::Script> script = Compile(
117  "fun1 = function() { return 1; }\n"
118  "fun2 = function() { return 2; }\n");
119  CheckFunctionName(script, "return 1", "fun1");
120  CheckFunctionName(script, "return 2", "fun2");
121 }
122 
123 
124 TEST(GlobalVar) {
125  InitializeVM();
126  v8::HandleScope scope;
127 
128  v8::Handle<v8::Script> script = Compile(
129  "var fun1 = function() { return 1; }\n"
130  "var fun2 = function() { return 2; }\n");
131  CheckFunctionName(script, "return 1", "fun1");
132  CheckFunctionName(script, "return 2", "fun2");
133 }
134 
135 
136 TEST(LocalVar) {
137  InitializeVM();
138  v8::HandleScope scope;
139 
140  v8::Handle<v8::Script> script = Compile(
141  "function outer() {\n"
142  " var fun1 = function() { return 1; }\n"
143  " var fun2 = function() { return 2; }\n"
144  "}");
145  CheckFunctionName(script, "return 1", "fun1");
146  CheckFunctionName(script, "return 2", "fun2");
147 }
148 
149 
150 TEST(InConstructor) {
151  InitializeVM();
152  v8::HandleScope scope;
153 
154  v8::Handle<v8::Script> script = Compile(
155  "function MyClass() {\n"
156  " this.method1 = function() { return 1; }\n"
157  " this.method2 = function() { return 2; }\n"
158  "}");
159  CheckFunctionName(script, "return 1", "MyClass.method1");
160  CheckFunctionName(script, "return 2", "MyClass.method2");
161 }
162 
163 
164 TEST(Factory) {
165  InitializeVM();
166  v8::HandleScope scope;
167 
168  v8::Handle<v8::Script> script = Compile(
169  "function createMyObj() {\n"
170  " var obj = {};\n"
171  " obj.method1 = function() { return 1; }\n"
172  " obj.method2 = function() { return 2; }\n"
173  " return obj;\n"
174  "}");
175  CheckFunctionName(script, "return 1", "obj.method1");
176  CheckFunctionName(script, "return 2", "obj.method2");
177 }
178 
179 
180 TEST(Static) {
181  InitializeVM();
182  v8::HandleScope scope;
183 
184  v8::Handle<v8::Script> script = Compile(
185  "function MyClass() {}\n"
186  "MyClass.static1 = function() { return 1; }\n"
187  "MyClass.static2 = function() { return 2; }\n"
188  "MyClass.MyInnerClass = {}\n"
189  "MyClass.MyInnerClass.static3 = function() { return 3; }\n"
190  "MyClass.MyInnerClass.static4 = function() { return 4; }");
191  CheckFunctionName(script, "return 1", "MyClass.static1");
192  CheckFunctionName(script, "return 2", "MyClass.static2");
193  CheckFunctionName(script, "return 3", "MyClass.MyInnerClass.static3");
194  CheckFunctionName(script, "return 4", "MyClass.MyInnerClass.static4");
195 }
196 
197 
198 TEST(Prototype) {
199  InitializeVM();
200  v8::HandleScope scope;
201 
202  v8::Handle<v8::Script> script = Compile(
203  "function MyClass() {}\n"
204  "MyClass.prototype.method1 = function() { return 1; }\n"
205  "MyClass.prototype.method2 = function() { return 2; }\n"
206  "MyClass.MyInnerClass = function() {}\n"
207  "MyClass.MyInnerClass.prototype.method3 = function() { return 3; }\n"
208  "MyClass.MyInnerClass.prototype.method4 = function() { return 4; }");
209  CheckFunctionName(script, "return 1", "MyClass.method1");
210  CheckFunctionName(script, "return 2", "MyClass.method2");
211  CheckFunctionName(script, "return 3", "MyClass.MyInnerClass.method3");
212  CheckFunctionName(script, "return 4", "MyClass.MyInnerClass.method4");
213 }
214 
215 
216 TEST(ObjectLiteral) {
217  InitializeVM();
218  v8::HandleScope scope;
219 
220  v8::Handle<v8::Script> script = Compile(
221  "function MyClass() {}\n"
222  "MyClass.prototype = {\n"
223  " method1: function() { return 1; },\n"
224  " method2: function() { return 2; } }");
225  CheckFunctionName(script, "return 1", "MyClass.method1");
226  CheckFunctionName(script, "return 2", "MyClass.method2");
227 }
228 
229 
230 TEST(AsParameter) {
231  InitializeVM();
232  v8::HandleScope scope;
233 
234  v8::Handle<v8::Script> script = Compile(
235  "function f1(a) { return a(); }\n"
236  "function f2(a, b) { return a() + b(); }\n"
237  "var result1 = f1(function() { return 1; })\n"
238  "var result2 = f2(function() { return 2; }, function() { return 3; })");
239  // Can't infer names here.
240  CheckFunctionName(script, "return 1", "");
241  CheckFunctionName(script, "return 2", "");
242  CheckFunctionName(script, "return 3", "");
243 }
244 
245 
246 TEST(MultipleFuncsConditional) {
247  InitializeVM();
248  v8::HandleScope scope;
249 
250  v8::Handle<v8::Script> script = Compile(
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) {
260  InitializeVM();
261  v8::HandleScope scope;
262 
263  v8::Handle<v8::Script> script = Compile(
264  "function MyClass() {}\n"
265  "MyClass.prototype = {\n"
266  " method1: 0 ? function() { return 1; } :\n"
267  " function() { return 2; } }");
268  CheckFunctionName(script, "return 1", "MyClass.method1");
269  CheckFunctionName(script, "return 2", "MyClass.method1");
270 }
271 
272 
273 // See http://code.google.com/p/v8/issues/detail?id=380
274 TEST(Issue380) {
275  InitializeVM();
276  v8::HandleScope scope;
277 
278  v8::Handle<v8::Script> script = Compile(
279  "function a() {\n"
280  "var result = function(p,a,c,k,e,d)"
281  "{return p}(\"if blah blah\",62,1976,\'a|b\'.split(\'|\'),0,{})\n"
282  "}");
283  CheckFunctionName(script, "return p", "");
284 }
285 
286 
287 TEST(MultipleAssignments) {
288  InitializeVM();
289  v8::HandleScope scope;
290 
291  v8::Handle<v8::Script> script = Compile(
292  "var fun1 = fun2 = function () { return 1; }\n"
293  "var bar1 = bar2 = bar3 = function () { return 2; }\n"
294  "foo1 = foo2 = function () { return 3; }\n"
295  "baz1 = baz2 = baz3 = function () { return 4; }");
296  CheckFunctionName(script, "return 1", "fun2");
297  CheckFunctionName(script, "return 2", "bar3");
298  CheckFunctionName(script, "return 3", "foo2");
299  CheckFunctionName(script, "return 4", "baz3");
300 }
301 
302 
303 TEST(AsConstructorParameter) {
304  InitializeVM();
305  v8::HandleScope scope;
306 
307  v8::Handle<v8::Script> script = Compile(
308  "function Foo() {}\n"
309  "var foo = new Foo(function() { return 1; })\n"
310  "var bar = new Foo(function() { return 2; }, function() { return 3; })");
311  CheckFunctionName(script, "return 1", "");
312  CheckFunctionName(script, "return 2", "");
313  CheckFunctionName(script, "return 3", "");
314 }
315 
316 
317 TEST(FactoryHashmap) {
318  InitializeVM();
319  v8::HandleScope scope;
320 
321  v8::Handle<v8::Script> script = Compile(
322  "function createMyObj() {\n"
323  " var obj = {};\n"
324  " obj[\"method1\"] = function() { return 1; }\n"
325  " obj[\"method2\"] = function() { return 2; }\n"
326  " return obj;\n"
327  "}");
328  CheckFunctionName(script, "return 1", "obj.method1");
329  CheckFunctionName(script, "return 2", "obj.method2");
330 }
331 
332 
333 TEST(FactoryHashmapVariable) {
334  InitializeVM();
335  v8::HandleScope scope;
336 
337  v8::Handle<v8::Script> script = Compile(
338  "function createMyObj() {\n"
339  " var obj = {};\n"
340  " var methodName = \"method1\";\n"
341  " obj[methodName] = function() { return 1; }\n"
342  " methodName = \"method2\";\n"
343  " obj[methodName] = function() { return 2; }\n"
344  " return obj;\n"
345  "}");
346  // Can't infer function names statically.
347  CheckFunctionName(script, "return 1", "obj.(anonymous function)");
348  CheckFunctionName(script, "return 2", "obj.(anonymous function)");
349 }
350 
351 
352 TEST(FactoryHashmapConditional) {
353  InitializeVM();
354  v8::HandleScope scope;
355 
356  v8::Handle<v8::Script> script = Compile(
357  "function createMyObj() {\n"
358  " var obj = {};\n"
359  " obj[0 ? \"method1\" : \"method2\"] = function() { return 1; }\n"
360  " return obj;\n"
361  "}");
362  // Can't infer the function name statically.
363  CheckFunctionName(script, "return 1", "obj.(anonymous function)");
364 }
365 
366 
367 TEST(GlobalAssignmentAndCall) {
368  InitializeVM();
369  v8::HandleScope scope;
370 
371  v8::Handle<v8::Script> script = Compile(
372  "var Foo = function() {\n"
373  " return 1;\n"
374  "}();\n"
375  "var Baz = Bar = function() {\n"
376  " return 2;\n"
377  "}");
378  // The inferred name is empty, because this is an assignment of a result.
379  CheckFunctionName(script, "return 1", "");
380  // See MultipleAssignments test.
381  CheckFunctionName(script, "return 2", "Bar");
382 }
383 
384 
385 TEST(AssignmentAndCall) {
386  InitializeVM();
387  v8::HandleScope scope;
388 
389  v8::Handle<v8::Script> script = Compile(
390  "(function Enclosing() {\n"
391  " var Foo;\n"
392  " Foo = function() {\n"
393  " return 1;\n"
394  " }();\n"
395  " var Baz = Bar = function() {\n"
396  " return 2;\n"
397  " }\n"
398  "})();");
399  // The inferred name is empty, because this is an assignment of a result.
400  CheckFunctionName(script, "return 1", "");
401  // See MultipleAssignments test.
402  // TODO(2276): Lazy compiling the enclosing outer closure would yield
403  // in "Enclosing.Bar" being the inferred name here.
404  CheckFunctionName(script, "return 2", "Bar");
405 }
406 
407 
408 TEST(MethodAssignmentInAnonymousFunctionCall) {
409  InitializeVM();
410  v8::HandleScope scope;
411 
412  v8::Handle<v8::Script> script = Compile(
413  "(function () {\n"
414  " var EventSource = function () { };\n"
415  " EventSource.prototype.addListener = function () {\n"
416  " return 2012;\n"
417  " };\n"
418  " this.PublicEventSource = EventSource;\n"
419  "})();");
420  CheckFunctionName(script, "return 2012", "EventSource.addListener");
421 }
422 
423 
424 TEST(ReturnAnonymousFunction) {
425  InitializeVM();
426  v8::HandleScope scope;
427 
428  v8::Handle<v8::Script> script = Compile(
429  "(function() {\n"
430  " function wrapCode() {\n"
431  " return function () {\n"
432  " return 2012;\n"
433  " };\n"
434  " };\n"
435  " var foo = 10;\n"
436  " function f() {\n"
437  " return wrapCode();\n"
438  " }\n"
439  " this.ref = f;\n"
440  "})()");
441  script->Run();
442  CheckFunctionName(script, "return 2012", "");
443 }
static Local< Script > Compile(Handle< String > source, ScriptOrigin *origin=NULL, ScriptData *pre_data=NULL, Handle< String > script_data=Handle< String >())
Definition: api.cc:1568
#define CHECK_EQ(expected, value)
Definition: checks.h:219
static V8EXPORT Local< String > New(const char *data, int length=-1)
Definition: api.cc:4779
#define CHECK(condition)
Definition: checks.h:56
TEST(GlobalProperty)
Definition: v8.h:105
#define CHECK_NE(unexpected, value)
Definition: checks.h:223
Vector< const char > CStrVector(const char *data)
Definition: utils.h:526
#define HEAP
Definition: isolate.h:1433
bool IsEmpty() const
Definition: v8.h:209
Local< Value > Run()
Definition: api.cc:1598
#define FACTORY
Definition: isolate.h:1434
static Persistent< Context > New(ExtensionConfiguration *extensions=NULL, Handle< ObjectTemplate > global_template=Handle< ObjectTemplate >(), Handle< Value > global_object=Handle< Value >())
Definition: api.cc:4411