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