1 // Copyright 2007-2009 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 35 using ::v8::internal::CStrVector; 36 using ::v8::internal::Factory; 37 using ::v8::internal::Handle; 38 using ::v8::internal::Heap; 39 using ::v8::internal::JSFunction; 40 using ::v8::internal::Object; 41 using ::v8::internal::Runtime; 42 using ::v8::internal::Script; 43 using ::v8::internal::SmartPointer; 44 using ::v8::internal::SharedFunctionInfo; 45 using ::v8::internal::String; 46 47 48 static v8::Persistent<v8::Context> env; 49 50 51 static void InitializeVM() { 52 if (env.IsEmpty()) { 53 v8::HandleScope scope; 54 env = v8::Context::New(); 55 } 56 v8::HandleScope scope; 57 env->Enter(); 58 } 59 60 61 static void CheckFunctionName(v8::Handle<v8::Script> script, 62 const char* func_pos_src, 63 const char* ref_inferred_name) { 64 // Get script source. 65 Handle<JSFunction> fun = v8::Utils::OpenHandle(*script); 66 Handle<Script> i_script(Script::cast(fun->shared()->script())); 67 CHECK(i_script->source()->IsString()); 68 Handle<String> script_src(String::cast(i_script->source())); 69 70 // Find the position of a given func source substring in the source. 71 Handle<String> func_pos_str = 72 Factory::NewStringFromAscii(CStrVector(func_pos_src)); 73 int func_pos = Runtime::StringMatch(script_src, func_pos_str, 0); 74 CHECK_NE(0, func_pos); 75 76 // Obtain SharedFunctionInfo for the function. 77 Object* shared_func_info_ptr = 78 Runtime::FindSharedFunctionInfoInScript(i_script, func_pos); 79 CHECK(shared_func_info_ptr != Heap::undefined_value()); 80 Handle<SharedFunctionInfo> shared_func_info( 81 SharedFunctionInfo::cast(shared_func_info_ptr)); 82 83 // Verify inferred function name. 84 SmartPointer<char> inferred_name = 85 shared_func_info->inferred_name()->ToCString(); 86 CHECK_EQ(ref_inferred_name, *inferred_name); 87 } 88 89 90 static v8::Handle<v8::Script> Compile(const char* src) { 91 return v8::Script::Compile(v8::String::New(src)); 92 } 93 94 95 TEST(GlobalProperty) { 96 InitializeVM(); 97 v8::HandleScope scope; 98 99 v8::Handle<v8::Script> script = Compile( 100 "fun1 = function() { return 1; }\n" 101 "fun2 = function() { return 2; }\n"); 102 CheckFunctionName(script, "return 1", "fun1"); 103 CheckFunctionName(script, "return 2", "fun2"); 104 } 105 106 107 TEST(GlobalVar) { 108 InitializeVM(); 109 v8::HandleScope scope; 110 111 v8::Handle<v8::Script> script = Compile( 112 "var fun1 = function() { return 1; }\n" 113 "var fun2 = function() { return 2; }\n"); 114 CheckFunctionName(script, "return 1", "fun1"); 115 CheckFunctionName(script, "return 2", "fun2"); 116 } 117 118 119 TEST(LocalVar) { 120 InitializeVM(); 121 v8::HandleScope scope; 122 123 v8::Handle<v8::Script> script = Compile( 124 "function outer() {\n" 125 " var fun1 = function() { return 1; }\n" 126 " var fun2 = function() { return 2; }\n" 127 "}"); 128 CheckFunctionName(script, "return 1", "fun1"); 129 CheckFunctionName(script, "return 2", "fun2"); 130 } 131 132 133 TEST(InConstructor) { 134 InitializeVM(); 135 v8::HandleScope scope; 136 137 v8::Handle<v8::Script> script = Compile( 138 "function MyClass() {\n" 139 " this.method1 = function() { return 1; }\n" 140 " this.method2 = function() { return 2; }\n" 141 "}"); 142 CheckFunctionName(script, "return 1", "MyClass.method1"); 143 CheckFunctionName(script, "return 2", "MyClass.method2"); 144 } 145 146 147 TEST(Factory) { 148 InitializeVM(); 149 v8::HandleScope scope; 150 151 v8::Handle<v8::Script> script = Compile( 152 "function createMyObj() {\n" 153 " var obj = {};\n" 154 " obj.method1 = function() { return 1; }\n" 155 " obj.method2 = function() { return 2; }\n" 156 " return obj;\n" 157 "}"); 158 CheckFunctionName(script, "return 1", "obj.method1"); 159 CheckFunctionName(script, "return 2", "obj.method2"); 160 } 161 162 163 TEST(Static) { 164 InitializeVM(); 165 v8::HandleScope scope; 166 167 v8::Handle<v8::Script> script = Compile( 168 "function MyClass() {}\n" 169 "MyClass.static1 = function() { return 1; }\n" 170 "MyClass.static2 = function() { return 2; }\n" 171 "MyClass.MyInnerClass = {}\n" 172 "MyClass.MyInnerClass.static3 = function() { return 3; }\n" 173 "MyClass.MyInnerClass.static4 = function() { return 4; }"); 174 CheckFunctionName(script, "return 1", "MyClass.static1"); 175 CheckFunctionName(script, "return 2", "MyClass.static2"); 176 CheckFunctionName(script, "return 3", "MyClass.MyInnerClass.static3"); 177 CheckFunctionName(script, "return 4", "MyClass.MyInnerClass.static4"); 178 } 179 180 181 TEST(Prototype) { 182 InitializeVM(); 183 v8::HandleScope scope; 184 185 v8::Handle<v8::Script> script = Compile( 186 "function MyClass() {}\n" 187 "MyClass.prototype.method1 = function() { return 1; }\n" 188 "MyClass.prototype.method2 = function() { return 2; }\n" 189 "MyClass.MyInnerClass = function() {}\n" 190 "MyClass.MyInnerClass.prototype.method3 = function() { return 3; }\n" 191 "MyClass.MyInnerClass.prototype.method4 = function() { return 4; }"); 192 CheckFunctionName(script, "return 1", "MyClass.method1"); 193 CheckFunctionName(script, "return 2", "MyClass.method2"); 194 CheckFunctionName(script, "return 3", "MyClass.MyInnerClass.method3"); 195 CheckFunctionName(script, "return 4", "MyClass.MyInnerClass.method4"); 196 } 197 198 199 TEST(ObjectLiteral) { 200 InitializeVM(); 201 v8::HandleScope scope; 202 203 v8::Handle<v8::Script> script = Compile( 204 "function MyClass() {}\n" 205 "MyClass.prototype = {\n" 206 " method1: function() { return 1; },\n" 207 " method2: function() { return 2; } }"); 208 CheckFunctionName(script, "return 1", "MyClass.method1"); 209 CheckFunctionName(script, "return 2", "MyClass.method2"); 210 } 211 212 213 TEST(AsParameter) { 214 InitializeVM(); 215 v8::HandleScope scope; 216 217 v8::Handle<v8::Script> script = Compile( 218 "function f1(a) { return a(); }\n" 219 "function f2(a, b) { return a() + b(); }\n" 220 "var result1 = f1(function() { return 1; })\n" 221 "var result2 = f2(function() { return 2; }, function() { return 3; })"); 222 // Can't infer names here. 223 CheckFunctionName(script, "return 1", ""); 224 CheckFunctionName(script, "return 2", ""); 225 CheckFunctionName(script, "return 3", ""); 226 } 227 228 229 TEST(MultipleFuncsConditional) { 230 InitializeVM(); 231 v8::HandleScope scope; 232 233 v8::Handle<v8::Script> script = Compile( 234 "fun1 = 0 ?\n" 235 " function() { return 1; } :\n" 236 " function() { return 2; }"); 237 CheckFunctionName(script, "return 1", "fun1"); 238 CheckFunctionName(script, "return 2", "fun1"); 239 } 240 241 242 TEST(MultipleFuncsInLiteral) { 243 InitializeVM(); 244 v8::HandleScope scope; 245 246 v8::Handle<v8::Script> script = Compile( 247 "function MyClass() {}\n" 248 "MyClass.prototype = {\n" 249 " method1: 0 ? function() { return 1; } :\n" 250 " function() { return 2; } }"); 251 CheckFunctionName(script, "return 1", "MyClass.method1"); 252 CheckFunctionName(script, "return 2", "MyClass.method1"); 253 } 254 255 256 // See http://code.google.com/p/v8/issues/detail?id=380 257 TEST(Issue380) { 258 InitializeVM(); 259 v8::HandleScope scope; 260 261 v8::Handle<v8::Script> script = Compile( 262 "function a() {\n" 263 "var result = function(p,a,c,k,e,d)" 264 "{return p}(\"if blah blah\",62,1976,\'a|b\'.split(\'|\'),0,{})\n" 265 "}"); 266 CheckFunctionName(script, "return p", ""); 267 } 268