Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1 | // Copyright 2012 the V8 project authors. All rights reserved. |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 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 <stdlib.h> |
| 29 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 30 | #include "src/v8.h" |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 31 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 32 | #include "src/api.h" |
| 33 | #include "src/frames-inl.h" |
| 34 | #include "src/string-stream.h" |
| 35 | #include "test/cctest/cctest.h" |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 36 | |
| 37 | using ::v8::ObjectTemplate; |
| 38 | using ::v8::Value; |
| 39 | using ::v8::Context; |
| 40 | using ::v8::Local; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 41 | using ::v8::Name; |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 42 | using ::v8::String; |
| 43 | using ::v8::Script; |
| 44 | using ::v8::Function; |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 45 | using ::v8::Extension; |
| 46 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 47 | static void handle_property(Local<String> name, |
| 48 | const v8::PropertyCallbackInfo<v8::Value>& info) { |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 49 | ApiTestFuzzer::Fuzz(); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 50 | info.GetReturnValue().Set(v8_num(900)); |
| 51 | } |
| 52 | |
| 53 | static void handle_property_2(Local<String> name, |
| 54 | const v8::PropertyCallbackInfo<v8::Value>& info) { |
| 55 | ApiTestFuzzer::Fuzz(); |
| 56 | info.GetReturnValue().Set(v8_num(902)); |
| 57 | } |
| 58 | |
| 59 | |
| 60 | static void handle_property(const v8::FunctionCallbackInfo<v8::Value>& info) { |
| 61 | ApiTestFuzzer::Fuzz(); |
| 62 | CHECK_EQ(0, info.Length()); |
| 63 | info.GetReturnValue().Set(v8_num(907)); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 64 | } |
| 65 | |
| 66 | |
| 67 | THREADED_TEST(PropertyHandler) { |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 68 | LocalContext env; |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 69 | v8::Isolate* isolate = env->GetIsolate(); |
| 70 | v8::HandleScope scope(isolate); |
| 71 | Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate); |
| 72 | fun_templ->InstanceTemplate()->SetAccessor(v8_str("foo"), handle_property); |
| 73 | Local<v8::FunctionTemplate> getter_templ = |
| 74 | v8::FunctionTemplate::New(isolate, handle_property); |
| 75 | getter_templ->SetLength(0); |
| 76 | fun_templ-> |
| 77 | InstanceTemplate()->SetAccessorProperty(v8_str("bar"), getter_templ); |
| 78 | fun_templ->InstanceTemplate()-> |
| 79 | SetNativeDataProperty(v8_str("instance_foo"), handle_property); |
| 80 | fun_templ->SetNativeDataProperty(v8_str("object_foo"), handle_property_2); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 81 | Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked(); |
| 82 | CHECK(env->Global()->Set(env.local(), v8_str("Fun"), fun).FromJust()); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 83 | Local<Script> getter; |
| 84 | Local<Script> setter; |
| 85 | // check function instance accessors |
| 86 | getter = v8_compile("var obj = new Fun(); obj.instance_foo;"); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 87 | CHECK_EQ(900, getter->Run(env.local()) |
| 88 | .ToLocalChecked() |
| 89 | ->Int32Value(env.local()) |
| 90 | .FromJust()); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 91 | setter = v8_compile("obj.instance_foo = 901;"); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 92 | CHECK_EQ(901, setter->Run(env.local()) |
| 93 | .ToLocalChecked() |
| 94 | ->Int32Value(env.local()) |
| 95 | .FromJust()); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 96 | getter = v8_compile("obj.bar;"); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 97 | CHECK_EQ(907, getter->Run(env.local()) |
| 98 | .ToLocalChecked() |
| 99 | ->Int32Value(env.local()) |
| 100 | .FromJust()); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 101 | setter = v8_compile("obj.bar = 908;"); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 102 | CHECK_EQ(908, setter->Run(env.local()) |
| 103 | .ToLocalChecked() |
| 104 | ->Int32Value(env.local()) |
| 105 | .FromJust()); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 106 | // check function static accessors |
| 107 | getter = v8_compile("Fun.object_foo;"); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 108 | CHECK_EQ(902, getter->Run(env.local()) |
| 109 | .ToLocalChecked() |
| 110 | ->Int32Value(env.local()) |
| 111 | .FromJust()); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 112 | setter = v8_compile("Fun.object_foo = 903;"); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 113 | CHECK_EQ(903, setter->Run(env.local()) |
| 114 | .ToLocalChecked() |
| 115 | ->Int32Value(env.local()) |
| 116 | .FromJust()); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 117 | } |
| 118 | |
| 119 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 120 | static void GetIntValue(Local<String> property, |
| 121 | const v8::PropertyCallbackInfo<v8::Value>& info) { |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 122 | ApiTestFuzzer::Fuzz(); |
| 123 | int* value = |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 124 | static_cast<int*>(v8::Local<v8::External>::Cast(info.Data())->Value()); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 125 | info.GetReturnValue().Set(v8_num(*value)); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 126 | } |
| 127 | |
| 128 | |
| 129 | static void SetIntValue(Local<String> property, |
| 130 | Local<Value> value, |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 131 | const v8::PropertyCallbackInfo<void>& info) { |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 132 | int* field = |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 133 | static_cast<int*>(v8::Local<v8::External>::Cast(info.Data())->Value()); |
| 134 | *field = value->Int32Value(info.GetIsolate()->GetCurrentContext()).FromJust(); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 135 | } |
| 136 | |
| 137 | int foo, bar, baz; |
| 138 | |
| 139 | THREADED_TEST(GlobalVariableAccess) { |
| 140 | foo = 0; |
| 141 | bar = -4; |
| 142 | baz = 10; |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 143 | v8::Isolate* isolate = CcTest::isolate(); |
| 144 | v8::HandleScope scope(isolate); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 145 | v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 146 | templ->InstanceTemplate()->SetAccessor( |
| 147 | v8_str("foo"), GetIntValue, SetIntValue, |
| 148 | v8::External::New(isolate, &foo)); |
| 149 | templ->InstanceTemplate()->SetAccessor( |
| 150 | v8_str("bar"), GetIntValue, SetIntValue, |
| 151 | v8::External::New(isolate, &bar)); |
| 152 | templ->InstanceTemplate()->SetAccessor( |
| 153 | v8_str("baz"), GetIntValue, SetIntValue, |
| 154 | v8::External::New(isolate, &baz)); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 155 | LocalContext env(0, templ->InstanceTemplate()); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 156 | v8_compile("foo = (++bar) + baz")->Run(env.local()).ToLocalChecked(); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 157 | CHECK_EQ(bar, -3); |
| 158 | CHECK_EQ(foo, 7); |
| 159 | } |
| 160 | |
| 161 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 162 | static int x_register[2] = {0, 0}; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 163 | static v8::Local<v8::Object> x_receiver; |
| 164 | static v8::Local<v8::Object> x_holder; |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 165 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 166 | template<class Info> |
| 167 | static void XGetter(const Info& info, int offset) { |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 168 | ApiTestFuzzer::Fuzz(); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 169 | v8::Isolate* isolate = CcTest::isolate(); |
| 170 | CHECK_EQ(isolate, info.GetIsolate()); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 171 | CHECK( |
| 172 | x_receiver->Equals(isolate->GetCurrentContext(), info.This()).FromJust()); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 173 | info.GetReturnValue().Set(v8_num(x_register[offset])); |
| 174 | } |
| 175 | |
| 176 | |
| 177 | static void XGetter(Local<String> name, |
| 178 | const v8::PropertyCallbackInfo<v8::Value>& info) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 179 | CHECK(x_holder->Equals(info.GetIsolate()->GetCurrentContext(), info.Holder()) |
| 180 | .FromJust()); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 181 | XGetter(info, 0); |
| 182 | } |
| 183 | |
| 184 | |
| 185 | static void XGetter(const v8::FunctionCallbackInfo<v8::Value>& info) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 186 | CHECK( |
| 187 | x_receiver->Equals(info.GetIsolate()->GetCurrentContext(), info.Holder()) |
| 188 | .FromJust()); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 189 | XGetter(info, 1); |
| 190 | } |
| 191 | |
| 192 | |
| 193 | template<class Info> |
| 194 | static void XSetter(Local<Value> value, const Info& info, int offset) { |
| 195 | v8::Isolate* isolate = CcTest::isolate(); |
| 196 | CHECK_EQ(isolate, info.GetIsolate()); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 197 | CHECK(x_holder->Equals(info.GetIsolate()->GetCurrentContext(), info.This()) |
| 198 | .FromJust()); |
| 199 | CHECK(x_holder->Equals(info.GetIsolate()->GetCurrentContext(), info.Holder()) |
| 200 | .FromJust()); |
| 201 | x_register[offset] = |
| 202 | value->Int32Value(info.GetIsolate()->GetCurrentContext()).FromJust(); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 203 | info.GetReturnValue().Set(v8_num(-1)); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 204 | } |
| 205 | |
| 206 | |
| 207 | static void XSetter(Local<String> name, |
| 208 | Local<Value> value, |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 209 | const v8::PropertyCallbackInfo<void>& info) { |
| 210 | XSetter(value, info, 0); |
| 211 | } |
| 212 | |
| 213 | |
| 214 | static void XSetter(const v8::FunctionCallbackInfo<v8::Value>& info) { |
| 215 | CHECK_EQ(1, info.Length()); |
| 216 | XSetter(info[0], info, 1); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 217 | } |
| 218 | |
| 219 | |
| 220 | THREADED_TEST(AccessorIC) { |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 221 | LocalContext context; |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 222 | v8::Isolate* isolate = context->GetIsolate(); |
| 223 | v8::HandleScope scope(isolate); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 224 | v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 225 | obj->SetAccessor(v8_str("x0"), XGetter, XSetter); |
| 226 | obj->SetAccessorProperty(v8_str("x1"), |
| 227 | v8::FunctionTemplate::New(isolate, XGetter), |
| 228 | v8::FunctionTemplate::New(isolate, XSetter)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 229 | x_holder = obj->NewInstance(context.local()).ToLocalChecked(); |
| 230 | CHECK(context->Global() |
| 231 | ->Set(context.local(), v8_str("holder"), x_holder) |
| 232 | .FromJust()); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 233 | x_receiver = v8::Object::New(isolate); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 234 | CHECK(context->Global() |
| 235 | ->Set(context.local(), v8_str("obj"), x_receiver) |
| 236 | .FromJust()); |
| 237 | v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast( |
| 238 | CompileRun("obj.__proto__ = holder;" |
| 239 | "var result = [];" |
| 240 | "var key_0 = 'x0';" |
| 241 | "var key_1 = 'x1';" |
| 242 | "for (var j = 0; j < 10; j++) {" |
| 243 | " var i = 4*j;" |
| 244 | " result.push(holder.x0 = i);" |
| 245 | " result.push(obj.x0);" |
| 246 | " result.push(holder.x1 = i + 1);" |
| 247 | " result.push(obj.x1);" |
| 248 | " result.push(holder[key_0] = i + 2);" |
| 249 | " result.push(obj[key_0]);" |
| 250 | " result.push(holder[key_1] = i + 3);" |
| 251 | " result.push(obj[key_1]);" |
| 252 | "}" |
| 253 | "result")); |
| 254 | CHECK_EQ(80u, array->Length()); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 255 | for (int i = 0; i < 80; i++) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 256 | v8::Local<Value> entry = |
| 257 | array->Get(context.local(), v8::Integer::New(isolate, i)) |
| 258 | .ToLocalChecked(); |
| 259 | CHECK(v8::Integer::New(isolate, i / 2) |
| 260 | ->Equals(context.local(), entry) |
| 261 | .FromJust()); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 262 | } |
| 263 | } |
| 264 | |
| 265 | |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 266 | template <int C> |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 267 | static void HandleAllocatingGetter( |
| 268 | Local<String> name, |
| 269 | const v8::PropertyCallbackInfo<v8::Value>& info) { |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 270 | ApiTestFuzzer::Fuzz(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 271 | for (int i = 0; i < C; i++) { |
| 272 | v8::String::NewFromUtf8(info.GetIsolate(), "foo", |
| 273 | v8::NewStringType::kNormal) |
| 274 | .ToLocalChecked(); |
| 275 | } |
| 276 | info.GetReturnValue().Set(v8::String::NewFromUtf8(info.GetIsolate(), "foo", |
| 277 | v8::NewStringType::kNormal) |
| 278 | .ToLocalChecked()); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 279 | } |
| 280 | |
| 281 | |
| 282 | THREADED_TEST(HandleScopePop) { |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 283 | LocalContext context; |
| 284 | v8::Isolate* isolate = context->GetIsolate(); |
| 285 | v8::HandleScope scope(isolate); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 286 | v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 287 | obj->SetAccessor(v8_str("one"), HandleAllocatingGetter<1>); |
| 288 | obj->SetAccessor(v8_str("many"), HandleAllocatingGetter<1024>); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 289 | v8::Local<v8::Object> inst = |
| 290 | obj->NewInstance(context.local()).ToLocalChecked(); |
| 291 | CHECK( |
| 292 | context->Global()->Set(context.local(), v8_str("obj"), inst).FromJust()); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 293 | int count_before = |
| 294 | i::HandleScope::NumberOfHandles(reinterpret_cast<i::Isolate*>(isolate)); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 295 | { |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 296 | v8::HandleScope scope(isolate); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 297 | CompileRun( |
| 298 | "for (var i = 0; i < 1000; i++) {" |
| 299 | " obj.one;" |
| 300 | " obj.many;" |
| 301 | "}"); |
| 302 | } |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 303 | int count_after = |
| 304 | i::HandleScope::NumberOfHandles(reinterpret_cast<i::Isolate*>(isolate)); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 305 | CHECK_EQ(count_before, count_after); |
| 306 | } |
| 307 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 308 | static void CheckAccessorArgsCorrect( |
| 309 | Local<String> name, |
| 310 | const v8::PropertyCallbackInfo<v8::Value>& info) { |
| 311 | CHECK(info.GetIsolate() == CcTest::isolate()); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 312 | CHECK(info.This() == info.Holder()); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 313 | CHECK(info.Data() |
| 314 | ->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("data")) |
| 315 | .FromJust()); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 316 | ApiTestFuzzer::Fuzz(); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 317 | CHECK(info.GetIsolate() == CcTest::isolate()); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 318 | CHECK(info.This() == info.Holder()); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 319 | CHECK(info.Data() |
| 320 | ->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("data")) |
| 321 | .FromJust()); |
| 322 | CcTest::heap()->CollectAllGarbage(); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 323 | CHECK(info.GetIsolate() == CcTest::isolate()); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 324 | CHECK(info.This() == info.Holder()); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 325 | CHECK(info.Data() |
| 326 | ->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("data")) |
| 327 | .FromJust()); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 328 | info.GetReturnValue().Set(17); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 329 | } |
| 330 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 331 | |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 332 | THREADED_TEST(DirectCall) { |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 333 | LocalContext context; |
| 334 | v8::Isolate* isolate = context->GetIsolate(); |
| 335 | v8::HandleScope scope(isolate); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 336 | v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate); |
| 337 | obj->SetAccessor(v8_str("xxx"), CheckAccessorArgsCorrect, NULL, |
| 338 | v8_str("data")); |
| 339 | v8::Local<v8::Object> inst = |
| 340 | obj->NewInstance(context.local()).ToLocalChecked(); |
| 341 | CHECK( |
| 342 | context->Global()->Set(context.local(), v8_str("obj"), inst).FromJust()); |
| 343 | Local<Script> scr = |
| 344 | v8::Script::Compile(context.local(), v8_str("obj.xxx")).ToLocalChecked(); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 345 | for (int i = 0; i < 10; i++) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 346 | Local<Value> result = scr->Run(context.local()).ToLocalChecked(); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 347 | CHECK(!result.IsEmpty()); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 348 | CHECK_EQ(17, result->Int32Value(context.local()).FromJust()); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 349 | } |
| 350 | } |
| 351 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 352 | static void EmptyGetter(Local<String> name, |
| 353 | const v8::PropertyCallbackInfo<v8::Value>& info) { |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 354 | CheckAccessorArgsCorrect(name, info); |
| 355 | ApiTestFuzzer::Fuzz(); |
| 356 | CheckAccessorArgsCorrect(name, info); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 357 | info.GetReturnValue().Set(v8::Local<v8::Value>()); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 358 | } |
| 359 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 360 | |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 361 | THREADED_TEST(EmptyResult) { |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 362 | LocalContext context; |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 363 | v8::Isolate* isolate = context->GetIsolate(); |
| 364 | v8::HandleScope scope(isolate); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 365 | v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate); |
| 366 | obj->SetAccessor(v8_str("xxx"), EmptyGetter, NULL, v8_str("data")); |
| 367 | v8::Local<v8::Object> inst = |
| 368 | obj->NewInstance(context.local()).ToLocalChecked(); |
| 369 | CHECK( |
| 370 | context->Global()->Set(context.local(), v8_str("obj"), inst).FromJust()); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 371 | Local<Script> scr = |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 372 | v8::Script::Compile(context.local(), v8_str("obj.xxx")).ToLocalChecked(); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 373 | for (int i = 0; i < 10; i++) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 374 | Local<Value> result = scr->Run(context.local()).ToLocalChecked(); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 375 | CHECK(result == v8::Undefined(isolate)); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 376 | } |
| 377 | } |
| 378 | |
| 379 | |
| 380 | THREADED_TEST(NoReuseRegress) { |
| 381 | // Check that the IC generated for the one test doesn't get reused |
| 382 | // for the other. |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 383 | v8::Isolate* isolate = CcTest::isolate(); |
| 384 | v8::HandleScope scope(isolate); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 385 | { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 386 | v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate); |
| 387 | obj->SetAccessor(v8_str("xxx"), EmptyGetter, NULL, v8_str("data")); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 388 | LocalContext context; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 389 | v8::Local<v8::Object> inst = |
| 390 | obj->NewInstance(context.local()).ToLocalChecked(); |
| 391 | CHECK(context->Global() |
| 392 | ->Set(context.local(), v8_str("obj"), inst) |
| 393 | .FromJust()); |
| 394 | Local<Script> scr = v8::Script::Compile(context.local(), v8_str("obj.xxx")) |
| 395 | .ToLocalChecked(); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 396 | for (int i = 0; i < 2; i++) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 397 | Local<Value> result = scr->Run(context.local()).ToLocalChecked(); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 398 | CHECK(result == v8::Undefined(isolate)); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 399 | } |
| 400 | } |
| 401 | { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 402 | v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate); |
| 403 | obj->SetAccessor(v8_str("xxx"), CheckAccessorArgsCorrect, NULL, |
| 404 | v8_str("data")); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 405 | LocalContext context; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 406 | v8::Local<v8::Object> inst = |
| 407 | obj->NewInstance(context.local()).ToLocalChecked(); |
| 408 | CHECK(context->Global() |
| 409 | ->Set(context.local(), v8_str("obj"), inst) |
| 410 | .FromJust()); |
| 411 | Local<Script> scr = v8::Script::Compile(context.local(), v8_str("obj.xxx")) |
| 412 | .ToLocalChecked(); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 413 | for (int i = 0; i < 10; i++) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 414 | Local<Value> result = scr->Run(context.local()).ToLocalChecked(); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 415 | CHECK(!result.IsEmpty()); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 416 | CHECK_EQ(17, result->Int32Value(context.local()).FromJust()); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 417 | } |
| 418 | } |
| 419 | } |
| 420 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 421 | static void ThrowingGetAccessor( |
| 422 | Local<String> name, |
| 423 | const v8::PropertyCallbackInfo<v8::Value>& info) { |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 424 | ApiTestFuzzer::Fuzz(); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 425 | info.GetIsolate()->ThrowException(v8_str("g")); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 426 | } |
| 427 | |
| 428 | |
| 429 | static void ThrowingSetAccessor(Local<String> name, |
| 430 | Local<Value> value, |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 431 | const v8::PropertyCallbackInfo<void>& info) { |
| 432 | info.GetIsolate()->ThrowException(value); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 433 | } |
| 434 | |
| 435 | |
| 436 | THREADED_TEST(Regress1054726) { |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 437 | LocalContext env; |
| 438 | v8::Isolate* isolate = env->GetIsolate(); |
| 439 | v8::HandleScope scope(isolate); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 440 | v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 441 | obj->SetAccessor(v8_str("x"), |
| 442 | ThrowingGetAccessor, |
| 443 | ThrowingSetAccessor, |
| 444 | Local<Value>()); |
| 445 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 446 | CHECK(env->Global() |
| 447 | ->Set(env.local(), v8_str("obj"), |
| 448 | obj->NewInstance(env.local()).ToLocalChecked()) |
| 449 | .FromJust()); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 450 | |
| 451 | // Use the throwing property setter/getter in a loop to force |
| 452 | // the accessor ICs to be initialized. |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 453 | v8::Local<Value> result; |
| 454 | result = Script::Compile(env.local(), |
| 455 | v8_str("var result = '';" |
| 456 | "for (var i = 0; i < 5; i++) {" |
| 457 | " try { obj.x; } catch (e) { result += e; }" |
| 458 | "}; result")) |
| 459 | .ToLocalChecked() |
| 460 | ->Run(env.local()) |
| 461 | .ToLocalChecked(); |
| 462 | CHECK(v8_str("ggggg")->Equals(env.local(), result).FromJust()); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 463 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 464 | result = |
| 465 | Script::Compile(env.local(), |
| 466 | v8_str("var result = '';" |
| 467 | "for (var i = 0; i < 5; i++) {" |
| 468 | " try { obj.x = i; } catch (e) { result += e; }" |
| 469 | "}; result")) |
| 470 | .ToLocalChecked() |
| 471 | ->Run(env.local()) |
| 472 | .ToLocalChecked(); |
| 473 | CHECK(v8_str("01234")->Equals(env.local(), result).FromJust()); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 474 | } |
| 475 | |
| 476 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 477 | static void AllocGetter(Local<String> name, |
| 478 | const v8::PropertyCallbackInfo<v8::Value>& info) { |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 479 | ApiTestFuzzer::Fuzz(); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 480 | info.GetReturnValue().Set(v8::Array::New(info.GetIsolate(), 1000)); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 481 | } |
| 482 | |
| 483 | |
| 484 | THREADED_TEST(Gc) { |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 485 | LocalContext env; |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 486 | v8::Isolate* isolate = env->GetIsolate(); |
| 487 | v8::HandleScope scope(isolate); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 488 | v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 489 | obj->SetAccessor(v8_str("xxx"), AllocGetter); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 490 | CHECK(env->Global() |
| 491 | ->Set(env.local(), v8_str("obj"), |
| 492 | obj->NewInstance(env.local()).ToLocalChecked()) |
| 493 | .FromJust()); |
| 494 | Script::Compile(env.local(), v8_str("var last = [];" |
| 495 | "for (var i = 0; i < 2048; i++) {" |
| 496 | " var result = obj.xxx;" |
| 497 | " result[0] = last;" |
| 498 | " last = result;" |
| 499 | "}")) |
| 500 | .ToLocalChecked() |
| 501 | ->Run(env.local()) |
| 502 | .ToLocalChecked(); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 503 | } |
| 504 | |
| 505 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 506 | static void StackCheck(Local<String> name, |
| 507 | const v8::PropertyCallbackInfo<v8::Value>& info) { |
| 508 | i::StackFrameIterator iter(reinterpret_cast<i::Isolate*>(info.GetIsolate())); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 509 | for (int i = 0; !iter.done(); i++) { |
| 510 | i::StackFrame* frame = iter.frame(); |
| 511 | CHECK(i != 0 || (frame->type() == i::StackFrame::EXIT)); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 512 | i::Code* code = frame->LookupCode(); |
Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame] | 513 | CHECK(code->IsCode()); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 514 | i::Address pc = frame->pc(); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 515 | CHECK(code->contains(pc)); |
| 516 | iter.Advance(); |
| 517 | } |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 518 | } |
| 519 | |
| 520 | |
| 521 | THREADED_TEST(StackIteration) { |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 522 | LocalContext env; |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 523 | v8::Isolate* isolate = env->GetIsolate(); |
| 524 | v8::HandleScope scope(isolate); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 525 | v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 526 | i::StringStream::ClearMentionedObjectCache( |
| 527 | reinterpret_cast<i::Isolate*>(isolate)); |
| 528 | obj->SetAccessor(v8_str("xxx"), StackCheck); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 529 | CHECK(env->Global() |
| 530 | ->Set(env.local(), v8_str("obj"), |
| 531 | obj->NewInstance(env.local()).ToLocalChecked()) |
| 532 | .FromJust()); |
| 533 | Script::Compile(env.local(), v8_str("function foo() {" |
| 534 | " return obj.xxx;" |
| 535 | "}" |
| 536 | "for (var i = 0; i < 100; i++) {" |
| 537 | " foo();" |
| 538 | "}")) |
| 539 | .ToLocalChecked() |
| 540 | ->Run(env.local()) |
| 541 | .ToLocalChecked(); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 542 | } |
| 543 | |
| 544 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 545 | static void AllocateHandles(Local<String> name, |
| 546 | const v8::PropertyCallbackInfo<v8::Value>& info) { |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 547 | for (int i = 0; i < i::kHandleBlockSize + 1; i++) { |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 548 | v8::Local<v8::Value>::New(info.GetIsolate(), name); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 549 | } |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 550 | info.GetReturnValue().Set(v8::Integer::New(info.GetIsolate(), 100)); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 551 | } |
| 552 | |
| 553 | |
| 554 | THREADED_TEST(HandleScopeSegment) { |
| 555 | // Check that we can return values past popping of handle scope |
| 556 | // segments. |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 557 | LocalContext env; |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 558 | v8::Isolate* isolate = env->GetIsolate(); |
| 559 | v8::HandleScope scope(isolate); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 560 | v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 561 | obj->SetAccessor(v8_str("xxx"), AllocateHandles); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 562 | CHECK(env->Global() |
| 563 | ->Set(env.local(), v8_str("obj"), |
| 564 | obj->NewInstance(env.local()).ToLocalChecked()) |
| 565 | .FromJust()); |
| 566 | v8::Local<v8::Value> result = |
| 567 | Script::Compile(env.local(), v8_str("var result;" |
| 568 | "for (var i = 0; i < 4; i++)" |
| 569 | " result = obj.xxx;" |
| 570 | "result;")) |
| 571 | .ToLocalChecked() |
| 572 | ->Run(env.local()) |
| 573 | .ToLocalChecked(); |
| 574 | CHECK_EQ(100, result->Int32Value(env.local()).FromJust()); |
Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 575 | } |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 576 | |
| 577 | |
| 578 | void JSONStringifyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 579 | v8::Local<v8::Array> array = v8::Array::New(info.GetIsolate(), 1); |
| 580 | CHECK(array->Set(info.GetIsolate()->GetCurrentContext(), 0, v8_str("regress")) |
| 581 | .FromJust()); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 582 | info.GetReturnValue().Set(array); |
| 583 | } |
| 584 | |
| 585 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 586 | void JSONStringifyGetter(Local<Name> name, |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 587 | const v8::PropertyCallbackInfo<v8::Value>& info) { |
| 588 | info.GetReturnValue().Set(v8_str("crbug-161028")); |
| 589 | } |
| 590 | |
| 591 | |
| 592 | THREADED_TEST(JSONStringifyNamedInterceptorObject) { |
| 593 | LocalContext env; |
| 594 | v8::Isolate* isolate = env->GetIsolate(); |
| 595 | v8::HandleScope scope(isolate); |
| 596 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 597 | v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 598 | obj->SetHandler(v8::NamedPropertyHandlerConfiguration( |
| 599 | JSONStringifyGetter, NULL, NULL, NULL, JSONStringifyEnumerator)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 600 | CHECK(env->Global() |
| 601 | ->Set(env.local(), v8_str("obj"), |
| 602 | obj->NewInstance(env.local()).ToLocalChecked()) |
| 603 | .FromJust()); |
| 604 | v8::Local<v8::String> expected = v8_str("{\"regress\":\"crbug-161028\"}"); |
| 605 | CHECK(CompileRun("JSON.stringify(obj)") |
| 606 | ->Equals(env.local(), expected) |
| 607 | .FromJust()); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 608 | } |
| 609 | |
| 610 | |
| 611 | static v8::Local<v8::Context> expected_current_context; |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 612 | |
| 613 | |
| 614 | static void check_contexts(const v8::FunctionCallbackInfo<v8::Value>& info) { |
| 615 | ApiTestFuzzer::Fuzz(); |
| 616 | CHECK(expected_current_context == info.GetIsolate()->GetCurrentContext()); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 617 | } |
| 618 | |
| 619 | |
| 620 | THREADED_TEST(AccessorPropertyCrossContext) { |
| 621 | LocalContext env; |
| 622 | v8::Isolate* isolate = env->GetIsolate(); |
| 623 | v8::HandleScope scope(isolate); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 624 | v8::Local<v8::Function> fun = |
| 625 | v8::Function::New(env.local(), check_contexts).ToLocalChecked(); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 626 | LocalContext switch_context; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 627 | CHECK(switch_context->Global() |
| 628 | ->Set(switch_context.local(), v8_str("fun"), fun) |
| 629 | .FromJust()); |
| 630 | v8::TryCatch try_catch(isolate); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 631 | expected_current_context = env.local(); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 632 | CompileRun( |
| 633 | "var o = Object.create(null, { n: { get:fun } });" |
| 634 | "for (var i = 0; i < 10; i++) o.n;"); |
| 635 | CHECK(!try_catch.HasCaught()); |
| 636 | } |
| 637 | |
| 638 | |
| 639 | THREADED_TEST(GlobalObjectAccessor) { |
| 640 | LocalContext env; |
| 641 | v8::Isolate* isolate = env->GetIsolate(); |
| 642 | v8::HandleScope scope(isolate); |
| 643 | CompileRun( |
| 644 | "var set_value = 1;" |
| 645 | "Object.defineProperty(this.__proto__, 'x', {" |
| 646 | " get : function() { return this; }," |
| 647 | " set : function() { set_value = this; }" |
| 648 | "});" |
| 649 | "function getter() { return x; }" |
| 650 | "function setter() { x = 1; }" |
| 651 | "for (var i = 0; i < 4; i++) { getter(); setter(); }"); |
| 652 | CHECK(v8::Utils::OpenHandle(*CompileRun("getter()"))->IsJSGlobalProxy()); |
| 653 | CHECK(v8::Utils::OpenHandle(*CompileRun("set_value"))->IsJSGlobalProxy()); |
| 654 | } |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 655 | |
| 656 | |
| 657 | static void EmptyGetter(Local<Name> name, |
| 658 | const v8::PropertyCallbackInfo<v8::Value>& info) { |
| 659 | ApiTestFuzzer::Fuzz(); |
| 660 | } |
| 661 | |
| 662 | |
| 663 | static void OneProperty(Local<String> name, |
| 664 | const v8::PropertyCallbackInfo<v8::Value>& info) { |
| 665 | ApiTestFuzzer::Fuzz(); |
| 666 | info.GetReturnValue().Set(v8_num(1)); |
| 667 | } |
| 668 | |
| 669 | |
| 670 | THREADED_TEST(Regress433458) { |
| 671 | LocalContext env; |
| 672 | v8::Isolate* isolate = env->GetIsolate(); |
| 673 | v8::HandleScope scope(isolate); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 674 | v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 675 | obj->SetHandler(v8::NamedPropertyHandlerConfiguration(EmptyGetter)); |
| 676 | obj->SetNativeDataProperty(v8_str("prop"), OneProperty); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 677 | CHECK(env->Global() |
| 678 | ->Set(env.local(), v8_str("obj"), |
| 679 | obj->NewInstance(env.local()).ToLocalChecked()) |
| 680 | .FromJust()); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 681 | CompileRun( |
| 682 | "Object.defineProperty(obj, 'prop', { writable: false });" |
| 683 | "Object.defineProperty(obj, 'prop', { writable: true });"); |
| 684 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 685 | |
| 686 | |
| 687 | static bool security_check_value = false; |
| 688 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 689 | static bool SecurityTestCallback(Local<v8::Context> accessing_context, |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 690 | Local<v8::Object> accessed_object, |
| 691 | Local<v8::Value> data) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 692 | return security_check_value; |
| 693 | } |
| 694 | |
| 695 | |
| 696 | TEST(PrototypeGetterAccessCheck) { |
| 697 | i::FLAG_allow_natives_syntax = true; |
| 698 | LocalContext env; |
| 699 | v8::Isolate* isolate = env->GetIsolate(); |
| 700 | v8::HandleScope scope(isolate); |
| 701 | auto fun_templ = v8::FunctionTemplate::New(isolate); |
| 702 | auto getter_templ = v8::FunctionTemplate::New(isolate, handle_property); |
| 703 | getter_templ->SetAcceptAnyReceiver(false); |
| 704 | fun_templ->InstanceTemplate()->SetAccessorProperty(v8_str("foo"), |
| 705 | getter_templ); |
| 706 | auto obj_templ = v8::ObjectTemplate::New(isolate); |
| 707 | obj_templ->SetAccessCheckCallback(SecurityTestCallback); |
| 708 | CHECK(env->Global() |
| 709 | ->Set(env.local(), v8_str("Fun"), |
| 710 | fun_templ->GetFunction(env.local()).ToLocalChecked()) |
| 711 | .FromJust()); |
| 712 | CHECK(env->Global() |
| 713 | ->Set(env.local(), v8_str("obj"), |
| 714 | obj_templ->NewInstance(env.local()).ToLocalChecked()) |
| 715 | .FromJust()); |
| 716 | CHECK(env->Global() |
| 717 | ->Set(env.local(), v8_str("obj2"), |
| 718 | obj_templ->NewInstance(env.local()).ToLocalChecked()) |
| 719 | .FromJust()); |
| 720 | |
| 721 | security_check_value = true; |
| 722 | CompileRun("var proto = new Fun();"); |
| 723 | CompileRun("obj.__proto__ = proto;"); |
| 724 | ExpectInt32("proto.foo", 907); |
| 725 | |
| 726 | // Test direct. |
| 727 | security_check_value = true; |
| 728 | ExpectInt32("obj.foo", 907); |
| 729 | security_check_value = false; |
| 730 | { |
| 731 | v8::TryCatch try_catch(isolate); |
| 732 | CompileRun("obj.foo"); |
| 733 | CHECK(try_catch.HasCaught()); |
| 734 | } |
| 735 | |
| 736 | // Test through call. |
| 737 | security_check_value = true; |
| 738 | ExpectInt32("proto.__lookupGetter__('foo').call(obj)", 907); |
| 739 | security_check_value = false; |
| 740 | { |
| 741 | v8::TryCatch try_catch(isolate); |
| 742 | CompileRun("proto.__lookupGetter__('foo').call(obj)"); |
| 743 | CHECK(try_catch.HasCaught()); |
| 744 | } |
| 745 | |
| 746 | // Test ics. |
| 747 | CompileRun( |
| 748 | "function f() {" |
| 749 | " var x;" |
| 750 | " for (var i = 0; i < 4; i++) {" |
| 751 | " x = obj.foo;" |
| 752 | " }" |
| 753 | " return x;" |
| 754 | "}"); |
| 755 | |
| 756 | security_check_value = true; |
| 757 | ExpectInt32("f()", 907); |
| 758 | security_check_value = false; |
| 759 | { |
| 760 | v8::TryCatch try_catch(isolate); |
| 761 | CompileRun("f();"); |
| 762 | CHECK(try_catch.HasCaught()); |
| 763 | } |
| 764 | |
| 765 | // Test crankshaft. |
| 766 | CompileRun("%OptimizeFunctionOnNextCall(f);"); |
| 767 | |
| 768 | security_check_value = true; |
| 769 | ExpectInt32("f()", 907); |
| 770 | security_check_value = false; |
| 771 | { |
| 772 | v8::TryCatch try_catch(isolate); |
| 773 | CompileRun("f();"); |
| 774 | CHECK(try_catch.HasCaught()); |
| 775 | } |
| 776 | } |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 777 | |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 778 | static void CheckReceiver(Local<String> name, |
| 779 | const v8::PropertyCallbackInfo<v8::Value>& info) { |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 780 | CHECK(info.This()->IsObject()); |
| 781 | } |
| 782 | |
| 783 | TEST(Regress609134) { |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 784 | LocalContext env; |
| 785 | v8::Isolate* isolate = env->GetIsolate(); |
| 786 | v8::HandleScope scope(isolate); |
| 787 | auto fun_templ = v8::FunctionTemplate::New(isolate); |
| 788 | fun_templ->InstanceTemplate()->SetNativeDataProperty(v8_str("foo"), |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 789 | CheckReceiver); |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 790 | |
| 791 | CHECK(env->Global() |
| 792 | ->Set(env.local(), v8_str("Fun"), |
| 793 | fun_templ->GetFunction(env.local()).ToLocalChecked()) |
| 794 | .FromJust()); |
| 795 | |
| 796 | CompileRun( |
| 797 | "var f = new Fun();" |
| 798 | "Number.prototype.__proto__ = f;" |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 799 | "var a = 42;" |
| 800 | "for (var i = 0; i<3; i++) { a.foo; }"); |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 801 | } |