blob: f4e8fe8e4bd36b6f4f934c962ce4f28a4100ffca [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// 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
Ben Murdochb8a8cc12014-11-26 15:28:44 +000028#include <climits>
29#include <csignal>
30#include <map>
31#include <string>
Steve Blocka7e24c12009-10-30 11:49:00 +000032
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000033#include "test/cctest/test-api.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000034
Ben Murdochb8a8cc12014-11-26 15:28:44 +000035#if V8_OS_POSIX
36#include <unistd.h> // NOLINT
37#endif
38
39#include "include/v8-util.h"
40#include "src/api.h"
41#include "src/arguments.h"
42#include "src/base/platform/platform.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000043#include "src/base/smart-pointers.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000044#include "src/compilation-cache.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000045#include "src/debug/debug.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000046#include "src/execution.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000047#include "src/futex-emulation.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000048#include "src/objects.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000049#include "src/parsing/parser.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000050#include "src/unicode-inl.h"
51#include "src/utils.h"
52#include "src/vm-state.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000053#include "test/cctest/heap/heap-tester.h"
54#include "test/cctest/heap/utils-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000055
Ben Murdoch257744e2011-11-30 15:57:28 +000056static const bool kLogThreading = false;
Steve Blockd0582a62009-12-15 09:54:21 +000057
Ben Murdochb8a8cc12014-11-26 15:28:44 +000058using ::v8::Boolean;
59using ::v8::BooleanObject;
Steve Block44f0eee2011-05-26 01:26:41 +010060using ::v8::Context;
Steve Blocka7e24c12009-10-30 11:49:00 +000061using ::v8::Extension;
Steve Block44f0eee2011-05-26 01:26:41 +010062using ::v8::Function;
Ben Murdoch8b112d22011-06-08 16:22:53 +010063using ::v8::FunctionTemplate;
Steve Block44f0eee2011-05-26 01:26:41 +010064using ::v8::HandleScope;
65using ::v8::Local;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000066using ::v8::Maybe;
Ben Murdoch8b112d22011-06-08 16:22:53 +010067using ::v8::Message;
68using ::v8::MessageCallback;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000069using ::v8::Name;
70using ::v8::None;
Steve Block44f0eee2011-05-26 01:26:41 +010071using ::v8::Object;
72using ::v8::ObjectTemplate;
73using ::v8::Persistent;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000074using ::v8::PropertyAttribute;
Steve Block44f0eee2011-05-26 01:26:41 +010075using ::v8::Script;
Ben Murdoch8b112d22011-06-08 16:22:53 +010076using ::v8::StackTrace;
Steve Block44f0eee2011-05-26 01:26:41 +010077using ::v8::String;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000078using ::v8::Symbol;
Ben Murdoch8b112d22011-06-08 16:22:53 +010079using ::v8::TryCatch;
80using ::v8::Undefined;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000081using ::v8::UniqueId;
Steve Block44f0eee2011-05-26 01:26:41 +010082using ::v8::V8;
Ben Murdoch8b112d22011-06-08 16:22:53 +010083using ::v8::Value;
Steve Blocka7e24c12009-10-30 11:49:00 +000084
Steve Blocka7e24c12009-10-30 11:49:00 +000085
Ben Murdochb8a8cc12014-11-26 15:28:44 +000086#define THREADED_PROFILED_TEST(Name) \
87 static void Test##Name(); \
88 TEST(Name##WithProfiler) { \
89 RunWithProfiler(&Test##Name); \
90 } \
91 THREADED_TEST(Name)
Leon Clarked91b9f72010-01-27 17:25:45 +000092
93
Ben Murdochb8a8cc12014-11-26 15:28:44 +000094void RunWithProfiler(void (*test)()) {
95 LocalContext env;
96 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000097 v8::Local<v8::String> profile_name = v8_str("my_profile1");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000098 v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
Leon Clarkef7060e22010-06-03 12:02:55 +010099
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000100 cpu_profiler->StartProfiling(profile_name);
101 (*test)();
102 reinterpret_cast<i::CpuProfiler*>(cpu_profiler)->DeleteAllProfiles();
Iain Merrick75681382010-08-19 15:07:18 +0100103}
104
105
Steve Blocka7e24c12009-10-30 11:49:00 +0000106static int signature_callback_count;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000107static Local<Value> signature_expected_receiver;
108static void IncrementingSignatureCallback(
109 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000110 ApiTestFuzzer::Fuzz();
111 signature_callback_count++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000112 CHECK(signature_expected_receiver->Equals(
113 args.GetIsolate()->GetCurrentContext(),
114 args.Holder())
115 .FromJust());
116 CHECK(signature_expected_receiver->Equals(
117 args.GetIsolate()->GetCurrentContext(),
118 args.This())
119 .FromJust());
120 v8::Local<v8::Array> result =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000121 v8::Array::New(args.GetIsolate(), args.Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000122 for (int i = 0; i < args.Length(); i++) {
123 CHECK(result->Set(args.GetIsolate()->GetCurrentContext(),
124 v8::Integer::New(args.GetIsolate(), i), args[i])
125 .FromJust());
126 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000127 args.GetReturnValue().Set(result);
Steve Blocka7e24c12009-10-30 11:49:00 +0000128}
129
130
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000131static void Returns42(const v8::FunctionCallbackInfo<v8::Value>& info) {
132 info.GetReturnValue().Set(42);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000133}
134
135
136// Tests that call v8::V8::Dispose() cannot be threaded.
137UNINITIALIZED_TEST(InitializeAndDisposeOnce) {
138 CHECK(v8::V8::Initialize());
139 CHECK(v8::V8::Dispose());
140}
141
142
143// Tests that call v8::V8::Dispose() cannot be threaded.
144UNINITIALIZED_TEST(InitializeAndDisposeMultiple) {
145 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
146 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
147 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
148 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
149 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
Steve Blocka7e24c12009-10-30 11:49:00 +0000150}
151
152
153THREADED_TEST(Handles) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000154 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000155 Local<Context> local_env;
156 {
157 LocalContext env;
158 local_env = env.local();
159 }
160
161 // Local context should still be live.
162 CHECK(!local_env.IsEmpty());
163 local_env->Enter();
164
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000165 v8::Local<v8::Primitive> undef = v8::Undefined(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000166 CHECK(!undef.IsEmpty());
167 CHECK(undef->IsUndefined());
168
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000169 const char* source = "1 + 2 + 3";
170 Local<Script> script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000171 CHECK_EQ(6, v8_run_int32value(script));
Steve Blocka7e24c12009-10-30 11:49:00 +0000172
173 local_env->Exit();
174}
175
176
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000177THREADED_TEST(IsolateOfContext) {
178 v8::HandleScope scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000179 v8::Local<Context> env = Context::New(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000180
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000181 CHECK(!env->GetIsolate()->InContext());
182 CHECK(env->GetIsolate() == CcTest::isolate());
183 env->Enter();
184 CHECK(env->GetIsolate()->InContext());
185 CHECK(env->GetIsolate() == CcTest::isolate());
186 env->Exit();
187 CHECK(!env->GetIsolate()->InContext());
188 CHECK(env->GetIsolate() == CcTest::isolate());
189}
190
191
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400192static void TestSignature(const char* loop_js, Local<Value> receiver,
193 v8::Isolate* isolate) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000194 i::ScopedVector<char> source(200);
195 i::SNPrintF(source,
196 "for (var i = 0; i < 10; i++) {"
197 " %s"
198 "}",
199 loop_js);
200 signature_callback_count = 0;
201 signature_expected_receiver = receiver;
202 bool expected_to_throw = receiver.IsEmpty();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000203 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000204 CompileRun(source.start());
205 CHECK_EQ(expected_to_throw, try_catch.HasCaught());
206 if (!expected_to_throw) {
207 CHECK_EQ(10, signature_callback_count);
208 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000209 CHECK(v8_str("TypeError: Illegal invocation")
210 ->Equals(isolate->GetCurrentContext(),
211 try_catch.Exception()
212 ->ToString(isolate->GetCurrentContext())
213 .ToLocalChecked())
214 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000215 }
216}
217
218
219THREADED_TEST(ReceiverSignature) {
220 LocalContext env;
221 v8::Isolate* isolate = env->GetIsolate();
222 v8::HandleScope scope(isolate);
223 // Setup templates.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000224 v8::Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
225 v8::Local<v8::Signature> sig = v8::Signature::New(isolate, fun);
226 v8::Local<v8::FunctionTemplate> callback_sig = v8::FunctionTemplate::New(
227 isolate, IncrementingSignatureCallback, Local<Value>(), sig);
228 v8::Local<v8::FunctionTemplate> callback =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000229 v8::FunctionTemplate::New(isolate, IncrementingSignatureCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000230 v8::Local<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000231 sub_fun->Inherit(fun);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000232 v8::Local<v8::FunctionTemplate> unrel_fun =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000233 v8::FunctionTemplate::New(isolate);
234 // Install properties.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000235 v8::Local<v8::ObjectTemplate> fun_proto = fun->PrototypeTemplate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000236 fun_proto->Set(v8_str("prop_sig"), callback_sig);
237 fun_proto->Set(v8_str("prop"), callback);
238 fun_proto->SetAccessorProperty(
239 v8_str("accessor_sig"), callback_sig, callback_sig);
240 fun_proto->SetAccessorProperty(v8_str("accessor"), callback, callback);
241 // Instantiate templates.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000242 Local<Value> fun_instance =
243 fun->InstanceTemplate()->NewInstance(env.local()).ToLocalChecked();
244 Local<Value> sub_fun_instance =
245 sub_fun->InstanceTemplate()->NewInstance(env.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000246 // Setup global variables.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000247 CHECK(env->Global()
248 ->Set(env.local(), v8_str("Fun"),
249 fun->GetFunction(env.local()).ToLocalChecked())
250 .FromJust());
251 CHECK(env->Global()
252 ->Set(env.local(), v8_str("UnrelFun"),
253 unrel_fun->GetFunction(env.local()).ToLocalChecked())
254 .FromJust());
255 CHECK(env->Global()
256 ->Set(env.local(), v8_str("fun_instance"), fun_instance)
257 .FromJust());
258 CHECK(env->Global()
259 ->Set(env.local(), v8_str("sub_fun_instance"), sub_fun_instance)
260 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +0000261 CompileRun(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000262 "var accessor_sig_key = 'accessor_sig';"
263 "var accessor_key = 'accessor';"
264 "var prop_sig_key = 'prop_sig';"
265 "var prop_key = 'prop';"
266 ""
267 "function copy_props(obj) {"
268 " var keys = [accessor_sig_key, accessor_key, prop_sig_key, prop_key];"
269 " var source = Fun.prototype;"
270 " for (var i in keys) {"
271 " var key = keys[i];"
272 " var desc = Object.getOwnPropertyDescriptor(source, key);"
273 " Object.defineProperty(obj, key, desc);"
274 " }"
275 "}"
276 ""
277 "var obj = {};"
278 "copy_props(obj);"
279 "var unrel = new UnrelFun();"
280 "copy_props(unrel);");
281 // Test with and without ICs
282 const char* test_objects[] = {
283 "fun_instance", "sub_fun_instance", "obj", "unrel" };
284 unsigned bad_signature_start_offset = 2;
285 for (unsigned i = 0; i < arraysize(test_objects); i++) {
286 i::ScopedVector<char> source(200);
287 i::SNPrintF(
288 source, "var test_object = %s; test_object", test_objects[i]);
289 Local<Value> test_object = CompileRun(source.start());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400290 TestSignature("test_object.prop();", test_object, isolate);
291 TestSignature("test_object.accessor;", test_object, isolate);
292 TestSignature("test_object[accessor_key];", test_object, isolate);
293 TestSignature("test_object.accessor = 1;", test_object, isolate);
294 TestSignature("test_object[accessor_key] = 1;", test_object, isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000295 if (i >= bad_signature_start_offset) test_object = Local<Value>();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400296 TestSignature("test_object.prop_sig();", test_object, isolate);
297 TestSignature("test_object.accessor_sig;", test_object, isolate);
298 TestSignature("test_object[accessor_sig_key];", test_object, isolate);
299 TestSignature("test_object.accessor_sig = 1;", test_object, isolate);
300 TestSignature("test_object[accessor_sig_key] = 1;", test_object, isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000301 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000302}
303
304
Steve Blocka7e24c12009-10-30 11:49:00 +0000305THREADED_TEST(HulIgennem) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000306 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000307 v8::Isolate* isolate = env->GetIsolate();
308 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000309 v8::Local<v8::Primitive> undef = v8::Undefined(isolate);
310 Local<String> undef_str = undef->ToString(env.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000311 char* value = i::NewArray<char>(undef_str->Utf8Length() + 1);
312 undef_str->WriteUtf8(value);
Steve Blocka7e24c12009-10-30 11:49:00 +0000313 CHECK_EQ(0, strcmp(value, "undefined"));
314 i::DeleteArray(value);
315}
316
317
318THREADED_TEST(Access) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000319 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000320 v8::Isolate* isolate = env->GetIsolate();
321 v8::HandleScope scope(isolate);
322 Local<v8::Object> obj = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000323 Local<Value> foo_before =
324 obj->Get(env.local(), v8_str("foo")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000325 CHECK(foo_before->IsUndefined());
326 Local<String> bar_str = v8_str("bar");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000327 CHECK(obj->Set(env.local(), v8_str("foo"), bar_str).FromJust());
328 Local<Value> foo_after =
329 obj->Get(env.local(), v8_str("foo")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000330 CHECK(!foo_after->IsUndefined());
331 CHECK(foo_after->IsString());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000332 CHECK(bar_str->Equals(env.local(), foo_after).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +0000333}
334
335
Steve Block6ded16b2010-05-10 14:33:55 +0100336THREADED_TEST(AccessElement) {
Steve Block6ded16b2010-05-10 14:33:55 +0100337 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000338 v8::HandleScope scope(env->GetIsolate());
339 Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000340 Local<Value> before = obj->Get(env.local(), 1).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +0100341 CHECK(before->IsUndefined());
342 Local<String> bar_str = v8_str("bar");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000343 CHECK(obj->Set(env.local(), 1, bar_str).FromJust());
344 Local<Value> after = obj->Get(env.local(), 1).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +0100345 CHECK(!after->IsUndefined());
346 CHECK(after->IsString());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000347 CHECK(bar_str->Equals(env.local(), after).FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +0100348
349 Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000350 CHECK(v8_str("a")
351 ->Equals(env.local(), value->Get(env.local(), 0).ToLocalChecked())
352 .FromJust());
353 CHECK(v8_str("b")
354 ->Equals(env.local(), value->Get(env.local(), 1).ToLocalChecked())
355 .FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +0100356}
357
358
Steve Blocka7e24c12009-10-30 11:49:00 +0000359THREADED_TEST(Script) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000360 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000361 v8::HandleScope scope(env->GetIsolate());
362 const char* source = "1 + 2 + 3";
363 Local<Script> script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000364 CHECK_EQ(6, v8_run_int32value(script));
Steve Blocka7e24c12009-10-30 11:49:00 +0000365}
366
367
Steve Blocka7e24c12009-10-30 11:49:00 +0000368class TestResource: public String::ExternalStringResource {
369 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000370 explicit TestResource(uint16_t* data, int* counter = NULL,
371 bool owning_data = true)
372 : data_(data), length_(0), counter_(counter), owning_data_(owning_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000373 while (data[length_]) ++length_;
374 }
375
376 ~TestResource() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000377 if (owning_data_) i::DeleteArray(data_);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000378 if (counter_ != NULL) ++*counter_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000379 }
380
381 const uint16_t* data() const {
382 return data_;
383 }
384
385 size_t length() const {
386 return length_;
387 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000388
Steve Blocka7e24c12009-10-30 11:49:00 +0000389 private:
390 uint16_t* data_;
391 size_t length_;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000392 int* counter_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000393 bool owning_data_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000394};
395
396
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000397class TestOneByteResource : public String::ExternalOneByteStringResource {
Steve Blocka7e24c12009-10-30 11:49:00 +0000398 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000399 explicit TestOneByteResource(const char* data, int* counter = NULL,
400 size_t offset = 0)
401 : orig_data_(data),
402 data_(data + offset),
403 length_(strlen(data) - offset),
404 counter_(counter) {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000405
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000406 ~TestOneByteResource() {
407 i::DeleteArray(orig_data_);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000408 if (counter_ != NULL) ++*counter_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000409 }
410
411 const char* data() const {
412 return data_;
413 }
414
415 size_t length() const {
416 return length_;
417 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000418
Steve Blocka7e24c12009-10-30 11:49:00 +0000419 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000420 const char* orig_data_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000421 const char* data_;
422 size_t length_;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000423 int* counter_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000424};
425
426
Steve Blocka7e24c12009-10-30 11:49:00 +0000427THREADED_TEST(ScriptUsingStringResource) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000428 int dispose_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000429 const char* c_source = "1 + 2 * 3";
430 uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
431 {
Steve Blocka7e24c12009-10-30 11:49:00 +0000432 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000433 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000434 TestResource* resource = new TestResource(two_byte_source, &dispose_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000435 Local<String> source =
436 String::NewExternalTwoByte(env->GetIsolate(), resource)
437 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000438 Local<Script> script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000439 Local<Value> value = script->Run(env.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000440 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000441 CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +0000442 CHECK(source->IsExternal());
443 CHECK_EQ(resource,
444 static_cast<TestResource*>(source->GetExternalStringResource()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000445 String::Encoding encoding = String::UNKNOWN_ENCODING;
446 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
447 source->GetExternalStringResourceBase(&encoding));
448 CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000449 CcTest::heap()->CollectAllGarbage();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000450 CHECK_EQ(0, dispose_count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000451 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000452 CcTest::i_isolate()->compilation_cache()->Clear();
453 CcTest::heap()->CollectAllAvailableGarbage();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000454 CHECK_EQ(1, dispose_count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000455}
456
457
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000458THREADED_TEST(ScriptUsingOneByteStringResource) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000459 int dispose_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000460 const char* c_source = "1 + 2 * 3";
461 {
Steve Blocka7e24c12009-10-30 11:49:00 +0000462 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000463 v8::HandleScope scope(env->GetIsolate());
464 TestOneByteResource* resource =
465 new TestOneByteResource(i::StrDup(c_source), &dispose_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000466 Local<String> source =
467 String::NewExternalOneByte(env->GetIsolate(), resource)
468 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000469 CHECK(source->IsExternalOneByte());
470 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
471 source->GetExternalOneByteStringResource());
472 String::Encoding encoding = String::UNKNOWN_ENCODING;
473 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
474 source->GetExternalStringResourceBase(&encoding));
475 CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
476 Local<Script> script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000477 Local<Value> value = script->Run(env.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000478 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000479 CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
480 CcTest::heap()->CollectAllGarbage();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000481 CHECK_EQ(0, dispose_count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000482 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000483 CcTest::i_isolate()->compilation_cache()->Clear();
484 CcTest::heap()->CollectAllAvailableGarbage();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000485 CHECK_EQ(1, dispose_count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000486}
487
488
489THREADED_TEST(ScriptMakingExternalString) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000490 int dispose_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000491 uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
492 {
Steve Blocka7e24c12009-10-30 11:49:00 +0000493 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000494 v8::HandleScope scope(env->GetIsolate());
495 Local<String> source =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000496 String::NewFromTwoByte(env->GetIsolate(), two_byte_source,
497 v8::NewStringType::kNormal)
498 .ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +0000499 // Trigger GCs so that the newly allocated string moves to old gen.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000500 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
501 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
502 CHECK_EQ(source->IsExternal(), false);
503 CHECK_EQ(source->IsExternalOneByte(), false);
504 String::Encoding encoding = String::UNKNOWN_ENCODING;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000505 CHECK(!source->GetExternalStringResourceBase(&encoding));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000506 CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000507 bool success = source->MakeExternal(new TestResource(two_byte_source,
508 &dispose_count));
Steve Blocka7e24c12009-10-30 11:49:00 +0000509 CHECK(success);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000510 Local<Script> script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000511 Local<Value> value = script->Run(env.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000512 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000513 CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
514 CcTest::heap()->CollectAllGarbage();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000515 CHECK_EQ(0, dispose_count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000516 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000517 CcTest::i_isolate()->compilation_cache()->Clear();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000518 CcTest::heap()->CollectAllGarbage();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000519 CHECK_EQ(1, dispose_count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000520}
521
522
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000523THREADED_TEST(ScriptMakingExternalOneByteString) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000524 int dispose_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000525 const char* c_source = "1 + 2 * 3";
526 {
Steve Blocka7e24c12009-10-30 11:49:00 +0000527 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000528 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000529 Local<String> source = v8_str(c_source);
Andrei Popescu402d9372010-02-26 13:31:12 +0000530 // Trigger GCs so that the newly allocated string moves to old gen.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000531 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
532 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
Steve Blocka7e24c12009-10-30 11:49:00 +0000533 bool success = source->MakeExternal(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000534 new TestOneByteResource(i::StrDup(c_source), &dispose_count));
Steve Blocka7e24c12009-10-30 11:49:00 +0000535 CHECK(success);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000536 Local<Script> script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000537 Local<Value> value = script->Run(env.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000538 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000539 CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
540 CcTest::heap()->CollectAllGarbage();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000541 CHECK_EQ(0, dispose_count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000542 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000543 CcTest::i_isolate()->compilation_cache()->Clear();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000544 CcTest::heap()->CollectAllGarbage();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000545 CHECK_EQ(1, dispose_count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000546}
547
548
Andrei Popescu402d9372010-02-26 13:31:12 +0000549TEST(MakingExternalStringConditions) {
Andrei Popescu402d9372010-02-26 13:31:12 +0000550 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000551 v8::HandleScope scope(env->GetIsolate());
Andrei Popescu402d9372010-02-26 13:31:12 +0000552
553 // Free some space in the new space so that we can check freshness.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000554 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
555 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
Andrei Popescu402d9372010-02-26 13:31:12 +0000556
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100557 uint16_t* two_byte_string = AsciiToTwoByteString("s1");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000558 Local<String> small_string =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000559 String::NewFromTwoByte(env->GetIsolate(), two_byte_string,
560 v8::NewStringType::kNormal)
561 .ToLocalChecked();
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100562 i::DeleteArray(two_byte_string);
563
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000564 // We should refuse to externalize small strings.
Andrei Popescu402d9372010-02-26 13:31:12 +0000565 CHECK(!small_string->CanMakeExternal());
566 // Trigger GCs so that the newly allocated string moves to old gen.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000567 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
568 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
Andrei Popescu402d9372010-02-26 13:31:12 +0000569 // Old space strings should be accepted.
570 CHECK(small_string->CanMakeExternal());
571
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100572 two_byte_string = AsciiToTwoByteString("small string 2");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000573 small_string = String::NewFromTwoByte(env->GetIsolate(), two_byte_string,
574 v8::NewStringType::kNormal)
575 .ToLocalChecked();
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100576 i::DeleteArray(two_byte_string);
577
Andrei Popescu402d9372010-02-26 13:31:12 +0000578 const int buf_size = 10 * 1024;
579 char* buf = i::NewArray<char>(buf_size);
580 memset(buf, 'a', buf_size);
581 buf[buf_size - 1] = '\0';
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100582
583 two_byte_string = AsciiToTwoByteString(buf);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000584 Local<String> large_string =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000585 String::NewFromTwoByte(env->GetIsolate(), two_byte_string,
586 v8::NewStringType::kNormal)
587 .ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +0000588 i::DeleteArray(buf);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100589 i::DeleteArray(two_byte_string);
Andrei Popescu402d9372010-02-26 13:31:12 +0000590 // Large strings should be immediately accepted.
591 CHECK(large_string->CanMakeExternal());
592}
593
594
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000595TEST(MakingExternalOneByteStringConditions) {
Andrei Popescu402d9372010-02-26 13:31:12 +0000596 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000597 v8::HandleScope scope(env->GetIsolate());
Andrei Popescu402d9372010-02-26 13:31:12 +0000598
599 // Free some space in the new space so that we can check freshness.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000600 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
601 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
Andrei Popescu402d9372010-02-26 13:31:12 +0000602
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000603 Local<String> small_string = v8_str("s1");
604 // We should refuse to externalize small strings.
Andrei Popescu402d9372010-02-26 13:31:12 +0000605 CHECK(!small_string->CanMakeExternal());
606 // Trigger GCs so that the newly allocated string moves to old gen.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000607 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
608 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
Andrei Popescu402d9372010-02-26 13:31:12 +0000609 // Old space strings should be accepted.
610 CHECK(small_string->CanMakeExternal());
611
Andrei Popescu402d9372010-02-26 13:31:12 +0000612 const int buf_size = 10 * 1024;
613 char* buf = i::NewArray<char>(buf_size);
614 memset(buf, 'a', buf_size);
615 buf[buf_size - 1] = '\0';
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000616 Local<String> large_string = v8_str(buf);
Andrei Popescu402d9372010-02-26 13:31:12 +0000617 i::DeleteArray(buf);
618 // Large strings should be immediately accepted.
619 CHECK(large_string->CanMakeExternal());
620}
621
622
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000623TEST(MakingExternalUnalignedOneByteString) {
624 LocalContext env;
625 v8::HandleScope scope(env->GetIsolate());
626
627 CompileRun("function cons(a, b) { return a + b; }"
628 "function slice(a) { return a.substring(1); }");
629 // Create a cons string that will land in old pointer space.
630 Local<String> cons = Local<String>::Cast(CompileRun(
631 "cons('abcdefghijklm', 'nopqrstuvwxyz');"));
632 // Create a sliced string that will land in old pointer space.
633 Local<String> slice = Local<String>::Cast(CompileRun(
634 "slice('abcdefghijklmnopqrstuvwxyz');"));
635
636 // Trigger GCs so that the newly allocated string moves to old gen.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000637 SimulateFullSpace(CcTest::heap()->old_space());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000638 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
639 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
640
641 // Turn into external string with unaligned resource data.
642 const char* c_cons = "_abcdefghijklmnopqrstuvwxyz";
643 bool success =
644 cons->MakeExternal(new TestOneByteResource(i::StrDup(c_cons), NULL, 1));
645 CHECK(success);
646 const char* c_slice = "_bcdefghijklmnopqrstuvwxyz";
647 success =
648 slice->MakeExternal(new TestOneByteResource(i::StrDup(c_slice), NULL, 1));
649 CHECK(success);
650
651 // Trigger GCs and force evacuation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000652 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000653 CcTest::heap()->CollectAllGarbage(i::Heap::kReduceMemoryFootprintMask);
Steve Blocka7e24c12009-10-30 11:49:00 +0000654}
655
656
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000657THREADED_TEST(UsingExternalString) {
658 i::Factory* factory = CcTest::i_isolate()->factory();
Steve Blocka7e24c12009-10-30 11:49:00 +0000659 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000660 v8::HandleScope scope(CcTest::isolate());
661 uint16_t* two_byte_string = AsciiToTwoByteString("test string");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000662 Local<String> string =
663 String::NewExternalTwoByte(CcTest::isolate(),
664 new TestResource(two_byte_string))
665 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000666 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
667 // Trigger GCs so that the newly allocated string moves to old gen.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000668 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
669 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
670 i::Handle<i::String> isymbol =
671 factory->InternalizeString(istring);
672 CHECK(isymbol->IsInternalizedString());
Steve Blocka7e24c12009-10-30 11:49:00 +0000673 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000674 CcTest::heap()->CollectAllGarbage();
675 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000676}
677
678
679THREADED_TEST(UsingExternalOneByteString) {
680 i::Factory* factory = CcTest::i_isolate()->factory();
681 {
682 v8::HandleScope scope(CcTest::isolate());
683 const char* one_byte_string = "test string";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000684 Local<String> string =
685 String::NewExternalOneByte(
686 CcTest::isolate(),
687 new TestOneByteResource(i::StrDup(one_byte_string)))
688 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000689 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
690 // Trigger GCs so that the newly allocated string moves to old gen.
691 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
692 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
693 i::Handle<i::String> isymbol =
694 factory->InternalizeString(istring);
695 CHECK(isymbol->IsInternalizedString());
696 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000697 CcTest::heap()->CollectAllGarbage();
698 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +0000699}
700
701
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400702class RandomLengthResource : public v8::String::ExternalStringResource {
703 public:
704 explicit RandomLengthResource(int length) : length_(length) {}
705 virtual const uint16_t* data() const { return string_; }
706 virtual size_t length() const { return length_; }
707
708 private:
709 uint16_t string_[10];
710 int length_;
711};
712
713
714class RandomLengthOneByteResource
715 : public v8::String::ExternalOneByteStringResource {
716 public:
717 explicit RandomLengthOneByteResource(int length) : length_(length) {}
718 virtual const char* data() const { return string_; }
719 virtual size_t length() const { return length_; }
720
721 private:
722 char string_[10];
723 int length_;
724};
725
726
727THREADED_TEST(NewExternalForVeryLongString) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000728 auto isolate = CcTest::isolate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400729 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000730 v8::HandleScope scope(isolate);
731 v8::TryCatch try_catch(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400732 RandomLengthOneByteResource r(1 << 30);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000733 v8::MaybeLocal<v8::String> maybe_str =
734 v8::String::NewExternalOneByte(isolate, &r);
735 CHECK(maybe_str.IsEmpty());
736 CHECK(!try_catch.HasCaught());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400737 }
738
739 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000740 v8::HandleScope scope(isolate);
741 v8::TryCatch try_catch(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400742 RandomLengthResource r(1 << 30);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000743 v8::MaybeLocal<v8::String> maybe_str =
744 v8::String::NewExternalTwoByte(isolate, &r);
745 CHECK(maybe_str.IsEmpty());
746 CHECK(!try_catch.HasCaught());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400747 }
748}
749
750
Leon Clarkee46be812010-01-19 14:06:41 +0000751THREADED_TEST(ScavengeExternalString) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000752 i::FLAG_stress_compaction = false;
753 i::FLAG_gc_global = false;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000754 int dispose_count = 0;
Steve Block6ded16b2010-05-10 14:33:55 +0100755 bool in_new_space = false;
Leon Clarkee46be812010-01-19 14:06:41 +0000756 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000757 v8::HandleScope scope(CcTest::isolate());
Leon Clarkee46be812010-01-19 14:06:41 +0000758 uint16_t* two_byte_string = AsciiToTwoByteString("test string");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000759 Local<String> string =
760 String::NewExternalTwoByte(
761 CcTest::isolate(),
762 new TestResource(two_byte_string, &dispose_count))
763 .ToLocalChecked();
Leon Clarkee46be812010-01-19 14:06:41 +0000764 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000765 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
766 in_new_space = CcTest::heap()->InNewSpace(*istring);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000767 CHECK(in_new_space || CcTest::heap()->old_space()->Contains(*istring));
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000768 CHECK_EQ(0, dispose_count);
Leon Clarkee46be812010-01-19 14:06:41 +0000769 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000770 CcTest::heap()->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_SPACE);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000771 CHECK_EQ(1, dispose_count);
Leon Clarkee46be812010-01-19 14:06:41 +0000772}
773
774
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000775THREADED_TEST(ScavengeExternalOneByteString) {
776 i::FLAG_stress_compaction = false;
777 i::FLAG_gc_global = false;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000778 int dispose_count = 0;
Steve Block6ded16b2010-05-10 14:33:55 +0100779 bool in_new_space = false;
Leon Clarkee46be812010-01-19 14:06:41 +0000780 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000781 v8::HandleScope scope(CcTest::isolate());
Leon Clarkee46be812010-01-19 14:06:41 +0000782 const char* one_byte_string = "test string";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000783 Local<String> string =
784 String::NewExternalOneByte(
785 CcTest::isolate(),
786 new TestOneByteResource(i::StrDup(one_byte_string), &dispose_count))
787 .ToLocalChecked();
Leon Clarkee46be812010-01-19 14:06:41 +0000788 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000789 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
790 in_new_space = CcTest::heap()->InNewSpace(*istring);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000791 CHECK(in_new_space || CcTest::heap()->old_space()->Contains(*istring));
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000792 CHECK_EQ(0, dispose_count);
Leon Clarkee46be812010-01-19 14:06:41 +0000793 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000794 CcTest::heap()->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_SPACE);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000795 CHECK_EQ(1, dispose_count);
Leon Clarkee46be812010-01-19 14:06:41 +0000796}
797
798
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000799class TestOneByteResourceWithDisposeControl : public TestOneByteResource {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100800 public:
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000801 // Only used by non-threaded tests, so it can use static fields.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100802 static int dispose_calls;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000803 static int dispose_count;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100804
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000805 TestOneByteResourceWithDisposeControl(const char* data, bool dispose)
806 : TestOneByteResource(data, &dispose_count), dispose_(dispose) {}
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100807
808 void Dispose() {
809 ++dispose_calls;
810 if (dispose_) delete this;
811 }
812 private:
813 bool dispose_;
814};
815
816
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000817int TestOneByteResourceWithDisposeControl::dispose_count = 0;
818int TestOneByteResourceWithDisposeControl::dispose_calls = 0;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100819
820
821TEST(ExternalStringWithDisposeHandling) {
822 const char* c_source = "1 + 2 * 3";
823
824 // Use a stack allocated external string resource allocated object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000825 TestOneByteResourceWithDisposeControl::dispose_count = 0;
826 TestOneByteResourceWithDisposeControl::dispose_calls = 0;
827 TestOneByteResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100828 {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100829 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000830 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000831 Local<String> source =
832 String::NewExternalOneByte(env->GetIsolate(), &res_stack)
833 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000834 Local<Script> script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000835 Local<Value> value = script->Run(env.local()).ToLocalChecked();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100836 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000837 CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000838 CcTest::heap()->CollectAllAvailableGarbage();
839 CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100840 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000841 CcTest::i_isolate()->compilation_cache()->Clear();
842 CcTest::heap()->CollectAllAvailableGarbage();
843 CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
844 CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100845
846 // Use a heap allocated external string resource allocated object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000847 TestOneByteResourceWithDisposeControl::dispose_count = 0;
848 TestOneByteResourceWithDisposeControl::dispose_calls = 0;
849 TestOneByteResource* res_heap =
850 new TestOneByteResourceWithDisposeControl(i::StrDup(c_source), true);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100851 {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100852 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000853 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000854 Local<String> source =
855 String::NewExternalOneByte(env->GetIsolate(), res_heap)
856 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000857 Local<Script> script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000858 Local<Value> value = script->Run(env.local()).ToLocalChecked();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100859 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000860 CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000861 CcTest::heap()->CollectAllAvailableGarbage();
862 CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100863 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000864 CcTest::i_isolate()->compilation_cache()->Clear();
865 CcTest::heap()->CollectAllAvailableGarbage();
866 CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
867 CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_count);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100868}
869
870
Steve Block3ce2e202009-11-05 08:53:23 +0000871THREADED_TEST(StringConcat) {
872 {
Steve Block3ce2e202009-11-05 08:53:23 +0000873 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000874 v8::HandleScope scope(env->GetIsolate());
Steve Block3ce2e202009-11-05 08:53:23 +0000875 const char* one_byte_string_1 = "function a_times_t";
876 const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
877 const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
878 const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
879 const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
880 const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
881 const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
882 Local<String> left = v8_str(one_byte_string_1);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100883
884 uint16_t* two_byte_source = AsciiToTwoByteString(two_byte_string_1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000885 Local<String> right =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000886 String::NewFromTwoByte(env->GetIsolate(), two_byte_source,
887 v8::NewStringType::kNormal)
888 .ToLocalChecked();
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100889 i::DeleteArray(two_byte_source);
890
Steve Block3ce2e202009-11-05 08:53:23 +0000891 Local<String> source = String::Concat(left, right);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000892 right = String::NewExternalOneByte(
893 env->GetIsolate(),
894 new TestOneByteResource(i::StrDup(one_byte_extern_1)))
895 .ToLocalChecked();
Steve Block3ce2e202009-11-05 08:53:23 +0000896 source = String::Concat(source, right);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000897 right = String::NewExternalTwoByte(
898 env->GetIsolate(),
899 new TestResource(AsciiToTwoByteString(two_byte_extern_1)))
900 .ToLocalChecked();
Steve Block3ce2e202009-11-05 08:53:23 +0000901 source = String::Concat(source, right);
902 right = v8_str(one_byte_string_2);
903 source = String::Concat(source, right);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100904
905 two_byte_source = AsciiToTwoByteString(two_byte_string_2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000906 right = String::NewFromTwoByte(env->GetIsolate(), two_byte_source,
907 v8::NewStringType::kNormal)
908 .ToLocalChecked();
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100909 i::DeleteArray(two_byte_source);
910
Steve Block3ce2e202009-11-05 08:53:23 +0000911 source = String::Concat(source, right);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000912 right = String::NewExternalTwoByte(
913 env->GetIsolate(),
914 new TestResource(AsciiToTwoByteString(two_byte_extern_2)))
915 .ToLocalChecked();
Steve Block3ce2e202009-11-05 08:53:23 +0000916 source = String::Concat(source, right);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000917 Local<Script> script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000918 Local<Value> value = script->Run(env.local()).ToLocalChecked();
Steve Block3ce2e202009-11-05 08:53:23 +0000919 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000920 CHECK_EQ(68, value->Int32Value(env.local()).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +0000921 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000922 CcTest::i_isolate()->compilation_cache()->Clear();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000923 CcTest::heap()->CollectAllGarbage();
924 CcTest::heap()->CollectAllGarbage();
Steve Block3ce2e202009-11-05 08:53:23 +0000925}
926
927
Steve Blocka7e24c12009-10-30 11:49:00 +0000928THREADED_TEST(GlobalProperties) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000929 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000930 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000931 v8::Local<v8::Object> global = env->Global();
932 CHECK(global->Set(env.local(), v8_str("pi"), v8_num(3.1415926)).FromJust());
933 Local<Value> pi = global->Get(env.local(), v8_str("pi")).ToLocalChecked();
934 CHECK_EQ(3.1415926, pi->NumberValue(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000935}
936
937
938static void handle_callback_impl(const v8::FunctionCallbackInfo<Value>& info,
939 i::Address callback) {
940 ApiTestFuzzer::Fuzz();
941 CheckReturnValue(info, callback);
942 info.GetReturnValue().Set(v8_str("bad value"));
943 info.GetReturnValue().Set(v8_num(102));
944}
945
946
947static void handle_callback(const v8::FunctionCallbackInfo<Value>& info) {
948 return handle_callback_impl(info, FUNCTION_ADDR(handle_callback));
949}
950
951
952static void handle_callback_2(const v8::FunctionCallbackInfo<Value>& info) {
953 return handle_callback_impl(info, FUNCTION_ADDR(handle_callback_2));
954}
955
956static void construct_callback(
957 const v8::FunctionCallbackInfo<Value>& info) {
958 ApiTestFuzzer::Fuzz();
959 CheckReturnValue(info, FUNCTION_ADDR(construct_callback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000960 CHECK(
961 info.This()
962 ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("x"), v8_num(1))
963 .FromJust());
964 CHECK(
965 info.This()
966 ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(2))
967 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000968 info.GetReturnValue().Set(v8_str("bad value"));
969 info.GetReturnValue().Set(info.This());
970}
971
972
973static void Return239Callback(
974 Local<String> name, const v8::PropertyCallbackInfo<Value>& info) {
975 ApiTestFuzzer::Fuzz();
976 CheckReturnValue(info, FUNCTION_ADDR(Return239Callback));
977 info.GetReturnValue().Set(v8_str("bad value"));
978 info.GetReturnValue().Set(v8_num(239));
979}
980
981
982template<typename Handler>
983static void TestFunctionTemplateInitializer(Handler handler,
984 Handler handler_2) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000985 // Test constructor calls.
986 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000987 LocalContext env;
988 v8::Isolate* isolate = env->GetIsolate();
989 v8::HandleScope scope(isolate);
990
Steve Blocka7e24c12009-10-30 11:49:00 +0000991 Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000992 v8::FunctionTemplate::New(isolate, handler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000993 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
994 CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000995 Local<Script> script = v8_compile("obj()");
996 for (int i = 0; i < 30; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000997 CHECK_EQ(102, v8_run_int32value(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000998 }
999 }
1000 // Use SetCallHandler to initialize a function template, should work like
1001 // the previous one.
1002 {
1003 LocalContext env;
1004 v8::Isolate* isolate = env->GetIsolate();
1005 v8::HandleScope scope(isolate);
1006
1007 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
1008 fun_templ->SetCallHandler(handler_2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001009 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
1010 CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001011 Local<Script> script = v8_compile("obj()");
1012 for (int i = 0; i < 30; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001013 CHECK_EQ(102, v8_run_int32value(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001014 }
1015 }
1016}
1017
1018
1019template<typename Constructor, typename Accessor>
1020static void TestFunctionTemplateAccessor(Constructor constructor,
1021 Accessor accessor) {
1022 LocalContext env;
1023 v8::HandleScope scope(env->GetIsolate());
1024
1025 Local<v8::FunctionTemplate> fun_templ =
1026 v8::FunctionTemplate::New(env->GetIsolate(), constructor);
1027 fun_templ->SetClassName(v8_str("funky"));
1028 fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), accessor);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001029 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
1030 CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
1031 Local<Value> result =
1032 v8_compile("(new obj()).toString()")->Run(env.local()).ToLocalChecked();
1033 CHECK(v8_str("[object funky]")->Equals(env.local(), result).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001034 CompileRun("var obj_instance = new obj();");
1035 Local<Script> script;
1036 script = v8_compile("obj_instance.x");
1037 for (int i = 0; i < 30; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001038 CHECK_EQ(1, v8_run_int32value(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001039 }
1040 script = v8_compile("obj_instance.m");
1041 for (int i = 0; i < 30; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001042 CHECK_EQ(239, v8_run_int32value(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001043 }
1044}
Steve Blocka7e24c12009-10-30 11:49:00 +00001045
Ben Murdochf87a2032010-10-22 12:50:53 +01001046
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001047THREADED_PROFILED_TEST(FunctionTemplate) {
1048 TestFunctionTemplateInitializer(handle_callback, handle_callback_2);
1049 TestFunctionTemplateAccessor(construct_callback, Return239Callback);
1050}
1051
1052
1053static void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
1054 ApiTestFuzzer::Fuzz();
1055 CheckReturnValue(info, FUNCTION_ADDR(SimpleCallback));
1056 info.GetReturnValue().Set(v8_num(51423 + info.Length()));
1057}
1058
1059
1060template<typename Callback>
1061static void TestSimpleCallback(Callback callback) {
1062 LocalContext env;
1063 v8::Isolate* isolate = env->GetIsolate();
1064 v8::HandleScope scope(isolate);
1065
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001066 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001067 v8::ObjectTemplate::New(isolate);
1068 object_template->Set(isolate, "callback",
1069 v8::FunctionTemplate::New(isolate, callback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001070 v8::Local<v8::Object> object =
1071 object_template->NewInstance(env.local()).ToLocalChecked();
1072 CHECK((*env)
1073 ->Global()
1074 ->Set(env.local(), v8_str("callback_object"), object)
1075 .FromJust());
1076 v8::Local<v8::Script> script;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001077 script = v8_compile("callback_object.callback(17)");
1078 for (int i = 0; i < 30; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001079 CHECK_EQ(51424, v8_run_int32value(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001080 }
1081 script = v8_compile("callback_object.callback(17, 24)");
1082 for (int i = 0; i < 30; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001083 CHECK_EQ(51425, v8_run_int32value(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001084 }
1085}
1086
1087
1088THREADED_PROFILED_TEST(SimpleCallback) {
1089 TestSimpleCallback(SimpleCallback);
1090}
1091
1092
1093template<typename T>
1094void FastReturnValueCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
1095
1096// constant return values
1097static int32_t fast_return_value_int32 = 471;
1098static uint32_t fast_return_value_uint32 = 571;
1099static const double kFastReturnValueDouble = 2.7;
1100// variable return values
1101static bool fast_return_value_bool = false;
1102enum ReturnValueOddball {
1103 kNullReturnValue,
1104 kUndefinedReturnValue,
1105 kEmptyStringReturnValue
1106};
1107static ReturnValueOddball fast_return_value_void;
1108static bool fast_return_value_object_is_empty = false;
1109
1110// Helper function to avoid compiler error: insufficient contextual information
1111// to determine type when applying FUNCTION_ADDR to a template function.
1112static i::Address address_of(v8::FunctionCallback callback) {
1113 return FUNCTION_ADDR(callback);
1114}
1115
1116template<>
1117void FastReturnValueCallback<int32_t>(
1118 const v8::FunctionCallbackInfo<v8::Value>& info) {
1119 CheckReturnValue(info, address_of(FastReturnValueCallback<int32_t>));
1120 info.GetReturnValue().Set(fast_return_value_int32);
1121}
1122
1123template<>
1124void FastReturnValueCallback<uint32_t>(
1125 const v8::FunctionCallbackInfo<v8::Value>& info) {
1126 CheckReturnValue(info, address_of(FastReturnValueCallback<uint32_t>));
1127 info.GetReturnValue().Set(fast_return_value_uint32);
1128}
1129
1130template<>
1131void FastReturnValueCallback<double>(
1132 const v8::FunctionCallbackInfo<v8::Value>& info) {
1133 CheckReturnValue(info, address_of(FastReturnValueCallback<double>));
1134 info.GetReturnValue().Set(kFastReturnValueDouble);
1135}
1136
1137template<>
1138void FastReturnValueCallback<bool>(
1139 const v8::FunctionCallbackInfo<v8::Value>& info) {
1140 CheckReturnValue(info, address_of(FastReturnValueCallback<bool>));
1141 info.GetReturnValue().Set(fast_return_value_bool);
1142}
1143
1144template<>
1145void FastReturnValueCallback<void>(
1146 const v8::FunctionCallbackInfo<v8::Value>& info) {
1147 CheckReturnValue(info, address_of(FastReturnValueCallback<void>));
1148 switch (fast_return_value_void) {
1149 case kNullReturnValue:
1150 info.GetReturnValue().SetNull();
1151 break;
1152 case kUndefinedReturnValue:
1153 info.GetReturnValue().SetUndefined();
1154 break;
1155 case kEmptyStringReturnValue:
1156 info.GetReturnValue().SetEmptyString();
1157 break;
1158 }
1159}
1160
1161template<>
1162void FastReturnValueCallback<Object>(
1163 const v8::FunctionCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001164 v8::Local<v8::Object> object;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001165 if (!fast_return_value_object_is_empty) {
1166 object = Object::New(info.GetIsolate());
1167 }
1168 info.GetReturnValue().Set(object);
1169}
1170
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001171template <typename T>
1172Local<Value> TestFastReturnValues() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001173 LocalContext env;
1174 v8::Isolate* isolate = env->GetIsolate();
1175 v8::EscapableHandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001176 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001177 v8::ObjectTemplate::New(isolate);
1178 v8::FunctionCallback callback = &FastReturnValueCallback<T>;
1179 object_template->Set(isolate, "callback",
1180 v8::FunctionTemplate::New(isolate, callback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001181 v8::Local<v8::Object> object =
1182 object_template->NewInstance(env.local()).ToLocalChecked();
1183 CHECK((*env)
1184 ->Global()
1185 ->Set(env.local(), v8_str("callback_object"), object)
1186 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001187 return scope.Escape(CompileRun("callback_object.callback()"));
1188}
1189
1190
1191THREADED_PROFILED_TEST(FastReturnValues) {
1192 LocalContext env;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001193 v8::Isolate* isolate = env->GetIsolate();
1194 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001195 v8::Local<v8::Value> value;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001196 // check int32_t and uint32_t
1197 int32_t int_values[] = {
1198 0, 234, -723,
1199 i::Smi::kMinValue, i::Smi::kMaxValue
1200 };
1201 for (size_t i = 0; i < arraysize(int_values); i++) {
1202 for (int modifier = -1; modifier <= 1; modifier++) {
1203 int int_value = int_values[i] + modifier;
1204 // check int32_t
1205 fast_return_value_int32 = int_value;
1206 value = TestFastReturnValues<int32_t>();
1207 CHECK(value->IsInt32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001208 CHECK_EQ(fast_return_value_int32,
1209 value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001210 // check uint32_t
1211 fast_return_value_uint32 = static_cast<uint32_t>(int_value);
1212 value = TestFastReturnValues<uint32_t>();
1213 CHECK(value->IsUint32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001214 CHECK_EQ(fast_return_value_uint32,
1215 value->Uint32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001216 }
1217 }
1218 // check double
1219 value = TestFastReturnValues<double>();
1220 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001221 CHECK_EQ(kFastReturnValueDouble,
1222 value->ToNumber(env.local()).ToLocalChecked()->Value());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001223 // check bool values
1224 for (int i = 0; i < 2; i++) {
1225 fast_return_value_bool = i == 0;
1226 value = TestFastReturnValues<bool>();
1227 CHECK(value->IsBoolean());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001228 CHECK_EQ(fast_return_value_bool,
1229 value->ToBoolean(env.local()).ToLocalChecked()->Value());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001230 }
1231 // check oddballs
1232 ReturnValueOddball oddballs[] = {
1233 kNullReturnValue,
1234 kUndefinedReturnValue,
1235 kEmptyStringReturnValue
1236 };
1237 for (size_t i = 0; i < arraysize(oddballs); i++) {
1238 fast_return_value_void = oddballs[i];
1239 value = TestFastReturnValues<void>();
1240 switch (fast_return_value_void) {
1241 case kNullReturnValue:
1242 CHECK(value->IsNull());
1243 break;
1244 case kUndefinedReturnValue:
1245 CHECK(value->IsUndefined());
1246 break;
1247 case kEmptyStringReturnValue:
1248 CHECK(value->IsString());
1249 CHECK_EQ(0, v8::String::Cast(*value)->Length());
1250 break;
1251 }
1252 }
1253 // check handles
1254 fast_return_value_object_is_empty = false;
1255 value = TestFastReturnValues<Object>();
1256 CHECK(value->IsObject());
1257 fast_return_value_object_is_empty = true;
1258 value = TestFastReturnValues<Object>();
1259 CHECK(value->IsUndefined());
1260}
1261
1262
1263THREADED_TEST(FunctionTemplateSetLength) {
1264 LocalContext env;
1265 v8::Isolate* isolate = env->GetIsolate();
1266 v8::HandleScope scope(isolate);
1267 {
1268 Local<v8::FunctionTemplate> fun_templ =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001269 v8::FunctionTemplate::New(isolate, handle_callback, Local<v8::Value>(),
1270 Local<v8::Signature>(), 23);
1271 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
1272 CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001273 Local<Script> script = v8_compile("obj.length");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001274 CHECK_EQ(23, v8_run_int32value(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001275 }
1276 {
1277 Local<v8::FunctionTemplate> fun_templ =
1278 v8::FunctionTemplate::New(isolate, handle_callback);
1279 fun_templ->SetLength(22);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001280 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
1281 CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001282 Local<Script> script = v8_compile("obj.length");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001283 CHECK_EQ(22, v8_run_int32value(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001284 }
1285 {
1286 // Without setting length it defaults to 0.
1287 Local<v8::FunctionTemplate> fun_templ =
1288 v8::FunctionTemplate::New(isolate, handle_callback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001289 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
1290 CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001291 Local<Script> script = v8_compile("obj.length");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001292 CHECK_EQ(0, v8_run_int32value(script));
Steve Blocka7e24c12009-10-30 11:49:00 +00001293 }
1294}
1295
1296
Ben Murdochb8e0da22011-05-16 14:20:40 +01001297static void* expected_ptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001298static void callback(const v8::FunctionCallbackInfo<v8::Value>& args) {
1299 void* ptr = v8::External::Cast(*args.Data())->Value();
Ben Murdochb8e0da22011-05-16 14:20:40 +01001300 CHECK_EQ(expected_ptr, ptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001301 args.GetReturnValue().Set(true);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001302}
1303
1304
1305static void TestExternalPointerWrapping() {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001306 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001307 v8::Isolate* isolate = env->GetIsolate();
1308 v8::HandleScope scope(isolate);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001309
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001310 v8::Local<v8::Value> data = v8::External::New(isolate, expected_ptr);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001311
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001312 v8::Local<v8::Object> obj = v8::Object::New(isolate);
1313 CHECK(obj->Set(env.local(), v8_str("func"),
1314 v8::FunctionTemplate::New(isolate, callback, data)
1315 ->GetFunction(env.local())
1316 .ToLocalChecked())
1317 .FromJust());
1318 CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001319
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001320 CHECK(CompileRun("function foo() {\n"
1321 " for (var i = 0; i < 13; i++) obj.func();\n"
1322 "}\n"
1323 "foo(), true")
1324 ->BooleanValue(env.local())
1325 .FromJust());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001326}
1327
1328
1329THREADED_TEST(ExternalWrap) {
1330 // Check heap allocated object.
1331 int* ptr = new int;
1332 expected_ptr = ptr;
1333 TestExternalPointerWrapping();
1334 delete ptr;
1335
1336 // Check stack allocated object.
1337 int foo;
1338 expected_ptr = &foo;
1339 TestExternalPointerWrapping();
1340
1341 // Check not aligned addresses.
1342 const int n = 100;
1343 char* s = new char[n];
1344 for (int i = 0; i < n; i++) {
1345 expected_ptr = s + i;
1346 TestExternalPointerWrapping();
1347 }
1348
1349 delete[] s;
1350
1351 // Check several invalid addresses.
1352 expected_ptr = reinterpret_cast<void*>(1);
1353 TestExternalPointerWrapping();
1354
1355 expected_ptr = reinterpret_cast<void*>(0xdeadbeef);
1356 TestExternalPointerWrapping();
1357
1358 expected_ptr = reinterpret_cast<void*>(0xdeadbeef + 1);
1359 TestExternalPointerWrapping();
1360
1361#if defined(V8_HOST_ARCH_X64)
Steve Block1e0659c2011-05-24 12:43:12 +01001362 // Check a value with a leading 1 bit in x64 Smi encoding.
1363 expected_ptr = reinterpret_cast<void*>(0x400000000);
1364 TestExternalPointerWrapping();
1365
Ben Murdochb8e0da22011-05-16 14:20:40 +01001366 expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef);
1367 TestExternalPointerWrapping();
1368
1369 expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef + 1);
1370 TestExternalPointerWrapping();
1371#endif
1372}
1373
1374
Steve Blocka7e24c12009-10-30 11:49:00 +00001375THREADED_TEST(FindInstanceInPrototypeChain) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001376 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001377 v8::Isolate* isolate = env->GetIsolate();
1378 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001379
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001380 Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New(isolate);
1381 Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New(isolate);
1382 Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001383 derived->Inherit(base);
1384
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001385 Local<v8::Function> base_function =
1386 base->GetFunction(env.local()).ToLocalChecked();
1387 Local<v8::Function> derived_function =
1388 derived->GetFunction(env.local()).ToLocalChecked();
1389 Local<v8::Function> other_function =
1390 other->GetFunction(env.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001391
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001392 Local<v8::Object> base_instance =
1393 base_function->NewInstance(env.local()).ToLocalChecked();
1394 Local<v8::Object> derived_instance =
1395 derived_function->NewInstance(env.local()).ToLocalChecked();
1396 Local<v8::Object> derived_instance2 =
1397 derived_function->NewInstance(env.local()).ToLocalChecked();
1398 Local<v8::Object> other_instance =
1399 other_function->NewInstance(env.local()).ToLocalChecked();
1400 CHECK(
1401 derived_instance2->Set(env.local(), v8_str("__proto__"), derived_instance)
1402 .FromJust());
1403 CHECK(other_instance->Set(env.local(), v8_str("__proto__"), derived_instance2)
1404 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001405
1406 // base_instance is only an instance of base.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001407 CHECK(base_instance->Equals(env.local(),
1408 base_instance->FindInstanceInPrototypeChain(base))
1409 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001410 CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
1411 CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1412
1413 // derived_instance is an instance of base and derived.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001414 CHECK(derived_instance->Equals(env.local(),
1415 derived_instance->FindInstanceInPrototypeChain(
1416 base))
1417 .FromJust());
1418 CHECK(derived_instance->Equals(env.local(),
1419 derived_instance->FindInstanceInPrototypeChain(
1420 derived))
1421 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001422 CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1423
1424 // other_instance is an instance of other and its immediate
1425 // prototype derived_instance2 is an instance of base and derived.
1426 // Note, derived_instance is an instance of base and derived too,
1427 // but it comes after derived_instance2 in the prototype chain of
1428 // other_instance.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001429 CHECK(derived_instance2->Equals(
1430 env.local(),
1431 other_instance->FindInstanceInPrototypeChain(base))
1432 .FromJust());
1433 CHECK(derived_instance2->Equals(env.local(),
1434 other_instance->FindInstanceInPrototypeChain(
1435 derived))
1436 .FromJust());
1437 CHECK(other_instance->Equals(
1438 env.local(),
1439 other_instance->FindInstanceInPrototypeChain(other))
1440 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001441}
1442
1443
Steve Block3ce2e202009-11-05 08:53:23 +00001444THREADED_TEST(TinyInteger) {
Steve Block3ce2e202009-11-05 08:53:23 +00001445 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001446 v8::Isolate* isolate = env->GetIsolate();
1447 v8::HandleScope scope(isolate);
1448
Steve Block3ce2e202009-11-05 08:53:23 +00001449 int32_t value = 239;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001450 Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
1451 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1452
1453 value_obj = v8::Integer::New(isolate, value);
Steve Block3ce2e202009-11-05 08:53:23 +00001454 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1455}
1456
1457
1458THREADED_TEST(BigSmiInteger) {
Steve Block3ce2e202009-11-05 08:53:23 +00001459 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001460 v8::HandleScope scope(env->GetIsolate());
1461 v8::Isolate* isolate = CcTest::isolate();
1462
Steve Block3ce2e202009-11-05 08:53:23 +00001463 int32_t value = i::Smi::kMaxValue;
1464 // We cannot add one to a Smi::kMaxValue without wrapping.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001465 if (i::SmiValuesAre31Bits()) {
Steve Block3ce2e202009-11-05 08:53:23 +00001466 CHECK(i::Smi::IsValid(value));
1467 CHECK(!i::Smi::IsValid(value + 1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001468
1469 Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
1470 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1471
1472 value_obj = v8::Integer::New(isolate, value);
Steve Block3ce2e202009-11-05 08:53:23 +00001473 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1474 }
1475}
1476
1477
1478THREADED_TEST(BigInteger) {
Steve Block3ce2e202009-11-05 08:53:23 +00001479 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001480 v8::HandleScope scope(env->GetIsolate());
1481 v8::Isolate* isolate = CcTest::isolate();
1482
Steve Block3ce2e202009-11-05 08:53:23 +00001483 // We cannot add one to a Smi::kMaxValue without wrapping.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001484 if (i::SmiValuesAre31Bits()) {
Steve Block3ce2e202009-11-05 08:53:23 +00001485 // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
1486 // The code will not be run in that case, due to the "if" guard.
1487 int32_t value =
1488 static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
1489 CHECK(value > i::Smi::kMaxValue);
1490 CHECK(!i::Smi::IsValid(value));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001491
1492 Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
1493 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1494
1495 value_obj = v8::Integer::New(isolate, value);
Steve Block3ce2e202009-11-05 08:53:23 +00001496 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1497 }
1498}
1499
1500
1501THREADED_TEST(TinyUnsignedInteger) {
Steve Block3ce2e202009-11-05 08:53:23 +00001502 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001503 v8::HandleScope scope(env->GetIsolate());
1504 v8::Isolate* isolate = CcTest::isolate();
1505
Steve Block3ce2e202009-11-05 08:53:23 +00001506 uint32_t value = 239;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001507
1508 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1509 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1510
1511 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
Steve Block3ce2e202009-11-05 08:53:23 +00001512 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1513}
1514
1515
1516THREADED_TEST(BigUnsignedSmiInteger) {
Steve Block3ce2e202009-11-05 08:53:23 +00001517 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001518 v8::HandleScope scope(env->GetIsolate());
1519 v8::Isolate* isolate = CcTest::isolate();
1520
Steve Block3ce2e202009-11-05 08:53:23 +00001521 uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
1522 CHECK(i::Smi::IsValid(value));
1523 CHECK(!i::Smi::IsValid(value + 1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001524
1525 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1526 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1527
1528 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
Steve Block3ce2e202009-11-05 08:53:23 +00001529 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1530}
1531
1532
1533THREADED_TEST(BigUnsignedInteger) {
Steve Block3ce2e202009-11-05 08:53:23 +00001534 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001535 v8::HandleScope scope(env->GetIsolate());
1536 v8::Isolate* isolate = CcTest::isolate();
1537
Steve Block3ce2e202009-11-05 08:53:23 +00001538 uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
1539 CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
1540 CHECK(!i::Smi::IsValid(value));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001541
1542 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1543 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1544
1545 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
Steve Block3ce2e202009-11-05 08:53:23 +00001546 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1547}
1548
1549
1550THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
Steve Block3ce2e202009-11-05 08:53:23 +00001551 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001552 v8::HandleScope scope(env->GetIsolate());
1553 v8::Isolate* isolate = CcTest::isolate();
1554
Steve Block3ce2e202009-11-05 08:53:23 +00001555 uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
1556 uint32_t value = INT32_MAX_AS_UINT + 1;
1557 CHECK(value > INT32_MAX_AS_UINT); // No overflow.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001558
1559 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1560 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1561
1562 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
Steve Block3ce2e202009-11-05 08:53:23 +00001563 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1564}
1565
1566
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001567THREADED_TEST(IsNativeError) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001568 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001569 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001570 v8::Local<Value> syntax_error = CompileRun(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001571 "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
1572 CHECK(syntax_error->IsNativeError());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001573 v8::Local<Value> not_error = CompileRun("{a:42}");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001574 CHECK(!not_error->IsNativeError());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001575 v8::Local<Value> not_object = CompileRun("42");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001576 CHECK(!not_object->IsNativeError());
1577}
1578
1579
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001580THREADED_TEST(IsGeneratorFunctionOrObject) {
1581 LocalContext env;
1582 v8::HandleScope scope(env->GetIsolate());
1583
1584 CompileRun("function *gen() { yield 1; }\nfunction func() {}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001585 v8::Local<Value> gen = CompileRun("gen");
1586 v8::Local<Value> genObj = CompileRun("gen()");
1587 v8::Local<Value> object = CompileRun("{a:42}");
1588 v8::Local<Value> func = CompileRun("func");
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001589
1590 CHECK(gen->IsGeneratorFunction());
1591 CHECK(gen->IsFunction());
1592 CHECK(!gen->IsGeneratorObject());
1593
1594 CHECK(!genObj->IsGeneratorFunction());
1595 CHECK(!genObj->IsFunction());
1596 CHECK(genObj->IsGeneratorObject());
1597
1598 CHECK(!object->IsGeneratorFunction());
1599 CHECK(!object->IsFunction());
1600 CHECK(!object->IsGeneratorObject());
1601
1602 CHECK(!func->IsGeneratorFunction());
1603 CHECK(func->IsFunction());
1604 CHECK(!func->IsGeneratorObject());
1605}
1606
1607
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001608THREADED_TEST(ArgumentsObject) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001609 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001610 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001611 v8::Local<Value> arguments_object =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001612 CompileRun("var out = 0; (function(){ out = arguments; })(1,2,3); out;");
1613 CHECK(arguments_object->IsArgumentsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001614 v8::Local<Value> array = CompileRun("[1,2,3]");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001615 CHECK(!array->IsArgumentsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001616 v8::Local<Value> object = CompileRun("{a:42}");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001617 CHECK(!object->IsArgumentsObject());
1618}
1619
1620
1621THREADED_TEST(IsMapOrSet) {
1622 LocalContext env;
1623 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001624 v8::Local<Value> map = CompileRun("new Map()");
1625 v8::Local<Value> set = CompileRun("new Set()");
1626 v8::Local<Value> weak_map = CompileRun("new WeakMap()");
1627 v8::Local<Value> weak_set = CompileRun("new WeakSet()");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001628 CHECK(map->IsMap());
1629 CHECK(set->IsSet());
1630 CHECK(weak_map->IsWeakMap());
1631 CHECK(weak_set->IsWeakSet());
1632
1633 CHECK(!map->IsSet());
1634 CHECK(!map->IsWeakMap());
1635 CHECK(!map->IsWeakSet());
1636
1637 CHECK(!set->IsMap());
1638 CHECK(!set->IsWeakMap());
1639 CHECK(!set->IsWeakSet());
1640
1641 CHECK(!weak_map->IsMap());
1642 CHECK(!weak_map->IsSet());
1643 CHECK(!weak_map->IsWeakSet());
1644
1645 CHECK(!weak_set->IsMap());
1646 CHECK(!weak_set->IsSet());
1647 CHECK(!weak_set->IsWeakMap());
1648
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001649 v8::Local<Value> object = CompileRun("{a:42}");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001650 CHECK(!object->IsMap());
1651 CHECK(!object->IsSet());
1652 CHECK(!object->IsWeakMap());
1653 CHECK(!object->IsWeakSet());
1654}
1655
1656
1657THREADED_TEST(StringObject) {
1658 LocalContext env;
1659 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001660 v8::Local<Value> boxed_string = CompileRun("new String(\"test\")");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001661 CHECK(boxed_string->IsStringObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001662 v8::Local<Value> unboxed_string = CompileRun("\"test\"");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001663 CHECK(!unboxed_string->IsStringObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001664 v8::Local<Value> boxed_not_string = CompileRun("new Number(42)");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001665 CHECK(!boxed_not_string->IsStringObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001666 v8::Local<Value> not_object = CompileRun("0");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001667 CHECK(!not_object->IsStringObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001668 v8::Local<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001669 CHECK(!as_boxed.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001670 Local<v8::String> the_string = as_boxed->ValueOf();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001671 CHECK(!the_string.IsEmpty());
1672 ExpectObject("\"test\"", the_string);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001673 v8::Local<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001674 CHECK(new_boxed_string->IsStringObject());
1675 as_boxed = new_boxed_string.As<v8::StringObject>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001676 the_string = as_boxed->ValueOf();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001677 CHECK(!the_string.IsEmpty());
1678 ExpectObject("\"test\"", the_string);
1679}
1680
1681
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001682TEST(StringObjectDelete) {
1683 LocalContext context;
1684 v8::HandleScope scope(context->GetIsolate());
1685 v8::Local<Value> boxed_string = CompileRun("new String(\"test\")");
1686 CHECK(boxed_string->IsStringObject());
1687 v8::Local<v8::Object> str_obj = boxed_string.As<v8::Object>();
1688 CHECK(!str_obj->Delete(context.local(), 2).FromJust());
1689 CHECK(!str_obj->Delete(context.local(), v8_num(2)).FromJust());
1690}
1691
1692
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001693THREADED_TEST(NumberObject) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001694 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001695 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001696 v8::Local<Value> boxed_number = CompileRun("new Number(42)");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001697 CHECK(boxed_number->IsNumberObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001698 v8::Local<Value> unboxed_number = CompileRun("42");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001699 CHECK(!unboxed_number->IsNumberObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001700 v8::Local<Value> boxed_not_number = CompileRun("new Boolean(false)");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001701 CHECK(!boxed_not_number->IsNumberObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001702 v8::Local<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001703 CHECK(!as_boxed.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001704 double the_number = as_boxed->ValueOf();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001705 CHECK_EQ(42.0, the_number);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001706 v8::Local<v8::Value> new_boxed_number =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001707 v8::NumberObject::New(env->GetIsolate(), 43);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001708 CHECK(new_boxed_number->IsNumberObject());
1709 as_boxed = new_boxed_number.As<v8::NumberObject>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001710 the_number = as_boxed->ValueOf();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001711 CHECK_EQ(43.0, the_number);
1712}
1713
1714
1715THREADED_TEST(BooleanObject) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001716 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001717 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001718 v8::Local<Value> boxed_boolean = CompileRun("new Boolean(true)");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001719 CHECK(boxed_boolean->IsBooleanObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001720 v8::Local<Value> unboxed_boolean = CompileRun("true");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001721 CHECK(!unboxed_boolean->IsBooleanObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001722 v8::Local<Value> boxed_not_boolean = CompileRun("new Number(42)");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001723 CHECK(!boxed_not_boolean->IsBooleanObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001724 v8::Local<v8::BooleanObject> as_boxed = boxed_boolean.As<v8::BooleanObject>();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001725 CHECK(!as_boxed.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001726 bool the_boolean = as_boxed->ValueOf();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001727 CHECK_EQ(true, the_boolean);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001728 v8::Local<v8::Value> boxed_true =
1729 v8::BooleanObject::New(env->GetIsolate(), true);
1730 v8::Local<v8::Value> boxed_false =
1731 v8::BooleanObject::New(env->GetIsolate(), false);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001732 CHECK(boxed_true->IsBooleanObject());
1733 CHECK(boxed_false->IsBooleanObject());
1734 as_boxed = boxed_true.As<v8::BooleanObject>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001735 CHECK_EQ(true, as_boxed->ValueOf());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001736 as_boxed = boxed_false.As<v8::BooleanObject>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001737 CHECK_EQ(false, as_boxed->ValueOf());
1738}
1739
1740
1741THREADED_TEST(PrimitiveAndWrappedBooleans) {
1742 LocalContext env;
1743 v8::HandleScope scope(env->GetIsolate());
1744
1745 Local<Value> primitive_false = Boolean::New(env->GetIsolate(), false);
1746 CHECK(primitive_false->IsBoolean());
1747 CHECK(!primitive_false->IsBooleanObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001748 CHECK(!primitive_false->BooleanValue(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001749 CHECK(!primitive_false->IsTrue());
1750 CHECK(primitive_false->IsFalse());
1751
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001752 Local<Value> false_value = BooleanObject::New(env->GetIsolate(), false);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001753 CHECK(!false_value->IsBoolean());
1754 CHECK(false_value->IsBooleanObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001755 CHECK(false_value->BooleanValue(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001756 CHECK(!false_value->IsTrue());
1757 CHECK(!false_value->IsFalse());
1758
1759 Local<BooleanObject> false_boolean_object = false_value.As<BooleanObject>();
1760 CHECK(!false_boolean_object->IsBoolean());
1761 CHECK(false_boolean_object->IsBooleanObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001762 CHECK(false_boolean_object->BooleanValue(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001763 CHECK(!false_boolean_object->ValueOf());
1764 CHECK(!false_boolean_object->IsTrue());
1765 CHECK(!false_boolean_object->IsFalse());
1766
1767 Local<Value> primitive_true = Boolean::New(env->GetIsolate(), true);
1768 CHECK(primitive_true->IsBoolean());
1769 CHECK(!primitive_true->IsBooleanObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001770 CHECK(primitive_true->BooleanValue(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001771 CHECK(primitive_true->IsTrue());
1772 CHECK(!primitive_true->IsFalse());
1773
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001774 Local<Value> true_value = BooleanObject::New(env->GetIsolate(), true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001775 CHECK(!true_value->IsBoolean());
1776 CHECK(true_value->IsBooleanObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001777 CHECK(true_value->BooleanValue(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001778 CHECK(!true_value->IsTrue());
1779 CHECK(!true_value->IsFalse());
1780
1781 Local<BooleanObject> true_boolean_object = true_value.As<BooleanObject>();
1782 CHECK(!true_boolean_object->IsBoolean());
1783 CHECK(true_boolean_object->IsBooleanObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001784 CHECK(true_boolean_object->BooleanValue(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001785 CHECK(true_boolean_object->ValueOf());
1786 CHECK(!true_boolean_object->IsTrue());
1787 CHECK(!true_boolean_object->IsFalse());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001788}
1789
1790
Steve Blocka7e24c12009-10-30 11:49:00 +00001791THREADED_TEST(Number) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001792 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001793 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001794 double PI = 3.1415926;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001795 Local<v8::Number> pi_obj = v8::Number::New(env->GetIsolate(), PI);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001796 CHECK_EQ(PI, pi_obj->NumberValue(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001797}
1798
1799
1800THREADED_TEST(ToNumber) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001801 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001802 v8::Isolate* isolate = CcTest::isolate();
1803 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001804 Local<String> str = v8_str("3.1415926");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001805 CHECK_EQ(3.1415926, str->NumberValue(env.local()).FromJust());
1806 v8::Local<v8::Boolean> t = v8::True(isolate);
1807 CHECK_EQ(1.0, t->NumberValue(env.local()).FromJust());
1808 v8::Local<v8::Boolean> f = v8::False(isolate);
1809 CHECK_EQ(0.0, f->NumberValue(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001810}
1811
1812
1813THREADED_TEST(Date) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001814 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001815 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001816 double PI = 3.1415926;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001817 Local<Value> date = v8::Date::New(env.local(), PI).ToLocalChecked();
1818 CHECK_EQ(3.0, date->NumberValue(env.local()).FromJust());
1819 CHECK(date.As<v8::Date>()
1820 ->Set(env.local(), v8_str("property"),
1821 v8::Integer::New(env->GetIsolate(), 42))
1822 .FromJust());
1823 CHECK_EQ(42, date.As<v8::Date>()
1824 ->Get(env.local(), v8_str("property"))
1825 .ToLocalChecked()
1826 ->Int32Value(env.local())
1827 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001828}
1829
1830
1831THREADED_TEST(Boolean) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001832 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001833 v8::Isolate* isolate = env->GetIsolate();
1834 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001835 v8::Local<v8::Boolean> t = v8::True(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001836 CHECK(t->Value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001837 v8::Local<v8::Boolean> f = v8::False(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001838 CHECK(!f->Value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001839 v8::Local<v8::Primitive> u = v8::Undefined(isolate);
1840 CHECK(!u->BooleanValue(env.local()).FromJust());
1841 v8::Local<v8::Primitive> n = v8::Null(isolate);
1842 CHECK(!n->BooleanValue(env.local()).FromJust());
1843 v8::Local<String> str1 = v8_str("");
1844 CHECK(!str1->BooleanValue(env.local()).FromJust());
1845 v8::Local<String> str2 = v8_str("x");
1846 CHECK(str2->BooleanValue(env.local()).FromJust());
1847 CHECK(!v8::Number::New(isolate, 0)->BooleanValue(env.local()).FromJust());
1848 CHECK(v8::Number::New(isolate, -1)->BooleanValue(env.local()).FromJust());
1849 CHECK(v8::Number::New(isolate, 1)->BooleanValue(env.local()).FromJust());
1850 CHECK(v8::Number::New(isolate, 42)->BooleanValue(env.local()).FromJust());
1851 CHECK(!v8_compile("NaN")
1852 ->Run(env.local())
1853 .ToLocalChecked()
1854 ->BooleanValue(env.local())
1855 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001856}
1857
1858
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001859static void DummyCallHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001860 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001861 args.GetReturnValue().Set(v8_num(13.4));
Steve Blocka7e24c12009-10-30 11:49:00 +00001862}
1863
1864
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001865static void GetM(Local<String> name,
1866 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001867 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001868 info.GetReturnValue().Set(v8_num(876));
Steve Blocka7e24c12009-10-30 11:49:00 +00001869}
1870
1871
1872THREADED_TEST(GlobalPrototype) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001873 v8::Isolate* isolate = CcTest::isolate();
1874 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001875 v8::Local<v8::FunctionTemplate> func_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001876 v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001877 func_templ->PrototypeTemplate()->Set(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001878 isolate, "dummy", v8::FunctionTemplate::New(isolate, DummyCallHandler));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001879 v8::Local<ObjectTemplate> templ = func_templ->InstanceTemplate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001880 templ->Set(isolate, "x", v8_num(200));
Steve Blocka7e24c12009-10-30 11:49:00 +00001881 templ->SetAccessor(v8_str("m"), GetM);
1882 LocalContext env(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001883 v8::Local<Script> script(v8_compile("dummy()"));
1884 v8::Local<Value> result(script->Run(env.local()).ToLocalChecked());
1885 CHECK_EQ(13.4, result->NumberValue(env.local()).FromJust());
1886 CHECK_EQ(200, v8_run_int32value(v8_compile("x")));
1887 CHECK_EQ(876, v8_run_int32value(v8_compile("m")));
Steve Blocka7e24c12009-10-30 11:49:00 +00001888}
1889
1890
Steve Blocka7e24c12009-10-30 11:49:00 +00001891THREADED_TEST(ObjectTemplate) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001892 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001893 v8::Isolate* isolate = CcTest::isolate();
1894 v8::HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001895 Local<v8::FunctionTemplate> acc =
1896 v8::FunctionTemplate::New(isolate, Returns42);
1897 CHECK(env->Global()
1898 ->Set(env.local(), v8_str("acc"),
1899 acc->GetFunction(env.local()).ToLocalChecked())
1900 .FromJust());
1901
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001902 Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
1903 v8::Local<v8::String> class_name = v8_str("the_class_name");
1904 fun->SetClassName(class_name);
1905 Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate, fun);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001906 templ1->Set(isolate, "x", v8_num(10));
1907 templ1->Set(isolate, "y", v8_num(13));
Ben Murdoch097c5b22016-05-18 11:27:45 +01001908 templ1->Set(v8_str("foo"), acc);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001909 Local<v8::Object> instance1 =
1910 templ1->NewInstance(env.local()).ToLocalChecked();
1911 CHECK(class_name->StrictEquals(instance1->GetConstructorName()));
1912 CHECK(env->Global()->Set(env.local(), v8_str("p"), instance1).FromJust());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001913 CHECK(CompileRun("(p.x == 10)")->BooleanValue(env.local()).FromJust());
1914 CHECK(CompileRun("(p.y == 13)")->BooleanValue(env.local()).FromJust());
1915 CHECK(CompileRun("(p.foo() == 42)")->BooleanValue(env.local()).FromJust());
1916 CHECK(CompileRun("(p.foo == acc)")->BooleanValue(env.local()).FromJust());
1917 // Ensure that foo become a data field.
1918 CompileRun("p.foo = function() {}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001919 Local<v8::FunctionTemplate> fun2 = v8::FunctionTemplate::New(isolate);
1920 fun2->PrototypeTemplate()->Set(isolate, "nirk", v8_num(123));
1921 Local<ObjectTemplate> templ2 = fun2->InstanceTemplate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001922 templ2->Set(isolate, "a", v8_num(12));
1923 templ2->Set(isolate, "b", templ1);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001924 templ2->Set(v8_str("bar"), acc);
1925 templ2->SetAccessorProperty(v8_str("acc"), acc);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001926 Local<v8::Object> instance2 =
1927 templ2->NewInstance(env.local()).ToLocalChecked();
1928 CHECK(env->Global()->Set(env.local(), v8_str("q"), instance2).FromJust());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001929 CHECK(CompileRun("(q.nirk == 123)")->BooleanValue(env.local()).FromJust());
1930 CHECK(CompileRun("(q.a == 12)")->BooleanValue(env.local()).FromJust());
1931 CHECK(CompileRun("(q.b.x == 10)")->BooleanValue(env.local()).FromJust());
1932 CHECK(CompileRun("(q.b.y == 13)")->BooleanValue(env.local()).FromJust());
1933 CHECK(CompileRun("(q.b.foo() == 42)")->BooleanValue(env.local()).FromJust());
1934 CHECK(CompileRun("(q.b.foo === acc)")->BooleanValue(env.local()).FromJust());
1935 CHECK(CompileRun("(q.b !== p)")->BooleanValue(env.local()).FromJust());
1936 CHECK(CompileRun("(q.acc == 42)")->BooleanValue(env.local()).FromJust());
1937 CHECK(CompileRun("(q.bar() == 42)")->BooleanValue(env.local()).FromJust());
1938 CHECK(CompileRun("(q.bar == acc)")->BooleanValue(env.local()).FromJust());
1939
1940 instance2 = templ2->NewInstance(env.local()).ToLocalChecked();
1941 CHECK(env->Global()->Set(env.local(), v8_str("q2"), instance2).FromJust());
1942 CHECK(CompileRun("(q2.nirk == 123)")->BooleanValue(env.local()).FromJust());
1943 CHECK(CompileRun("(q2.a == 12)")->BooleanValue(env.local()).FromJust());
1944 CHECK(CompileRun("(q2.b.x == 10)")->BooleanValue(env.local()).FromJust());
1945 CHECK(CompileRun("(q2.b.y == 13)")->BooleanValue(env.local()).FromJust());
1946 CHECK(CompileRun("(q2.b.foo() == 42)")->BooleanValue(env.local()).FromJust());
1947 CHECK(CompileRun("(q2.b.foo === acc)")->BooleanValue(env.local()).FromJust());
1948 CHECK(CompileRun("(q2.acc == 42)")->BooleanValue(env.local()).FromJust());
1949 CHECK(CompileRun("(q2.bar() == 42)")->BooleanValue(env.local()).FromJust());
1950 CHECK(CompileRun("(q2.bar === acc)")->BooleanValue(env.local()).FromJust());
1951
1952 CHECK(CompileRun("(q.b !== q2.b)")->BooleanValue(env.local()).FromJust());
1953 CHECK(CompileRun("q.b.x = 17; (q2.b.x == 10)")
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001954 ->BooleanValue(env.local())
1955 .FromJust());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001956 CHECK(CompileRun("desc1 = Object.getOwnPropertyDescriptor(q, 'acc');"
1957 "(desc1.get === acc)")
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001958 ->BooleanValue(env.local())
1959 .FromJust());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001960 CHECK(CompileRun("desc2 = Object.getOwnPropertyDescriptor(q2, 'acc');"
1961 "(desc2.get === acc)")
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001962 ->BooleanValue(env.local())
1963 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001964}
1965
Ben Murdoch097c5b22016-05-18 11:27:45 +01001966THREADED_TEST(IntegerValue) {
1967 LocalContext env;
1968 v8::Isolate* isolate = CcTest::isolate();
1969 v8::HandleScope scope(isolate);
1970
1971 CHECK_EQ(0, CompileRun("undefined")->IntegerValue(env.local()).FromJust());
1972}
1973
1974static void GetNirk(Local<String> name,
1975 const v8::PropertyCallbackInfo<v8::Value>& info) {
1976 ApiTestFuzzer::Fuzz();
1977 info.GetReturnValue().Set(v8_num(900));
1978}
1979
1980static void GetRino(Local<String> name,
1981 const v8::PropertyCallbackInfo<v8::Value>& info) {
1982 ApiTestFuzzer::Fuzz();
1983 info.GetReturnValue().Set(v8_num(560));
1984}
1985
1986enum ObjectInstantiationMode {
1987 // Create object using ObjectTemplate::NewInstance.
1988 ObjectTemplate_NewInstance,
1989 // Create object using FunctionTemplate::NewInstance on constructor.
1990 Constructor_GetFunction_NewInstance,
1991 // Create object using new operator on constructor.
1992 Constructor_GetFunction_New
1993};
1994
1995// Test object instance creation using a function template with an instance
1996// template inherited from another function template with accessors and data
1997// properties in prototype template.
1998static void TestObjectTemplateInheritedWithPrototype(
1999 ObjectInstantiationMode mode) {
2000 LocalContext env;
2001 v8::Isolate* isolate = CcTest::isolate();
2002 v8::HandleScope scope(isolate);
2003
2004 Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
2005 fun_A->SetClassName(v8_str("A"));
2006 v8::Local<v8::ObjectTemplate> prototype_templ = fun_A->PrototypeTemplate();
2007 prototype_templ->Set(isolate, "a", v8_num(113));
2008 prototype_templ->SetNativeDataProperty(v8_str("nirk"), GetNirk);
2009 prototype_templ->Set(isolate, "b", v8_num(153));
2010
2011 Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
2012 v8::Local<v8::String> class_name = v8_str("B");
2013 fun_B->SetClassName(class_name);
2014 fun_B->Inherit(fun_A);
2015 prototype_templ = fun_B->PrototypeTemplate();
2016 prototype_templ->Set(isolate, "c", v8_num(713));
2017 prototype_templ->SetNativeDataProperty(v8_str("rino"), GetRino);
2018 prototype_templ->Set(isolate, "d", v8_num(753));
2019
2020 Local<ObjectTemplate> templ = fun_B->InstanceTemplate();
2021 templ->Set(isolate, "x", v8_num(10));
2022 templ->Set(isolate, "y", v8_num(13));
2023
2024 // Perform several iterations to trigger creation from cached boilerplate.
2025 for (int i = 0; i < 3; i++) {
2026 Local<v8::Object> instance;
2027 switch (mode) {
2028 case ObjectTemplate_NewInstance:
2029 instance = templ->NewInstance(env.local()).ToLocalChecked();
2030 break;
2031
2032 case Constructor_GetFunction_NewInstance: {
2033 Local<v8::Function> function_B =
2034 fun_B->GetFunction(env.local()).ToLocalChecked();
2035 instance = function_B->NewInstance(env.local()).ToLocalChecked();
2036 break;
2037 }
2038 case Constructor_GetFunction_New: {
2039 Local<v8::Function> function_B =
2040 fun_B->GetFunction(env.local()).ToLocalChecked();
2041 if (i == 0) {
2042 CHECK(env->Global()
2043 ->Set(env.local(), class_name, function_B)
2044 .FromJust());
2045 }
2046 instance =
2047 CompileRun("new B()")->ToObject(env.local()).ToLocalChecked();
2048 break;
2049 }
2050 default:
2051 UNREACHABLE();
2052 }
2053
2054 CHECK(class_name->StrictEquals(instance->GetConstructorName()));
2055 CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
2056
2057 CHECK_EQ(10, CompileRun("o.x")->IntegerValue(env.local()).FromJust());
2058 CHECK_EQ(13, CompileRun("o.y")->IntegerValue(env.local()).FromJust());
2059
2060 CHECK_EQ(113, CompileRun("o.a")->IntegerValue(env.local()).FromJust());
2061 CHECK_EQ(900, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
2062 CHECK_EQ(153, CompileRun("o.b")->IntegerValue(env.local()).FromJust());
2063 CHECK_EQ(713, CompileRun("o.c")->IntegerValue(env.local()).FromJust());
2064 CHECK_EQ(560, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
2065 CHECK_EQ(753, CompileRun("o.d")->IntegerValue(env.local()).FromJust());
2066 }
2067}
2068
2069THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype1) {
2070 TestObjectTemplateInheritedWithPrototype(ObjectTemplate_NewInstance);
2071}
2072
2073THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype2) {
2074 TestObjectTemplateInheritedWithPrototype(Constructor_GetFunction_NewInstance);
2075}
2076
2077THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype3) {
2078 TestObjectTemplateInheritedWithPrototype(Constructor_GetFunction_New);
2079}
2080
2081// Test object instance creation using a function template without an instance
2082// template inherited from another function template.
2083static void TestObjectTemplateInheritedWithoutInstanceTemplate(
2084 ObjectInstantiationMode mode) {
2085 LocalContext env;
2086 v8::Isolate* isolate = CcTest::isolate();
2087 v8::HandleScope scope(isolate);
2088
2089 Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
2090 fun_A->SetClassName(v8_str("A"));
2091
2092 Local<ObjectTemplate> templ_A = fun_A->InstanceTemplate();
2093 templ_A->SetNativeDataProperty(v8_str("nirk"), GetNirk);
2094 templ_A->SetNativeDataProperty(v8_str("rino"), GetRino);
2095
2096 Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
2097 v8::Local<v8::String> class_name = v8_str("B");
2098 fun_B->SetClassName(class_name);
2099 fun_B->Inherit(fun_A);
2100
2101 // Perform several iterations to trigger creation from cached boilerplate.
2102 for (int i = 0; i < 3; i++) {
2103 Local<v8::Object> instance;
2104 switch (mode) {
2105 case Constructor_GetFunction_NewInstance: {
2106 Local<v8::Function> function_B =
2107 fun_B->GetFunction(env.local()).ToLocalChecked();
2108 instance = function_B->NewInstance(env.local()).ToLocalChecked();
2109 break;
2110 }
2111 case Constructor_GetFunction_New: {
2112 Local<v8::Function> function_B =
2113 fun_B->GetFunction(env.local()).ToLocalChecked();
2114 if (i == 0) {
2115 CHECK(env->Global()
2116 ->Set(env.local(), class_name, function_B)
2117 .FromJust());
2118 }
2119 instance =
2120 CompileRun("new B()")->ToObject(env.local()).ToLocalChecked();
2121 break;
2122 }
2123 default:
2124 UNREACHABLE();
2125 }
2126
2127 CHECK(class_name->StrictEquals(instance->GetConstructorName()));
2128 CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
2129
2130 CHECK_EQ(900, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
2131 CHECK_EQ(560, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
2132 }
2133}
2134
2135THREADED_TEST(TestObjectTemplateInheritedWithPrototype1) {
2136 TestObjectTemplateInheritedWithoutInstanceTemplate(
2137 Constructor_GetFunction_NewInstance);
2138}
2139
2140THREADED_TEST(TestObjectTemplateInheritedWithPrototype2) {
2141 TestObjectTemplateInheritedWithoutInstanceTemplate(
2142 Constructor_GetFunction_New);
2143}
Steve Blocka7e24c12009-10-30 11:49:00 +00002144
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002145static void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002146 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002147 args.GetReturnValue().Set(v8_num(17.2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002148}
2149
2150
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002151static void GetKnurd(Local<String> property,
2152 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002153 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002154 info.GetReturnValue().Set(v8_num(15.2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002155}
2156
2157
2158THREADED_TEST(DescriptorInheritance) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002159 v8::Isolate* isolate = CcTest::isolate();
2160 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002161 v8::Local<v8::FunctionTemplate> super = v8::FunctionTemplate::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002162 super->PrototypeTemplate()->Set(isolate, "flabby",
2163 v8::FunctionTemplate::New(isolate,
2164 GetFlabby));
2165 super->PrototypeTemplate()->Set(isolate, "PI", v8_num(3.14));
Steve Blocka7e24c12009-10-30 11:49:00 +00002166
2167 super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
2168
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002169 v8::Local<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002170 base1->Inherit(super);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002171 base1->PrototypeTemplate()->Set(isolate, "v1", v8_num(20.1));
Steve Blocka7e24c12009-10-30 11:49:00 +00002172
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002173 v8::Local<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002174 base2->Inherit(super);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002175 base2->PrototypeTemplate()->Set(isolate, "v2", v8_num(10.1));
Steve Blocka7e24c12009-10-30 11:49:00 +00002176
2177 LocalContext env;
2178
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002179 CHECK(env->Global()
2180 ->Set(env.local(), v8_str("s"),
2181 super->GetFunction(env.local()).ToLocalChecked())
2182 .FromJust());
2183 CHECK(env->Global()
2184 ->Set(env.local(), v8_str("base1"),
2185 base1->GetFunction(env.local()).ToLocalChecked())
2186 .FromJust());
2187 CHECK(env->Global()
2188 ->Set(env.local(), v8_str("base2"),
2189 base2->GetFunction(env.local()).ToLocalChecked())
2190 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002191
2192 // Checks right __proto__ chain.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002193 CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")
2194 ->BooleanValue(env.local())
2195 .FromJust());
2196 CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")
2197 ->BooleanValue(env.local())
2198 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002199
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002200 CHECK(v8_compile("s.prototype.PI == 3.14")
2201 ->Run(env.local())
2202 .ToLocalChecked()
2203 ->BooleanValue(env.local())
2204 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002205
2206 // Instance accessor should not be visible on function object or its prototype
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002207 CHECK(
2208 CompileRun("s.knurd == undefined")->BooleanValue(env.local()).FromJust());
2209 CHECK(CompileRun("s.prototype.knurd == undefined")
2210 ->BooleanValue(env.local())
2211 .FromJust());
2212 CHECK(CompileRun("base1.prototype.knurd == undefined")
2213 ->BooleanValue(env.local())
2214 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002215
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002216 CHECK(env->Global()
2217 ->Set(env.local(), v8_str("obj"), base1->GetFunction(env.local())
2218 .ToLocalChecked()
2219 ->NewInstance(env.local())
2220 .ToLocalChecked())
2221 .FromJust());
Ben Murdoch097c5b22016-05-18 11:27:45 +01002222 CHECK_EQ(17.2,
2223 CompileRun("obj.flabby()")->NumberValue(env.local()).FromJust());
2224 CHECK(CompileRun("'flabby' in obj")->BooleanValue(env.local()).FromJust());
2225 CHECK_EQ(15.2, CompileRun("obj.knurd")->NumberValue(env.local()).FromJust());
2226 CHECK(CompileRun("'knurd' in obj")->BooleanValue(env.local()).FromJust());
2227 CHECK_EQ(20.1, CompileRun("obj.v1")->NumberValue(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002228
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002229 CHECK(env->Global()
2230 ->Set(env.local(), v8_str("obj2"), base2->GetFunction(env.local())
2231 .ToLocalChecked()
2232 ->NewInstance(env.local())
2233 .ToLocalChecked())
2234 .FromJust());
Ben Murdoch097c5b22016-05-18 11:27:45 +01002235 CHECK_EQ(17.2,
2236 CompileRun("obj2.flabby()")->NumberValue(env.local()).FromJust());
2237 CHECK(CompileRun("'flabby' in obj2")->BooleanValue(env.local()).FromJust());
2238 CHECK_EQ(15.2, CompileRun("obj2.knurd")->NumberValue(env.local()).FromJust());
2239 CHECK(CompileRun("'knurd' in obj2")->BooleanValue(env.local()).FromJust());
2240 CHECK_EQ(10.1, CompileRun("obj2.v2")->NumberValue(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002241
2242 // base1 and base2 cannot cross reference to each's prototype
Ben Murdoch097c5b22016-05-18 11:27:45 +01002243 CHECK(CompileRun("obj.v2")->IsUndefined());
2244 CHECK(CompileRun("obj2.v1")->IsUndefined());
2245}
2246
2247THREADED_TEST(DescriptorInheritance2) {
2248 LocalContext env;
2249 v8::Isolate* isolate = CcTest::isolate();
2250 v8::HandleScope scope(isolate);
2251 v8::Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
2252 fun_A->SetClassName(v8_str("A"));
2253 fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd1"), GetKnurd);
2254 fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk1"), GetNirk);
2255 fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("rino1"), GetRino);
2256
2257 v8::Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
2258 fun_B->SetClassName(v8_str("B"));
2259 fun_B->Inherit(fun_A);
2260
2261 v8::Local<v8::FunctionTemplate> fun_C = v8::FunctionTemplate::New(isolate);
2262 fun_C->SetClassName(v8_str("C"));
2263 fun_C->Inherit(fun_B);
2264 fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd2"), GetKnurd);
2265 fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk2"), GetNirk);
2266 fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("rino2"), GetRino);
2267
2268 v8::Local<v8::FunctionTemplate> fun_D = v8::FunctionTemplate::New(isolate);
2269 fun_D->SetClassName(v8_str("D"));
2270 fun_D->Inherit(fun_C);
2271
2272 v8::Local<v8::FunctionTemplate> fun_E = v8::FunctionTemplate::New(isolate);
2273 fun_E->SetClassName(v8_str("E"));
2274 fun_E->Inherit(fun_D);
2275 fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd3"), GetKnurd);
2276 fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk3"), GetNirk);
2277 fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("rino3"), GetRino);
2278
2279 v8::Local<v8::FunctionTemplate> fun_F = v8::FunctionTemplate::New(isolate);
2280 fun_F->SetClassName(v8_str("F"));
2281 fun_F->Inherit(fun_E);
2282 v8::Local<v8::ObjectTemplate> templ = fun_F->InstanceTemplate();
2283 const int kDataPropertiesNumber = 100;
2284 for (int i = 0; i < kDataPropertiesNumber; i++) {
2285 v8::Local<v8::Value> val = v8_num(i);
2286 v8::Local<v8::String> val_str = val->ToString(env.local()).ToLocalChecked();
2287 v8::Local<v8::String> name = String::Concat(v8_str("p"), val_str);
2288
2289 templ->Set(name, val);
2290 templ->Set(val_str, val);
2291 }
2292
2293 CHECK(env->Global()
2294 ->Set(env.local(), v8_str("F"),
2295 fun_F->GetFunction(env.local()).ToLocalChecked())
2296 .FromJust());
2297
2298 v8::Local<v8::Script> script = v8_compile("o = new F()");
2299
2300 for (int i = 0; i < 100; i++) {
2301 v8::HandleScope scope(isolate);
2302 script->Run(env.local()).ToLocalChecked();
2303 }
2304 v8::Local<v8::Object> object = script->Run(env.local())
2305 .ToLocalChecked()
2306 ->ToObject(env.local())
2307 .ToLocalChecked();
2308
2309 CHECK_EQ(15.2, CompileRun("o.knurd1")->NumberValue(env.local()).FromJust());
2310 CHECK_EQ(15.2, CompileRun("o.knurd2")->NumberValue(env.local()).FromJust());
2311 CHECK_EQ(15.2, CompileRun("o.knurd3")->NumberValue(env.local()).FromJust());
2312
2313 CHECK_EQ(900, CompileRun("o.nirk1")->IntegerValue(env.local()).FromJust());
2314 CHECK_EQ(900, CompileRun("o.nirk2")->IntegerValue(env.local()).FromJust());
2315 CHECK_EQ(900, CompileRun("o.nirk3")->IntegerValue(env.local()).FromJust());
2316
2317 CHECK_EQ(560, CompileRun("o.rino1")->IntegerValue(env.local()).FromJust());
2318 CHECK_EQ(560, CompileRun("o.rino2")->IntegerValue(env.local()).FromJust());
2319 CHECK_EQ(560, CompileRun("o.rino3")->IntegerValue(env.local()).FromJust());
2320
2321 for (int i = 0; i < kDataPropertiesNumber; i++) {
2322 v8::Local<v8::Value> val = v8_num(i);
2323 v8::Local<v8::String> val_str = val->ToString(env.local()).ToLocalChecked();
2324 v8::Local<v8::String> name = String::Concat(v8_str("p"), val_str);
2325
2326 CHECK_EQ(i, object->Get(env.local(), name)
2327 .ToLocalChecked()
2328 ->IntegerValue(env.local())
2329 .FromJust());
2330 CHECK_EQ(i, object->Get(env.local(), val)
2331 .ToLocalChecked()
2332 ->IntegerValue(env.local())
2333 .FromJust());
2334 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002335}
2336
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002337
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002338// Helper functions for Interceptor/Accessor interaction tests
2339
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002340void SimpleAccessorGetter(Local<String> name,
2341 const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002342 Local<Object> self = Local<Object>::Cast(info.This());
2343 info.GetReturnValue().Set(self->Get(info.GetIsolate()->GetCurrentContext(),
2344 String::Concat(v8_str("accessor_"), name))
2345 .ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002346}
2347
2348void SimpleAccessorSetter(Local<String> name, Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002349 const v8::PropertyCallbackInfo<void>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002350 Local<Object> self = Local<Object>::Cast(info.This());
2351 CHECK(self->Set(info.GetIsolate()->GetCurrentContext(),
2352 String::Concat(v8_str("accessor_"), name), value)
2353 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002354}
2355
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002356void SymbolAccessorGetter(Local<Name> name,
2357 const v8::PropertyCallbackInfo<v8::Value>& info) {
2358 CHECK(name->IsSymbol());
2359 Local<Symbol> sym = Local<Symbol>::Cast(name);
2360 if (sym->Name()->IsUndefined())
2361 return;
2362 SimpleAccessorGetter(Local<String>::Cast(sym->Name()), info);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002363}
2364
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002365void SymbolAccessorSetter(Local<Name> name, Local<Value> value,
2366 const v8::PropertyCallbackInfo<void>& info) {
2367 CHECK(name->IsSymbol());
2368 Local<Symbol> sym = Local<Symbol>::Cast(name);
2369 if (sym->Name()->IsUndefined())
2370 return;
2371 SimpleAccessorSetter(Local<String>::Cast(sym->Name()), value, info);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002372}
2373
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002374void SymbolAccessorGetterReturnsDefault(
2375 Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
2376 CHECK(name->IsSymbol());
2377 Local<Symbol> sym = Local<Symbol>::Cast(name);
2378 if (sym->Name()->IsUndefined()) return;
2379 info.GetReturnValue().Set(info.Data());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002380}
2381
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002382static void ThrowingSymbolAccessorGetter(
2383 Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
2384 info.GetReturnValue().Set(info.GetIsolate()->ThrowException(name));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002385}
2386
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002387
Ben Murdoch097c5b22016-05-18 11:27:45 +01002388THREADED_TEST(AccessorIsPreservedOnAttributeChange) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002389 v8::Isolate* isolate = CcTest::isolate();
2390 v8::HandleScope scope(isolate);
2391 LocalContext env;
2392 v8::Local<v8::Value> res = CompileRun("var a = []; a;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002393 i::Handle<i::JSReceiver> a(v8::Utils::OpenHandle(v8::Object::Cast(*res)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002394 CHECK(a->map()->instance_descriptors()->IsFixedArray());
2395 CHECK_GT(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
2396 CompileRun("Object.defineProperty(a, 'length', { writable: false });");
2397 CHECK_EQ(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002398 // But we should still have an AccessorInfo.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002399 i::Handle<i::String> name(v8::Utils::OpenHandle(*v8_str("length")));
2400 i::LookupIterator it(a, name, i::LookupIterator::OWN_SKIP_INTERCEPTOR);
2401 CHECK_EQ(i::LookupIterator::ACCESSOR, it.state());
Ben Murdoch097c5b22016-05-18 11:27:45 +01002402 CHECK(it.GetAccessors()->IsAccessorInfo());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002403}
2404
2405
Steve Blocka7e24c12009-10-30 11:49:00 +00002406THREADED_TEST(UndefinedIsNotEnumerable) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002407 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002408 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002409 v8::Local<Value> result = CompileRun("this.propertyIsEnumerable(undefined)");
Steve Blocka7e24c12009-10-30 11:49:00 +00002410 CHECK(result->IsFalse());
2411}
2412
2413
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002414v8::Local<Script> call_recursively_script;
2415static const int kTargetRecursionDepth = 150; // near maximum
Steve Blocka7e24c12009-10-30 11:49:00 +00002416
2417
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002418static void CallScriptRecursivelyCall(
2419 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002420 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002421 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
2422 int depth = args.This()
2423 ->Get(context, v8_str("depth"))
2424 .ToLocalChecked()
2425 ->Int32Value(context)
2426 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002427 if (depth == kTargetRecursionDepth) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002428 CHECK(args.This()
2429 ->Set(context, v8_str("depth"),
2430 v8::Integer::New(args.GetIsolate(), depth + 1))
2431 .FromJust());
2432 args.GetReturnValue().Set(
2433 call_recursively_script->Run(context).ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00002434}
2435
2436
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002437static void CallFunctionRecursivelyCall(
2438 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002439 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002440 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
2441 int depth = args.This()
2442 ->Get(context, v8_str("depth"))
2443 .ToLocalChecked()
2444 ->Int32Value(context)
2445 .FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00002446 if (depth == kTargetRecursionDepth) {
2447 printf("[depth = %d]\n", depth);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002448 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002449 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002450 CHECK(args.This()
2451 ->Set(context, v8_str("depth"),
2452 v8::Integer::New(args.GetIsolate(), depth + 1))
2453 .FromJust());
2454 v8::Local<Value> function =
2455 args.This()
2456 ->Get(context, v8_str("callFunctionRecursively"))
2457 .ToLocalChecked();
2458 args.GetReturnValue().Set(function.As<Function>()
2459 ->Call(context, args.This(), 0, NULL)
2460 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00002461}
2462
2463
2464THREADED_TEST(DeepCrossLanguageRecursion) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002465 v8::Isolate* isolate = CcTest::isolate();
2466 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002467 v8::Local<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002468 global->Set(v8_str("callScriptRecursively"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002469 v8::FunctionTemplate::New(isolate, CallScriptRecursivelyCall));
Steve Blocka7e24c12009-10-30 11:49:00 +00002470 global->Set(v8_str("callFunctionRecursively"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002471 v8::FunctionTemplate::New(isolate, CallFunctionRecursivelyCall));
Steve Blocka7e24c12009-10-30 11:49:00 +00002472 LocalContext env(NULL, global);
2473
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002474 CHECK(env->Global()
2475 ->Set(env.local(), v8_str("depth"), v8::Integer::New(isolate, 0))
2476 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002477 call_recursively_script = v8_compile("callScriptRecursively()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002478 call_recursively_script->Run(env.local()).ToLocalChecked();
2479 call_recursively_script = v8::Local<Script>();
Steve Blocka7e24c12009-10-30 11:49:00 +00002480
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002481 CHECK(env->Global()
2482 ->Set(env.local(), v8_str("depth"), v8::Integer::New(isolate, 0))
2483 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002484 CompileRun("callFunctionRecursively()");
Steve Blocka7e24c12009-10-30 11:49:00 +00002485}
2486
2487
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002488static void ThrowingPropertyHandlerGet(
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002489 Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>& info) {
2490 // Since this interceptor is used on "with" objects, the runtime will look up
2491 // @@unscopables. Punt.
2492 if (key->IsSymbol()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002493 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002494 info.GetReturnValue().Set(info.GetIsolate()->ThrowException(key));
Steve Blocka7e24c12009-10-30 11:49:00 +00002495}
2496
2497
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002498static void ThrowingPropertyHandlerSet(
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002499 Local<Name> key, Local<Value>,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002500 const v8::PropertyCallbackInfo<v8::Value>& info) {
2501 info.GetIsolate()->ThrowException(key);
2502 info.GetReturnValue().SetUndefined(); // not the same as empty handle
Steve Blocka7e24c12009-10-30 11:49:00 +00002503}
2504
2505
2506THREADED_TEST(CallbackExceptionRegression) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002507 v8::Isolate* isolate = CcTest::isolate();
2508 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002509 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002510 obj->SetHandler(v8::NamedPropertyHandlerConfiguration(
2511 ThrowingPropertyHandlerGet, ThrowingPropertyHandlerSet));
Steve Blocka7e24c12009-10-30 11:49:00 +00002512 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002513 CHECK(env->Global()
2514 ->Set(env.local(), v8_str("obj"),
2515 obj->NewInstance(env.local()).ToLocalChecked())
2516 .FromJust());
2517 v8::Local<Value> otto =
2518 CompileRun("try { with (obj) { otto; } } catch (e) { e; }");
2519 CHECK(v8_str("otto")->Equals(env.local(), otto).FromJust());
2520 v8::Local<Value> netto =
2521 CompileRun("try { with (obj) { netto = 4; } } catch (e) { e; }");
2522 CHECK(v8_str("netto")->Equals(env.local(), netto).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002523}
2524
2525
Steve Blocka7e24c12009-10-30 11:49:00 +00002526THREADED_TEST(FunctionPrototype) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002527 v8::Isolate* isolate = CcTest::isolate();
2528 v8::HandleScope scope(isolate);
2529 Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002530 Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
2531 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002532 CHECK(env->Global()
2533 ->Set(env.local(), v8_str("Foo"),
2534 Foo->GetFunction(env.local()).ToLocalChecked())
2535 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002536 Local<Script> script = v8_compile("Foo.prototype.plak");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002537 CHECK_EQ(v8_run_int32value(script), 321);
Steve Blocka7e24c12009-10-30 11:49:00 +00002538}
2539
2540
2541THREADED_TEST(InternalFields) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002542 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002543 v8::Isolate* isolate = env->GetIsolate();
2544 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002545
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002546 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002547 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2548 instance_templ->SetInternalFieldCount(1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002549 Local<v8::Object> obj = templ->GetFunction(env.local())
2550 .ToLocalChecked()
2551 ->NewInstance(env.local())
2552 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00002553 CHECK_EQ(1, obj->InternalFieldCount());
2554 CHECK(obj->GetInternalField(0)->IsUndefined());
2555 obj->SetInternalField(0, v8_num(17));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002556 CHECK_EQ(17, obj->GetInternalField(0)->Int32Value(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002557}
2558
2559
Steve Block6ded16b2010-05-10 14:33:55 +01002560THREADED_TEST(GlobalObjectInternalFields) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002561 v8::Isolate* isolate = CcTest::isolate();
2562 v8::HandleScope scope(isolate);
2563 Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
Steve Block6ded16b2010-05-10 14:33:55 +01002564 global_template->SetInternalFieldCount(1);
2565 LocalContext env(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002566 v8::Local<v8::Object> global_proxy = env->Global();
2567 v8::Local<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
Steve Block6ded16b2010-05-10 14:33:55 +01002568 CHECK_EQ(1, global->InternalFieldCount());
2569 CHECK(global->GetInternalField(0)->IsUndefined());
2570 global->SetInternalField(0, v8_num(17));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002571 CHECK_EQ(17, global->GetInternalField(0)->Int32Value(env.local()).FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +01002572}
2573
2574
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002575THREADED_TEST(GlobalObjectHasRealIndexedProperty) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002576 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002577 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00002578
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002579 v8::Local<v8::Object> global = env->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002580 CHECK(global->Set(env.local(), 0, v8_str("value")).FromJust());
2581 CHECK(global->HasRealIndexedProperty(env.local(), 0).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002582}
2583
2584
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002585static void CheckAlignedPointerInInternalField(Local<v8::Object> obj,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002586 void* value) {
2587 CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
2588 obj->SetAlignedPointerInInternalField(0, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002589 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002590 CHECK_EQ(value, obj->GetAlignedPointerFromInternalField(0));
2591}
Steve Block3ce2e202009-11-05 08:53:23 +00002592
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002593
2594THREADED_TEST(InternalFieldsAlignedPointers) {
2595 LocalContext env;
2596 v8::Isolate* isolate = env->GetIsolate();
2597 v8::HandleScope scope(isolate);
2598
2599 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Steve Block3ce2e202009-11-05 08:53:23 +00002600 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2601 instance_templ->SetInternalFieldCount(1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002602 Local<v8::Object> obj = templ->GetFunction(env.local())
2603 .ToLocalChecked()
2604 ->NewInstance(env.local())
2605 .ToLocalChecked();
Steve Block3ce2e202009-11-05 08:53:23 +00002606 CHECK_EQ(1, obj->InternalFieldCount());
Steve Block3ce2e202009-11-05 08:53:23 +00002607
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002608 CheckAlignedPointerInInternalField(obj, NULL);
Steve Block3ce2e202009-11-05 08:53:23 +00002609
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002610 int* heap_allocated = new int[100];
2611 CheckAlignedPointerInInternalField(obj, heap_allocated);
2612 delete[] heap_allocated;
Steve Block3ce2e202009-11-05 08:53:23 +00002613
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002614 int stack_allocated[100];
2615 CheckAlignedPointerInInternalField(obj, stack_allocated);
Steve Block3ce2e202009-11-05 08:53:23 +00002616
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002617 void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2618 CheckAlignedPointerInInternalField(obj, huge);
Steve Block3ce2e202009-11-05 08:53:23 +00002619
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002620 v8::Global<v8::Object> persistent(isolate, obj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002621 CHECK_EQ(1, Object::InternalFieldCount(persistent));
2622 CHECK_EQ(huge, Object::GetAlignedPointerFromInternalField(persistent, 0));
2623}
Steve Block3ce2e202009-11-05 08:53:23 +00002624
Steve Block3ce2e202009-11-05 08:53:23 +00002625
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002626static void CheckAlignedPointerInEmbedderData(LocalContext* env, int index,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002627 void* value) {
2628 CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
2629 (*env)->SetAlignedPointerInEmbedderData(index, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002630 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002631 CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
2632}
2633
2634
2635static void* AlignedTestPointer(int i) {
2636 return reinterpret_cast<void*>(i * 1234);
2637}
2638
2639
2640THREADED_TEST(EmbedderDataAlignedPointers) {
2641 LocalContext env;
2642 v8::HandleScope scope(env->GetIsolate());
2643
2644 CheckAlignedPointerInEmbedderData(&env, 0, NULL);
2645
2646 int* heap_allocated = new int[100];
2647 CheckAlignedPointerInEmbedderData(&env, 1, heap_allocated);
2648 delete[] heap_allocated;
2649
2650 int stack_allocated[100];
2651 CheckAlignedPointerInEmbedderData(&env, 2, stack_allocated);
2652
2653 void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2654 CheckAlignedPointerInEmbedderData(&env, 3, huge);
2655
2656 // Test growing of the embedder data's backing store.
2657 for (int i = 0; i < 100; i++) {
2658 env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
2659 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002660 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002661 for (int i = 0; i < 100; i++) {
2662 CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
2663 }
2664}
2665
2666
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002667static void CheckEmbedderData(LocalContext* env, int index,
2668 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002669 (*env)->SetEmbedderData(index, data);
2670 CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
2671}
2672
2673
2674THREADED_TEST(EmbedderData) {
2675 LocalContext env;
2676 v8::Isolate* isolate = env->GetIsolate();
2677 v8::HandleScope scope(isolate);
2678
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002679 CheckEmbedderData(&env, 3, v8_str("The quick brown fox jumps"));
2680 CheckEmbedderData(&env, 2, v8_str("over the lazy dog."));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002681 CheckEmbedderData(&env, 1, v8::Number::New(isolate, 1.2345));
2682 CheckEmbedderData(&env, 0, v8::Boolean::New(isolate, true));
Steve Block3ce2e202009-11-05 08:53:23 +00002683}
2684
2685
Steve Blocka7e24c12009-10-30 11:49:00 +00002686THREADED_TEST(IdentityHash) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002687 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002688 v8::Isolate* isolate = env->GetIsolate();
2689 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002690
2691 // Ensure that the test starts with an fresh heap to test whether the hash
2692 // code is based on the address.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002693 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002694 Local<v8::Object> obj = v8::Object::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002695 int hash = obj->GetIdentityHash();
2696 int hash1 = obj->GetIdentityHash();
2697 CHECK_EQ(hash, hash1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002698 int hash2 = v8::Object::New(isolate)->GetIdentityHash();
Steve Blocka7e24c12009-10-30 11:49:00 +00002699 // Since the identity hash is essentially a random number two consecutive
2700 // objects should not be assigned the same hash code. If the test below fails
2701 // the random number generator should be evaluated.
2702 CHECK_NE(hash, hash2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002703 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002704 int hash3 = v8::Object::New(isolate)->GetIdentityHash();
Steve Blocka7e24c12009-10-30 11:49:00 +00002705 // Make sure that the identity hash is not based on the initial address of
2706 // the object alone. If the test below fails the random number generator
2707 // should be evaluated.
2708 CHECK_NE(hash, hash3);
2709 int hash4 = obj->GetIdentityHash();
2710 CHECK_EQ(hash, hash4);
Steve Block1e0659c2011-05-24 12:43:12 +01002711
2712 // Check identity hashes behaviour in the presence of JS accessors.
2713 // Put a getter for 'v8::IdentityHash' on the Object's prototype:
2714 {
2715 CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002716 Local<v8::Object> o1 = v8::Object::New(isolate);
2717 Local<v8::Object> o2 = v8::Object::New(isolate);
Steve Block1e0659c2011-05-24 12:43:12 +01002718 CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2719 }
2720 {
2721 CompileRun(
2722 "function cnst() { return 42; };\n"
2723 "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002724 Local<v8::Object> o1 = v8::Object::New(isolate);
2725 Local<v8::Object> o2 = v8::Object::New(isolate);
Steve Block1e0659c2011-05-24 12:43:12 +01002726 CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2727 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002728}
2729
2730
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002731void GlobalProxyIdentityHash(bool set_in_js) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002732 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002733 v8::Isolate* isolate = env->GetIsolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002734 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002735 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002736 Local<Object> global_proxy = env->Global();
2737 i::Handle<i::Object> i_global_proxy = v8::Utils::OpenHandle(*global_proxy);
2738 CHECK(env->Global()
2739 ->Set(env.local(), v8_str("global"), global_proxy)
2740 .FromJust());
2741 i::Handle<i::Object> original_hash;
2742 if (set_in_js) {
2743 CompileRun("var m = new Set(); m.add(global);");
2744 original_hash = i::Handle<i::Object>(i_global_proxy->GetHash(), i_isolate);
2745 } else {
2746 original_hash = i::Handle<i::Object>(
2747 i::Object::GetOrCreateHash(i_isolate, i_global_proxy));
2748 }
2749 CHECK(original_hash->IsSmi());
2750 int32_t hash1 = i::Handle<i::Smi>::cast(original_hash)->value();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002751 // Hash should be retained after being detached.
2752 env->DetachGlobal();
2753 int hash2 = global_proxy->GetIdentityHash();
2754 CHECK_EQ(hash1, hash2);
2755 {
2756 // Re-attach global proxy to a new context, hash should stay the same.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002757 LocalContext env2(NULL, Local<ObjectTemplate>(), global_proxy);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002758 int hash3 = global_proxy->GetIdentityHash();
2759 CHECK_EQ(hash1, hash3);
2760 }
2761}
Steve Blocka7e24c12009-10-30 11:49:00 +00002762
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002763
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002764THREADED_TEST(GlobalProxyIdentityHash) {
2765 GlobalProxyIdentityHash(true);
2766 GlobalProxyIdentityHash(false);
2767}
2768
2769
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002770TEST(SymbolIdentityHash) {
2771 LocalContext env;
2772 v8::Isolate* isolate = env->GetIsolate();
2773 v8::HandleScope scope(isolate);
2774
2775 {
2776 Local<v8::Symbol> symbol = v8::Symbol::New(isolate);
2777 int hash = symbol->GetIdentityHash();
2778 int hash1 = symbol->GetIdentityHash();
2779 CHECK_EQ(hash, hash1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002780 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002781 int hash3 = symbol->GetIdentityHash();
2782 CHECK_EQ(hash, hash3);
2783 }
2784
2785 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002786 v8::Local<v8::Symbol> js_symbol =
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002787 CompileRun("Symbol('foo')").As<v8::Symbol>();
2788 int hash = js_symbol->GetIdentityHash();
2789 int hash1 = js_symbol->GetIdentityHash();
2790 CHECK_EQ(hash, hash1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002791 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002792 int hash3 = js_symbol->GetIdentityHash();
2793 CHECK_EQ(hash, hash3);
2794 }
2795}
2796
2797
2798TEST(StringIdentityHash) {
2799 LocalContext env;
2800 v8::Isolate* isolate = env->GetIsolate();
2801 v8::HandleScope scope(isolate);
2802
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002803 Local<v8::String> str = v8_str("str1");
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002804 int hash = str->GetIdentityHash();
2805 int hash1 = str->GetIdentityHash();
2806 CHECK_EQ(hash, hash1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002807 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002808 int hash3 = str->GetIdentityHash();
2809 CHECK_EQ(hash, hash3);
2810
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002811 Local<v8::String> str2 = v8_str("str1");
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002812 int hash4 = str2->GetIdentityHash();
2813 CHECK_EQ(hash, hash4);
2814}
2815
2816
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002817THREADED_TEST(SymbolProperties) {
2818 LocalContext env;
2819 v8::Isolate* isolate = env->GetIsolate();
2820 v8::HandleScope scope(isolate);
2821
2822 v8::Local<v8::Object> obj = v8::Object::New(isolate);
2823 v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002824 v8::Local<v8::Symbol> sym2 = v8::Symbol::New(isolate, v8_str("my-symbol"));
2825 v8::Local<v8::Symbol> sym3 = v8::Symbol::New(isolate, v8_str("sym3"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002826
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002827 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002828
2829 // Check basic symbol functionality.
2830 CHECK(sym1->IsSymbol());
2831 CHECK(sym2->IsSymbol());
2832 CHECK(!obj->IsSymbol());
2833
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002834 CHECK(sym1->Equals(env.local(), sym1).FromJust());
2835 CHECK(sym2->Equals(env.local(), sym2).FromJust());
2836 CHECK(!sym1->Equals(env.local(), sym2).FromJust());
2837 CHECK(!sym2->Equals(env.local(), sym1).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002838 CHECK(sym1->StrictEquals(sym1));
2839 CHECK(sym2->StrictEquals(sym2));
2840 CHECK(!sym1->StrictEquals(sym2));
2841 CHECK(!sym2->StrictEquals(sym1));
2842
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002843 CHECK(sym2->Name()->Equals(env.local(), v8_str("my-symbol")).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002844
2845 v8::Local<v8::Value> sym_val = sym2;
2846 CHECK(sym_val->IsSymbol());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002847 CHECK(sym_val->Equals(env.local(), sym2).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002848 CHECK(sym_val->StrictEquals(sym2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002849 CHECK(v8::Symbol::Cast(*sym_val)->Equals(env.local(), sym2).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002850
2851 v8::Local<v8::Value> sym_obj = v8::SymbolObject::New(isolate, sym2);
2852 CHECK(sym_obj->IsSymbolObject());
2853 CHECK(!sym2->IsSymbolObject());
2854 CHECK(!obj->IsSymbolObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002855 CHECK(sym_obj->Equals(env.local(), sym2).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002856 CHECK(!sym_obj->StrictEquals(sym2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002857 CHECK(v8::SymbolObject::Cast(*sym_obj)
2858 ->Equals(env.local(), sym_obj)
2859 .FromJust());
2860 CHECK(v8::SymbolObject::Cast(*sym_obj)
2861 ->ValueOf()
2862 ->Equals(env.local(), sym2)
2863 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002864
2865 // Make sure delete of a non-existent symbol property works.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002866 CHECK(obj->Delete(env.local(), sym1).FromJust());
2867 CHECK(!obj->Has(env.local(), sym1).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002868
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002869 CHECK(
2870 obj->Set(env.local(), sym1, v8::Integer::New(isolate, 1503)).FromJust());
2871 CHECK(obj->Has(env.local(), sym1).FromJust());
2872 CHECK_EQ(1503, obj->Get(env.local(), sym1)
2873 .ToLocalChecked()
2874 ->Int32Value(env.local())
2875 .FromJust());
2876 CHECK(
2877 obj->Set(env.local(), sym1, v8::Integer::New(isolate, 2002)).FromJust());
2878 CHECK(obj->Has(env.local(), sym1).FromJust());
2879 CHECK_EQ(2002, obj->Get(env.local(), sym1)
2880 .ToLocalChecked()
2881 ->Int32Value(env.local())
2882 .FromJust());
2883 CHECK_EQ(v8::None, obj->GetPropertyAttributes(env.local(), sym1).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002884
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002885 CHECK_EQ(0u,
2886 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
2887 unsigned num_props =
2888 obj->GetPropertyNames(env.local()).ToLocalChecked()->Length();
2889 CHECK(obj->Set(env.local(), v8_str("bla"), v8::Integer::New(isolate, 20))
2890 .FromJust());
2891 CHECK_EQ(1u,
2892 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
2893 CHECK_EQ(num_props + 1,
2894 obj->GetPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002895
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002896 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002897
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002898 CHECK(obj->SetAccessor(env.local(), sym3, SymbolAccessorGetter,
2899 SymbolAccessorSetter)
2900 .FromJust());
2901 CHECK(obj->Get(env.local(), sym3).ToLocalChecked()->IsUndefined());
2902 CHECK(obj->Set(env.local(), sym3, v8::Integer::New(isolate, 42)).FromJust());
2903 CHECK(obj->Get(env.local(), sym3)
2904 .ToLocalChecked()
2905 ->Equals(env.local(), v8::Integer::New(isolate, 42))
2906 .FromJust());
2907 CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
2908 .ToLocalChecked()
2909 ->Equals(env.local(), v8::Integer::New(isolate, 42))
2910 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002911
2912 // Add another property and delete it afterwards to force the object in
2913 // slow case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002914 CHECK(
2915 obj->Set(env.local(), sym2, v8::Integer::New(isolate, 2008)).FromJust());
2916 CHECK_EQ(2002, obj->Get(env.local(), sym1)
2917 .ToLocalChecked()
2918 ->Int32Value(env.local())
2919 .FromJust());
2920 CHECK_EQ(2008, obj->Get(env.local(), sym2)
2921 .ToLocalChecked()
2922 ->Int32Value(env.local())
2923 .FromJust());
2924 CHECK_EQ(2002, obj->Get(env.local(), sym1)
2925 .ToLocalChecked()
2926 ->Int32Value(env.local())
2927 .FromJust());
2928 CHECK_EQ(2u,
2929 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002930
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002931 CHECK(obj->Has(env.local(), sym1).FromJust());
2932 CHECK(obj->Has(env.local(), sym2).FromJust());
2933 CHECK(obj->Has(env.local(), sym3).FromJust());
2934 CHECK(obj->Has(env.local(), v8_str("accessor_sym3")).FromJust());
2935 CHECK(obj->Delete(env.local(), sym2).FromJust());
2936 CHECK(obj->Has(env.local(), sym1).FromJust());
2937 CHECK(!obj->Has(env.local(), sym2).FromJust());
2938 CHECK(obj->Has(env.local(), sym3).FromJust());
2939 CHECK(obj->Has(env.local(), v8_str("accessor_sym3")).FromJust());
2940 CHECK_EQ(2002, obj->Get(env.local(), sym1)
2941 .ToLocalChecked()
2942 ->Int32Value(env.local())
2943 .FromJust());
2944 CHECK(obj->Get(env.local(), sym3)
2945 .ToLocalChecked()
2946 ->Equals(env.local(), v8::Integer::New(isolate, 42))
2947 .FromJust());
2948 CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
2949 .ToLocalChecked()
2950 ->Equals(env.local(), v8::Integer::New(isolate, 42))
2951 .FromJust());
2952 CHECK_EQ(2u,
2953 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002954
2955 // Symbol properties are inherited.
2956 v8::Local<v8::Object> child = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002957 CHECK(child->SetPrototype(env.local(), obj).FromJust());
2958 CHECK(child->Has(env.local(), sym1).FromJust());
2959 CHECK_EQ(2002, child->Get(env.local(), sym1)
2960 .ToLocalChecked()
2961 ->Int32Value(env.local())
2962 .FromJust());
2963 CHECK(obj->Get(env.local(), sym3)
2964 .ToLocalChecked()
2965 ->Equals(env.local(), v8::Integer::New(isolate, 42))
2966 .FromJust());
2967 CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
2968 .ToLocalChecked()
2969 ->Equals(env.local(), v8::Integer::New(isolate, 42))
2970 .FromJust());
2971 CHECK_EQ(0u,
2972 child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002973}
2974
2975
2976THREADED_TEST(SymbolTemplateProperties) {
2977 LocalContext env;
2978 v8::Isolate* isolate = env->GetIsolate();
2979 v8::HandleScope scope(isolate);
2980 v8::Local<v8::FunctionTemplate> foo = v8::FunctionTemplate::New(isolate);
2981 v8::Local<v8::Name> name = v8::Symbol::New(isolate);
2982 CHECK(!name.IsEmpty());
2983 foo->PrototypeTemplate()->Set(name, v8::FunctionTemplate::New(isolate));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002984 v8::Local<v8::Object> new_instance =
2985 foo->InstanceTemplate()->NewInstance(env.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002986 CHECK(!new_instance.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002987 CHECK(new_instance->Has(env.local(), name).FromJust());
2988}
2989
2990
2991THREADED_TEST(PrivatePropertiesOnProxies) {
2992 i::FLAG_harmony_proxies = true;
2993 LocalContext env;
2994 v8::Isolate* isolate = env->GetIsolate();
2995 v8::HandleScope scope(isolate);
2996
2997 v8::Local<v8::Object> target = CompileRun("({})").As<v8::Object>();
2998 v8::Local<v8::Object> handler = CompileRun("({})").As<v8::Object>();
2999
3000 v8::Local<v8::Proxy> proxy =
3001 v8::Proxy::New(env.local(), target, handler).ToLocalChecked();
3002
3003 v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
3004 v8::Local<v8::Private> priv2 =
3005 v8::Private::New(isolate, v8_str("my-private"));
3006
3007 CcTest::heap()->CollectAllGarbage();
3008
3009 CHECK(priv2->Name()
3010 ->Equals(env.local(),
3011 v8::String::NewFromUtf8(isolate, "my-private",
3012 v8::NewStringType::kNormal)
3013 .ToLocalChecked())
3014 .FromJust());
3015
3016 // Make sure delete of a non-existent private symbol property works.
3017 proxy->DeletePrivate(env.local(), priv1).FromJust();
3018 CHECK(!proxy->HasPrivate(env.local(), priv1).FromJust());
3019
3020 CHECK(proxy->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 1503))
3021 .FromJust());
3022 CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
3023 CHECK_EQ(1503, proxy->GetPrivate(env.local(), priv1)
3024 .ToLocalChecked()
3025 ->Int32Value(env.local())
3026 .FromJust());
3027 CHECK(proxy->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 2002))
3028 .FromJust());
3029 CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
3030 CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
3031 .ToLocalChecked()
3032 ->Int32Value(env.local())
3033 .FromJust());
3034
3035 CHECK_EQ(0u,
3036 proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
3037 unsigned num_props =
3038 proxy->GetPropertyNames(env.local()).ToLocalChecked()->Length();
3039 CHECK(proxy->Set(env.local(), v8::String::NewFromUtf8(
3040 isolate, "bla", v8::NewStringType::kNormal)
3041 .ToLocalChecked(),
3042 v8::Integer::New(isolate, 20))
3043 .FromJust());
3044 CHECK_EQ(1u,
3045 proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
3046 CHECK_EQ(num_props + 1,
3047 proxy->GetPropertyNames(env.local()).ToLocalChecked()->Length());
3048
3049 CcTest::heap()->CollectAllGarbage();
3050
3051 // Add another property and delete it afterwards to force the object in
3052 // slow case.
3053 CHECK(proxy->SetPrivate(env.local(), priv2, v8::Integer::New(isolate, 2008))
3054 .FromJust());
3055 CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
3056 .ToLocalChecked()
3057 ->Int32Value(env.local())
3058 .FromJust());
3059 CHECK_EQ(2008, proxy->GetPrivate(env.local(), priv2)
3060 .ToLocalChecked()
3061 ->Int32Value(env.local())
3062 .FromJust());
3063 CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
3064 .ToLocalChecked()
3065 ->Int32Value(env.local())
3066 .FromJust());
3067 CHECK_EQ(1u,
3068 proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
3069
3070 CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
3071 CHECK(proxy->HasPrivate(env.local(), priv2).FromJust());
3072 CHECK(proxy->DeletePrivate(env.local(), priv2).FromJust());
3073 CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
3074 CHECK(!proxy->HasPrivate(env.local(), priv2).FromJust());
3075 CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
3076 .ToLocalChecked()
3077 ->Int32Value(env.local())
3078 .FromJust());
3079 CHECK_EQ(1u,
3080 proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
3081
3082 // Private properties are not inherited (for the time being).
3083 v8::Local<v8::Object> child = v8::Object::New(isolate);
3084 CHECK(child->SetPrototype(env.local(), proxy).FromJust());
3085 CHECK(!child->HasPrivate(env.local(), priv1).FromJust());
3086 CHECK_EQ(0u,
3087 child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003088}
3089
3090
3091THREADED_TEST(PrivateProperties) {
3092 LocalContext env;
3093 v8::Isolate* isolate = env->GetIsolate();
3094 v8::HandleScope scope(isolate);
3095
3096 v8::Local<v8::Object> obj = v8::Object::New(isolate);
3097 v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
3098 v8::Local<v8::Private> priv2 =
3099 v8::Private::New(isolate, v8_str("my-private"));
3100
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003101 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003102
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003103 CHECK(priv2->Name()
3104 ->Equals(env.local(),
3105 v8::String::NewFromUtf8(isolate, "my-private",
3106 v8::NewStringType::kNormal)
3107 .ToLocalChecked())
3108 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003109
3110 // Make sure delete of a non-existent private symbol property works.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003111 obj->DeletePrivate(env.local(), priv1).FromJust();
3112 CHECK(!obj->HasPrivate(env.local(), priv1).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003113
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003114 CHECK(obj->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 1503))
3115 .FromJust());
3116 CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
3117 CHECK_EQ(1503, obj->GetPrivate(env.local(), priv1)
3118 .ToLocalChecked()
3119 ->Int32Value(env.local())
3120 .FromJust());
3121 CHECK(obj->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 2002))
3122 .FromJust());
3123 CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
3124 CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
3125 .ToLocalChecked()
3126 ->Int32Value(env.local())
3127 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003128
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003129 CHECK_EQ(0u,
3130 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
3131 unsigned num_props =
3132 obj->GetPropertyNames(env.local()).ToLocalChecked()->Length();
3133 CHECK(obj->Set(env.local(), v8::String::NewFromUtf8(
3134 isolate, "bla", v8::NewStringType::kNormal)
3135 .ToLocalChecked(),
3136 v8::Integer::New(isolate, 20))
3137 .FromJust());
3138 CHECK_EQ(1u,
3139 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
3140 CHECK_EQ(num_props + 1,
3141 obj->GetPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003142
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003143 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003144
3145 // Add another property and delete it afterwards to force the object in
3146 // slow case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003147 CHECK(obj->SetPrivate(env.local(), priv2, v8::Integer::New(isolate, 2008))
3148 .FromJust());
3149 CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
3150 .ToLocalChecked()
3151 ->Int32Value(env.local())
3152 .FromJust());
3153 CHECK_EQ(2008, obj->GetPrivate(env.local(), priv2)
3154 .ToLocalChecked()
3155 ->Int32Value(env.local())
3156 .FromJust());
3157 CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
3158 .ToLocalChecked()
3159 ->Int32Value(env.local())
3160 .FromJust());
3161 CHECK_EQ(1u,
3162 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003163
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003164 CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
3165 CHECK(obj->HasPrivate(env.local(), priv2).FromJust());
3166 CHECK(obj->DeletePrivate(env.local(), priv2).FromJust());
3167 CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
3168 CHECK(!obj->HasPrivate(env.local(), priv2).FromJust());
3169 CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
3170 .ToLocalChecked()
3171 ->Int32Value(env.local())
3172 .FromJust());
3173 CHECK_EQ(1u,
3174 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003175
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003176 // Private properties are not inherited (for the time being).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003177 v8::Local<v8::Object> child = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003178 CHECK(child->SetPrototype(env.local(), obj).FromJust());
3179 CHECK(!child->HasPrivate(env.local(), priv1).FromJust());
3180 CHECK_EQ(0u,
3181 child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003182}
3183
3184
3185THREADED_TEST(GlobalSymbols) {
3186 LocalContext env;
3187 v8::Isolate* isolate = env->GetIsolate();
3188 v8::HandleScope scope(isolate);
3189
3190 v8::Local<String> name = v8_str("my-symbol");
3191 v8::Local<v8::Symbol> glob = v8::Symbol::For(isolate, name);
3192 v8::Local<v8::Symbol> glob2 = v8::Symbol::For(isolate, name);
3193 CHECK(glob2->SameValue(glob));
3194
3195 v8::Local<v8::Symbol> glob_api = v8::Symbol::ForApi(isolate, name);
3196 v8::Local<v8::Symbol> glob_api2 = v8::Symbol::ForApi(isolate, name);
3197 CHECK(glob_api2->SameValue(glob_api));
3198 CHECK(!glob_api->SameValue(glob));
3199
3200 v8::Local<v8::Symbol> sym = v8::Symbol::New(isolate, name);
3201 CHECK(!sym->SameValue(glob));
3202
3203 CompileRun("var sym2 = Symbol.for('my-symbol')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003204 v8::Local<Value> sym2 =
3205 env->Global()->Get(env.local(), v8_str("sym2")).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003206 CHECK(sym2->SameValue(glob));
3207 CHECK(!sym2->SameValue(glob_api));
3208}
3209
3210
3211static void CheckWellKnownSymbol(v8::Local<v8::Symbol>(*getter)(v8::Isolate*),
3212 const char* name) {
3213 LocalContext env;
3214 v8::Isolate* isolate = env->GetIsolate();
3215 v8::HandleScope scope(isolate);
3216
3217 v8::Local<v8::Symbol> symbol = getter(isolate);
3218 std::string script = std::string("var sym = ") + name;
3219 CompileRun(script.c_str());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003220 v8::Local<Value> value =
3221 env->Global()->Get(env.local(), v8_str("sym")).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003222
3223 CHECK(!value.IsEmpty());
3224 CHECK(!symbol.IsEmpty());
3225 CHECK(value->SameValue(symbol));
3226}
3227
3228
3229THREADED_TEST(WellKnownSymbols) {
3230 CheckWellKnownSymbol(v8::Symbol::GetIterator, "Symbol.iterator");
3231 CheckWellKnownSymbol(v8::Symbol::GetUnscopables, "Symbol.unscopables");
3232}
3233
3234
3235THREADED_TEST(GlobalPrivates) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003236 i::FLAG_allow_natives_syntax = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003237 LocalContext env;
3238 v8::Isolate* isolate = env->GetIsolate();
3239 v8::HandleScope scope(isolate);
3240
3241 v8::Local<String> name = v8_str("my-private");
3242 v8::Local<v8::Private> glob = v8::Private::ForApi(isolate, name);
3243 v8::Local<v8::Object> obj = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003244 CHECK(obj->SetPrivate(env.local(), glob, v8::Integer::New(isolate, 3))
3245 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003246
3247 v8::Local<v8::Private> glob2 = v8::Private::ForApi(isolate, name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003248 CHECK(obj->HasPrivate(env.local(), glob2).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003249
3250 v8::Local<v8::Private> priv = v8::Private::New(isolate, name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003251 CHECK(!obj->HasPrivate(env.local(), priv).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003252
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003253 CompileRun("var intern = %CreatePrivateSymbol('my-private')");
3254 v8::Local<Value> intern =
3255 env->Global()->Get(env.local(), v8_str("intern")).ToLocalChecked();
3256 CHECK(!obj->Has(env.local(), intern).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003257}
3258
3259
3260class ScopedArrayBufferContents {
3261 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003262 explicit ScopedArrayBufferContents(const v8::ArrayBuffer::Contents& contents)
3263 : contents_(contents) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003264 ~ScopedArrayBufferContents() { free(contents_.Data()); }
3265 void* Data() const { return contents_.Data(); }
3266 size_t ByteLength() const { return contents_.ByteLength(); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003267
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003268 private:
3269 const v8::ArrayBuffer::Contents contents_;
3270};
3271
3272template <typename T>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003273static void CheckInternalFieldsAreZero(v8::Local<T> value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003274 CHECK_EQ(T::kInternalFieldCount, value->InternalFieldCount());
3275 for (int i = 0; i < value->InternalFieldCount(); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003276 CHECK_EQ(0, value->GetInternalField(i)
3277 ->Int32Value(CcTest::isolate()->GetCurrentContext())
3278 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003279 }
3280}
3281
3282
3283THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
3284 LocalContext env;
3285 v8::Isolate* isolate = env->GetIsolate();
3286 v8::HandleScope handle_scope(isolate);
3287
3288 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 1024);
3289 CheckInternalFieldsAreZero(ab);
3290 CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
3291 CHECK(!ab->IsExternal());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003292 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003293
3294 ScopedArrayBufferContents ab_contents(ab->Externalize());
3295 CHECK(ab->IsExternal());
3296
3297 CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
3298 uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003299 CHECK(data != NULL);
3300 CHECK(env->Global()->Set(env.local(), v8_str("ab"), ab).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003301
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003302 v8::Local<v8::Value> result = CompileRun("ab.byteLength");
3303 CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003304
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003305 result = CompileRun(
3306 "var u8 = new Uint8Array(ab);"
3307 "u8[0] = 0xFF;"
3308 "u8[1] = 0xAA;"
3309 "u8.length");
3310 CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003311 CHECK_EQ(0xFF, data[0]);
3312 CHECK_EQ(0xAA, data[1]);
3313 data[0] = 0xCC;
3314 data[1] = 0x11;
3315 result = CompileRun("u8[0] + u8[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003316 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003317}
3318
3319
3320THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
3321 LocalContext env;
3322 v8::Isolate* isolate = env->GetIsolate();
3323 v8::HandleScope handle_scope(isolate);
3324
3325
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003326 v8::Local<v8::Value> result = CompileRun(
3327 "var ab1 = new ArrayBuffer(2);"
3328 "var u8_a = new Uint8Array(ab1);"
3329 "u8_a[0] = 0xAA;"
3330 "u8_a[1] = 0xFF; u8_a.buffer");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003331 Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
3332 CheckInternalFieldsAreZero(ab1);
3333 CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
3334 CHECK(!ab1->IsExternal());
3335 ScopedArrayBufferContents ab1_contents(ab1->Externalize());
3336 CHECK(ab1->IsExternal());
3337
3338 result = CompileRun("ab1.byteLength");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003339 CHECK_EQ(2, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003340 result = CompileRun("u8_a[0]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003341 CHECK_EQ(0xAA, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003342 result = CompileRun("u8_a[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003343 CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
3344 result = CompileRun(
3345 "var u8_b = new Uint8Array(ab1);"
3346 "u8_b[0] = 0xBB;"
3347 "u8_a[0]");
3348 CHECK_EQ(0xBB, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003349 result = CompileRun("u8_b[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003350 CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003351
3352 CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
3353 uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
3354 CHECK_EQ(0xBB, ab1_data[0]);
3355 CHECK_EQ(0xFF, ab1_data[1]);
3356 ab1_data[0] = 0xCC;
3357 ab1_data[1] = 0x11;
3358 result = CompileRun("u8_a[0] + u8_a[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003359 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003360}
3361
3362
3363THREADED_TEST(ArrayBuffer_External) {
3364 LocalContext env;
3365 v8::Isolate* isolate = env->GetIsolate();
3366 v8::HandleScope handle_scope(isolate);
3367
3368 i::ScopedVector<uint8_t> my_data(100);
3369 memset(my_data.start(), 0, 100);
3370 Local<v8::ArrayBuffer> ab3 =
3371 v8::ArrayBuffer::New(isolate, my_data.start(), 100);
3372 CheckInternalFieldsAreZero(ab3);
3373 CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
3374 CHECK(ab3->IsExternal());
3375
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003376 CHECK(env->Global()->Set(env.local(), v8_str("ab3"), ab3).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003377
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003378 v8::Local<v8::Value> result = CompileRun("ab3.byteLength");
3379 CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003380
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003381 result = CompileRun(
3382 "var u8_b = new Uint8Array(ab3);"
3383 "u8_b[0] = 0xBB;"
3384 "u8_b[1] = 0xCC;"
3385 "u8_b.length");
3386 CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003387 CHECK_EQ(0xBB, my_data[0]);
3388 CHECK_EQ(0xCC, my_data[1]);
3389 my_data[0] = 0xCC;
3390 my_data[1] = 0x11;
3391 result = CompileRun("u8_b[0] + u8_b[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003392 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003393}
3394
3395
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003396THREADED_TEST(ArrayBuffer_DisableNeuter) {
3397 LocalContext env;
3398 v8::Isolate* isolate = env->GetIsolate();
3399 v8::HandleScope handle_scope(isolate);
3400
3401 i::ScopedVector<uint8_t> my_data(100);
3402 memset(my_data.start(), 0, 100);
3403 Local<v8::ArrayBuffer> ab =
3404 v8::ArrayBuffer::New(isolate, my_data.start(), 100);
3405 CHECK(ab->IsNeuterable());
3406
3407 i::Handle<i::JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
3408 buf->set_is_neuterable(false);
3409
3410 CHECK(!ab->IsNeuterable());
3411}
3412
3413
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003414static void CheckDataViewIsNeutered(v8::Local<v8::DataView> dv) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003415 CHECK_EQ(0, static_cast<int>(dv->ByteLength()));
3416 CHECK_EQ(0, static_cast<int>(dv->ByteOffset()));
3417}
3418
3419
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003420static void CheckIsNeutered(v8::Local<v8::TypedArray> ta) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003421 CHECK_EQ(0, static_cast<int>(ta->ByteLength()));
3422 CHECK_EQ(0, static_cast<int>(ta->Length()));
3423 CHECK_EQ(0, static_cast<int>(ta->ByteOffset()));
3424}
3425
3426
3427static void CheckIsTypedArrayVarNeutered(const char* name) {
3428 i::ScopedVector<char> source(1024);
3429 i::SNPrintF(source,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003430 "%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
3431 name, name, name);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003432 CHECK(CompileRun(source.start())->IsTrue());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003433 v8::Local<v8::TypedArray> ta =
3434 v8::Local<v8::TypedArray>::Cast(CompileRun(name));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003435 CheckIsNeutered(ta);
3436}
3437
3438
3439template <typename TypedArray, int kElementSize>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003440static Local<TypedArray> CreateAndCheck(Local<v8::ArrayBuffer> ab,
3441 int byteOffset, int length) {
3442 v8::Local<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003443 CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
3444 CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
3445 CHECK_EQ(length, static_cast<int>(ta->Length()));
3446 CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
3447 return ta;
3448}
3449
3450
3451THREADED_TEST(ArrayBuffer_NeuteringApi) {
3452 LocalContext env;
3453 v8::Isolate* isolate = env->GetIsolate();
3454 v8::HandleScope handle_scope(isolate);
3455
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003456 v8::Local<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1024);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003457
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003458 v8::Local<v8::Uint8Array> u8a =
3459 CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
3460 v8::Local<v8::Uint8ClampedArray> u8c =
3461 CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
3462 v8::Local<v8::Int8Array> i8a =
3463 CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003464
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003465 v8::Local<v8::Uint16Array> u16a =
3466 CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
3467 v8::Local<v8::Int16Array> i16a =
3468 CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003469
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003470 v8::Local<v8::Uint32Array> u32a =
3471 CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
3472 v8::Local<v8::Int32Array> i32a =
3473 CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003474
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003475 v8::Local<v8::Float32Array> f32a =
3476 CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
3477 v8::Local<v8::Float64Array> f64a =
3478 CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003479
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003480 v8::Local<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003481 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
3482 CHECK_EQ(1, static_cast<int>(dv->ByteOffset()));
3483 CHECK_EQ(1023, static_cast<int>(dv->ByteLength()));
3484
3485 ScopedArrayBufferContents contents(buffer->Externalize());
3486 buffer->Neuter();
3487 CHECK_EQ(0, static_cast<int>(buffer->ByteLength()));
3488 CheckIsNeutered(u8a);
3489 CheckIsNeutered(u8c);
3490 CheckIsNeutered(i8a);
3491 CheckIsNeutered(u16a);
3492 CheckIsNeutered(i16a);
3493 CheckIsNeutered(u32a);
3494 CheckIsNeutered(i32a);
3495 CheckIsNeutered(f32a);
3496 CheckIsNeutered(f64a);
3497 CheckDataViewIsNeutered(dv);
3498}
3499
3500
3501THREADED_TEST(ArrayBuffer_NeuteringScript) {
3502 LocalContext env;
3503 v8::Isolate* isolate = env->GetIsolate();
3504 v8::HandleScope handle_scope(isolate);
3505
3506 CompileRun(
3507 "var ab = new ArrayBuffer(1024);"
3508 "var u8a = new Uint8Array(ab, 1, 1023);"
3509 "var u8c = new Uint8ClampedArray(ab, 1, 1023);"
3510 "var i8a = new Int8Array(ab, 1, 1023);"
3511 "var u16a = new Uint16Array(ab, 2, 511);"
3512 "var i16a = new Int16Array(ab, 2, 511);"
3513 "var u32a = new Uint32Array(ab, 4, 255);"
3514 "var i32a = new Int32Array(ab, 4, 255);"
3515 "var f32a = new Float32Array(ab, 4, 255);"
3516 "var f64a = new Float64Array(ab, 8, 127);"
3517 "var dv = new DataView(ab, 1, 1023);");
3518
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003519 v8::Local<v8::ArrayBuffer> ab =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003520 Local<v8::ArrayBuffer>::Cast(CompileRun("ab"));
3521
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003522 v8::Local<v8::DataView> dv = v8::Local<v8::DataView>::Cast(CompileRun("dv"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003523
3524 ScopedArrayBufferContents contents(ab->Externalize());
3525 ab->Neuter();
3526 CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003527 CHECK_EQ(0, v8_run_int32value(v8_compile("ab.byteLength")));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003528
3529 CheckIsTypedArrayVarNeutered("u8a");
3530 CheckIsTypedArrayVarNeutered("u8c");
3531 CheckIsTypedArrayVarNeutered("i8a");
3532 CheckIsTypedArrayVarNeutered("u16a");
3533 CheckIsTypedArrayVarNeutered("i16a");
3534 CheckIsTypedArrayVarNeutered("u32a");
3535 CheckIsTypedArrayVarNeutered("i32a");
3536 CheckIsTypedArrayVarNeutered("f32a");
3537 CheckIsTypedArrayVarNeutered("f64a");
3538
3539 CHECK(CompileRun("dv.byteLength == 0 && dv.byteOffset == 0")->IsTrue());
3540 CheckDataViewIsNeutered(dv);
3541}
3542
3543
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003544class ScopedSharedArrayBufferContents {
3545 public:
3546 explicit ScopedSharedArrayBufferContents(
3547 const v8::SharedArrayBuffer::Contents& contents)
3548 : contents_(contents) {}
3549 ~ScopedSharedArrayBufferContents() { free(contents_.Data()); }
3550 void* Data() const { return contents_.Data(); }
3551 size_t ByteLength() const { return contents_.ByteLength(); }
3552
3553 private:
3554 const v8::SharedArrayBuffer::Contents contents_;
3555};
3556
3557
3558THREADED_TEST(SharedArrayBuffer_ApiInternalToExternal) {
3559 i::FLAG_harmony_sharedarraybuffer = true;
3560 LocalContext env;
3561 v8::Isolate* isolate = env->GetIsolate();
3562 v8::HandleScope handle_scope(isolate);
3563
3564 Local<v8::SharedArrayBuffer> ab = v8::SharedArrayBuffer::New(isolate, 1024);
3565 CheckInternalFieldsAreZero(ab);
3566 CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
3567 CHECK(!ab->IsExternal());
3568 CcTest::heap()->CollectAllGarbage();
3569
3570 ScopedSharedArrayBufferContents ab_contents(ab->Externalize());
3571 CHECK(ab->IsExternal());
3572
3573 CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
3574 uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
3575 CHECK(data != NULL);
3576 CHECK(env->Global()->Set(env.local(), v8_str("ab"), ab).FromJust());
3577
3578 v8::Local<v8::Value> result = CompileRun("ab.byteLength");
3579 CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
3580
3581 result = CompileRun(
3582 "var u8 = new Uint8Array(ab);"
3583 "u8[0] = 0xFF;"
3584 "u8[1] = 0xAA;"
3585 "u8.length");
3586 CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
3587 CHECK_EQ(0xFF, data[0]);
3588 CHECK_EQ(0xAA, data[1]);
3589 data[0] = 0xCC;
3590 data[1] = 0x11;
3591 result = CompileRun("u8[0] + u8[1]");
3592 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
3593}
3594
3595
3596THREADED_TEST(SharedArrayBuffer_JSInternalToExternal) {
3597 i::FLAG_harmony_sharedarraybuffer = true;
3598 LocalContext env;
3599 v8::Isolate* isolate = env->GetIsolate();
3600 v8::HandleScope handle_scope(isolate);
3601
3602
3603 v8::Local<v8::Value> result = CompileRun(
3604 "var ab1 = new SharedArrayBuffer(2);"
3605 "var u8_a = new Uint8Array(ab1);"
3606 "u8_a[0] = 0xAA;"
3607 "u8_a[1] = 0xFF; u8_a.buffer");
3608 Local<v8::SharedArrayBuffer> ab1 = Local<v8::SharedArrayBuffer>::Cast(result);
3609 CheckInternalFieldsAreZero(ab1);
3610 CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
3611 CHECK(!ab1->IsExternal());
3612 ScopedSharedArrayBufferContents ab1_contents(ab1->Externalize());
3613 CHECK(ab1->IsExternal());
3614
3615 result = CompileRun("ab1.byteLength");
3616 CHECK_EQ(2, result->Int32Value(env.local()).FromJust());
3617 result = CompileRun("u8_a[0]");
3618 CHECK_EQ(0xAA, result->Int32Value(env.local()).FromJust());
3619 result = CompileRun("u8_a[1]");
3620 CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
3621 result = CompileRun(
3622 "var u8_b = new Uint8Array(ab1);"
3623 "u8_b[0] = 0xBB;"
3624 "u8_a[0]");
3625 CHECK_EQ(0xBB, result->Int32Value(env.local()).FromJust());
3626 result = CompileRun("u8_b[1]");
3627 CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
3628
3629 CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
3630 uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
3631 CHECK_EQ(0xBB, ab1_data[0]);
3632 CHECK_EQ(0xFF, ab1_data[1]);
3633 ab1_data[0] = 0xCC;
3634 ab1_data[1] = 0x11;
3635 result = CompileRun("u8_a[0] + u8_a[1]");
3636 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
3637}
3638
3639
3640THREADED_TEST(SharedArrayBuffer_External) {
3641 i::FLAG_harmony_sharedarraybuffer = true;
3642 LocalContext env;
3643 v8::Isolate* isolate = env->GetIsolate();
3644 v8::HandleScope handle_scope(isolate);
3645
3646 i::ScopedVector<uint8_t> my_data(100);
3647 memset(my_data.start(), 0, 100);
3648 Local<v8::SharedArrayBuffer> ab3 =
3649 v8::SharedArrayBuffer::New(isolate, my_data.start(), 100);
3650 CheckInternalFieldsAreZero(ab3);
3651 CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
3652 CHECK(ab3->IsExternal());
3653
3654 CHECK(env->Global()->Set(env.local(), v8_str("ab3"), ab3).FromJust());
3655
3656 v8::Local<v8::Value> result = CompileRun("ab3.byteLength");
3657 CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
3658
3659 result = CompileRun(
3660 "var u8_b = new Uint8Array(ab3);"
3661 "u8_b[0] = 0xBB;"
3662 "u8_b[1] = 0xCC;"
3663 "u8_b.length");
3664 CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
3665 CHECK_EQ(0xBB, my_data[0]);
3666 CHECK_EQ(0xCC, my_data[1]);
3667 my_data[0] = 0xCC;
3668 my_data[1] = 0x11;
3669 result = CompileRun("u8_b[0] + u8_b[1]");
3670 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
3671}
3672
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003673
3674THREADED_TEST(HiddenProperties) {
3675 LocalContext env;
3676 v8::Isolate* isolate = env->GetIsolate();
3677 v8::HandleScope scope(isolate);
3678
3679 v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003680 v8::Local<v8::Private> key =
3681 v8::Private::ForApi(isolate, v8_str("api-test::hidden-key"));
Steve Blocka7e24c12009-10-30 11:49:00 +00003682 v8::Local<v8::String> empty = v8_str("");
3683 v8::Local<v8::String> prop_name = v8_str("prop_name");
3684
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003685 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +00003686
3687 // Make sure delete of a non-existent hidden value works
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003688 obj->DeletePrivate(env.local(), key).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00003689
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003690 CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 1503))
3691 .FromJust());
3692 CHECK_EQ(1503, obj->GetPrivate(env.local(), key)
3693 .ToLocalChecked()
3694 ->Int32Value(env.local())
3695 .FromJust());
3696 CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 2002))
3697 .FromJust());
3698 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3699 .ToLocalChecked()
3700 ->Int32Value(env.local())
3701 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00003702
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003703 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +00003704
3705 // Make sure we do not find the hidden property.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003706 CHECK(!obj->Has(env.local(), empty).FromJust());
3707 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3708 .ToLocalChecked()
3709 ->Int32Value(env.local())
3710 .FromJust());
3711 CHECK(obj->Get(env.local(), empty).ToLocalChecked()->IsUndefined());
3712 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3713 .ToLocalChecked()
3714 ->Int32Value(env.local())
3715 .FromJust());
3716 CHECK(
3717 obj->Set(env.local(), empty, v8::Integer::New(isolate, 2003)).FromJust());
3718 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3719 .ToLocalChecked()
3720 ->Int32Value(env.local())
3721 .FromJust());
3722 CHECK_EQ(2003, obj->Get(env.local(), empty)
3723 .ToLocalChecked()
3724 ->Int32Value(env.local())
3725 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00003726
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003727 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +00003728
3729 // Add another property and delete it afterwards to force the object in
3730 // slow case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003731 CHECK(obj->Set(env.local(), prop_name, v8::Integer::New(isolate, 2008))
3732 .FromJust());
3733 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3734 .ToLocalChecked()
3735 ->Int32Value(env.local())
3736 .FromJust());
3737 CHECK_EQ(2008, obj->Get(env.local(), prop_name)
3738 .ToLocalChecked()
3739 ->Int32Value(env.local())
3740 .FromJust());
3741 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3742 .ToLocalChecked()
3743 ->Int32Value(env.local())
3744 .FromJust());
3745 CHECK(obj->Delete(env.local(), prop_name).FromJust());
3746 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3747 .ToLocalChecked()
3748 ->Int32Value(env.local())
3749 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00003750
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003751 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +00003752
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003753 CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 2002))
3754 .FromJust());
3755 CHECK(obj->DeletePrivate(env.local(), key).FromJust());
3756 CHECK(!obj->HasPrivate(env.local(), key).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00003757}
3758
3759
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003760THREADED_TEST(Regress97784) {
3761 // Regression test for crbug.com/97784
3762 // Messing with the Object.prototype should not have effect on
3763 // hidden properties.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003764 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003765 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003766
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003767 v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003768 v8::Local<v8::Private> key =
3769 v8::Private::New(env->GetIsolate(), v8_str("hidden"));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003770
3771 CompileRun(
3772 "set_called = false;"
3773 "Object.defineProperty("
3774 " Object.prototype,"
3775 " 'hidden',"
3776 " {get: function() { return 45; },"
3777 " set: function() { set_called = true; }})");
3778
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003779 CHECK(!obj->HasPrivate(env.local(), key).FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003780 // Make sure that the getter and setter from Object.prototype is not invoked.
3781 // If it did we would have full access to the hidden properties in
3782 // the accessor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003783 CHECK(
3784 obj->SetPrivate(env.local(), key, v8::Integer::New(env->GetIsolate(), 42))
3785 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003786 ExpectFalse("set_called");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003787 CHECK_EQ(42, obj->GetPrivate(env.local(), key)
3788 .ToLocalChecked()
3789 ->Int32Value(env.local())
3790 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00003791}
3792
3793
3794THREADED_TEST(External) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003795 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00003796 int x = 3;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003797 Local<v8::External> ext = v8::External::New(CcTest::isolate(), &x);
Steve Blocka7e24c12009-10-30 11:49:00 +00003798 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003799 CHECK(env->Global()->Set(env.local(), v8_str("ext"), ext).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003800 Local<Value> reext_obj = CompileRun("this.ext");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003801 v8::Local<v8::External> reext = reext_obj.As<v8::External>();
Steve Blocka7e24c12009-10-30 11:49:00 +00003802 int* ptr = static_cast<int*>(reext->Value());
3803 CHECK_EQ(x, 3);
3804 *ptr = 10;
3805 CHECK_EQ(x, 10);
3806
3807 // Make sure unaligned pointers are wrapped properly.
3808 char* data = i::StrDup("0123456789");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003809 Local<v8::Value> zero = v8::External::New(CcTest::isolate(), &data[0]);
3810 Local<v8::Value> one = v8::External::New(CcTest::isolate(), &data[1]);
3811 Local<v8::Value> two = v8::External::New(CcTest::isolate(), &data[2]);
3812 Local<v8::Value> three = v8::External::New(CcTest::isolate(), &data[3]);
Steve Blocka7e24c12009-10-30 11:49:00 +00003813
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003814 char* char_ptr = reinterpret_cast<char*>(v8::External::Cast(*zero)->Value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003815 CHECK_EQ('0', *char_ptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003816 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*one)->Value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003817 CHECK_EQ('1', *char_ptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003818 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*two)->Value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003819 CHECK_EQ('2', *char_ptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003820 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*three)->Value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003821 CHECK_EQ('3', *char_ptr);
3822 i::DeleteArray(data);
3823}
3824
3825
3826THREADED_TEST(GlobalHandle) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003827 v8::Isolate* isolate = CcTest::isolate();
Steve Blocka7e24c12009-10-30 11:49:00 +00003828 v8::Persistent<String> global;
3829 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003830 v8::HandleScope scope(isolate);
3831 global.Reset(isolate, v8_str("str"));
Steve Blocka7e24c12009-10-30 11:49:00 +00003832 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003833 {
3834 v8::HandleScope scope(isolate);
3835 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3836 }
3837 global.Reset();
3838 {
3839 v8::HandleScope scope(isolate);
3840 global.Reset(isolate, v8_str("str"));
3841 }
3842 {
3843 v8::HandleScope scope(isolate);
3844 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3845 }
3846 global.Reset();
3847}
3848
3849
3850THREADED_TEST(ResettingGlobalHandle) {
3851 v8::Isolate* isolate = CcTest::isolate();
3852 v8::Persistent<String> global;
3853 {
3854 v8::HandleScope scope(isolate);
3855 global.Reset(isolate, v8_str("str"));
3856 }
3857 v8::internal::GlobalHandles* global_handles =
3858 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3859 int initial_handle_count = global_handles->global_handles_count();
3860 {
3861 v8::HandleScope scope(isolate);
3862 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3863 }
3864 {
3865 v8::HandleScope scope(isolate);
3866 global.Reset(isolate, v8_str("longer"));
3867 }
3868 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count);
3869 {
3870 v8::HandleScope scope(isolate);
3871 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 6);
3872 }
3873 global.Reset();
3874 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
3875}
3876
3877
3878THREADED_TEST(ResettingGlobalHandleToEmpty) {
3879 v8::Isolate* isolate = CcTest::isolate();
3880 v8::Persistent<String> global;
3881 {
3882 v8::HandleScope scope(isolate);
3883 global.Reset(isolate, v8_str("str"));
3884 }
3885 v8::internal::GlobalHandles* global_handles =
3886 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3887 int initial_handle_count = global_handles->global_handles_count();
3888 {
3889 v8::HandleScope scope(isolate);
3890 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3891 }
3892 {
3893 v8::HandleScope scope(isolate);
3894 Local<String> empty;
3895 global.Reset(isolate, empty);
3896 }
3897 CHECK(global.IsEmpty());
3898 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
3899}
3900
3901
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003902template <class T>
3903static v8::Global<T> PassUnique(v8::Global<T> unique) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003904 return unique.Pass();
3905}
3906
3907
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003908template <class T>
3909static v8::Global<T> ReturnUnique(v8::Isolate* isolate,
3910 const v8::Persistent<T>& global) {
3911 v8::Global<String> unique(isolate, global);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003912 return unique.Pass();
3913}
3914
3915
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003916THREADED_TEST(Global) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003917 v8::Isolate* isolate = CcTest::isolate();
3918 v8::Persistent<String> global;
3919 {
3920 v8::HandleScope scope(isolate);
3921 global.Reset(isolate, v8_str("str"));
3922 }
3923 v8::internal::GlobalHandles* global_handles =
3924 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3925 int initial_handle_count = global_handles->global_handles_count();
3926 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003927 v8::Global<String> unique(isolate, global);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003928 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3929 // Test assignment via Pass
3930 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003931 v8::Global<String> copy = unique.Pass();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003932 CHECK(unique.IsEmpty());
3933 CHECK(copy == global);
3934 CHECK_EQ(initial_handle_count + 1,
3935 global_handles->global_handles_count());
3936 unique = copy.Pass();
3937 }
3938 // Test ctor via Pass
3939 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003940 v8::Global<String> copy(unique.Pass());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003941 CHECK(unique.IsEmpty());
3942 CHECK(copy == global);
3943 CHECK_EQ(initial_handle_count + 1,
3944 global_handles->global_handles_count());
3945 unique = copy.Pass();
3946 }
3947 // Test pass through function call
3948 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003949 v8::Global<String> copy = PassUnique(unique.Pass());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003950 CHECK(unique.IsEmpty());
3951 CHECK(copy == global);
3952 CHECK_EQ(initial_handle_count + 1,
3953 global_handles->global_handles_count());
3954 unique = copy.Pass();
3955 }
3956 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3957 }
3958 // Test pass from function call
3959 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003960 v8::Global<String> unique = ReturnUnique(isolate, global);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003961 CHECK(unique == global);
3962 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3963 }
3964 CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
3965 global.Reset();
3966}
3967
3968
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003969namespace {
3970
3971class TwoPassCallbackData;
3972void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
3973void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
3974
3975
3976class TwoPassCallbackData {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003977 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003978 TwoPassCallbackData(v8::Isolate* isolate, int* instance_counter)
3979 : first_pass_called_(false),
3980 second_pass_called_(false),
3981 trigger_gc_(false),
3982 instance_counter_(instance_counter) {
3983 HandleScope scope(isolate);
3984 i::ScopedVector<char> buffer(40);
3985 i::SNPrintF(buffer, "%p", static_cast<void*>(this));
3986 auto string =
3987 v8::String::NewFromUtf8(isolate, buffer.start(),
3988 v8::NewStringType::kNormal).ToLocalChecked();
3989 cell_.Reset(isolate, string);
3990 (*instance_counter_)++;
3991 }
3992
3993 ~TwoPassCallbackData() {
3994 CHECK(first_pass_called_);
3995 CHECK(second_pass_called_);
3996 CHECK(cell_.IsEmpty());
3997 (*instance_counter_)--;
3998 }
3999
4000 void FirstPass() {
4001 CHECK(!first_pass_called_);
4002 CHECK(!second_pass_called_);
4003 CHECK(!cell_.IsEmpty());
4004 cell_.Reset();
4005 first_pass_called_ = true;
4006 }
4007
4008 void SecondPass() {
4009 CHECK(first_pass_called_);
4010 CHECK(!second_pass_called_);
4011 CHECK(cell_.IsEmpty());
4012 second_pass_called_ = true;
4013 delete this;
4014 }
4015
4016 void SetWeak() {
4017 cell_.SetWeak(this, FirstPassCallback, v8::WeakCallbackType::kParameter);
4018 }
4019
4020 void MarkTriggerGc() { trigger_gc_ = true; }
4021 bool trigger_gc() { return trigger_gc_; }
4022
4023 int* instance_counter() { return instance_counter_; }
4024
4025 private:
4026 bool first_pass_called_;
4027 bool second_pass_called_;
4028 bool trigger_gc_;
4029 v8::Global<v8::String> cell_;
4030 int* instance_counter_;
4031};
4032
4033
4034void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
4035 ApiTestFuzzer::Fuzz();
4036 bool trigger_gc = data.GetParameter()->trigger_gc();
4037 int* instance_counter = data.GetParameter()->instance_counter();
4038 data.GetParameter()->SecondPass();
4039 if (!trigger_gc) return;
4040 auto data_2 = new TwoPassCallbackData(data.GetIsolate(), instance_counter);
4041 data_2->SetWeak();
4042 CcTest::heap()->CollectAllGarbage();
4043}
4044
4045
4046void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
4047 data.GetParameter()->FirstPass();
4048 data.SetSecondPassCallback(SecondPassCallback);
4049}
4050
4051} // namespace
4052
4053
4054TEST(TwoPassPhantomCallbacks) {
4055 auto isolate = CcTest::isolate();
4056 const size_t kLength = 20;
4057 int instance_counter = 0;
4058 for (size_t i = 0; i < kLength; ++i) {
4059 auto data = new TwoPassCallbackData(isolate, &instance_counter);
4060 data->SetWeak();
4061 }
4062 CHECK_EQ(static_cast<int>(kLength), instance_counter);
4063 CcTest::heap()->CollectAllGarbage();
4064 EmptyMessageQueues(isolate);
4065 CHECK_EQ(0, instance_counter);
4066}
4067
4068
4069TEST(TwoPassPhantomCallbacksNestedGc) {
4070 auto isolate = CcTest::isolate();
4071 const size_t kLength = 20;
4072 TwoPassCallbackData* array[kLength];
4073 int instance_counter = 0;
4074 for (size_t i = 0; i < kLength; ++i) {
4075 array[i] = new TwoPassCallbackData(isolate, &instance_counter);
4076 array[i]->SetWeak();
4077 }
4078 array[5]->MarkTriggerGc();
4079 array[10]->MarkTriggerGc();
4080 array[15]->MarkTriggerGc();
4081 CHECK_EQ(static_cast<int>(kLength), instance_counter);
4082 CcTest::heap()->CollectAllGarbage();
4083 EmptyMessageQueues(isolate);
4084 CHECK_EQ(0, instance_counter);
4085}
4086
4087
4088namespace {
4089
4090void* IntKeyToVoidPointer(int key) { return reinterpret_cast<void*>(key << 1); }
4091
4092
4093Local<v8::Object> NewObjectForIntKey(
4094 v8::Isolate* isolate, const v8::Global<v8::ObjectTemplate>& templ,
4095 int key) {
4096 auto local = Local<v8::ObjectTemplate>::New(isolate, templ);
4097 auto obj = local->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
4098 obj->SetAlignedPointerInInternalField(0, IntKeyToVoidPointer(key));
4099 return obj;
4100}
4101
4102
4103template <typename K, typename V>
4104class PhantomStdMapTraits : public v8::StdMapTraits<K, V> {
4105 public:
4106 typedef typename v8::GlobalValueMap<K, V, PhantomStdMapTraits<K, V>> MapType;
4107 static const v8::PersistentContainerCallbackType kCallbackType =
4108 v8::kWeakWithInternalFields;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004109 struct WeakCallbackDataType {
4110 MapType* map;
4111 K key;
4112 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004113 static WeakCallbackDataType* WeakCallbackParameter(MapType* map, const K& key,
4114 Local<V> value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004115 WeakCallbackDataType* data = new WeakCallbackDataType;
4116 data->map = map;
4117 data->key = key;
4118 return data;
4119 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004120 static MapType* MapFromWeakCallbackInfo(
4121 const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004122 return data.GetParameter()->map;
4123 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004124 static K KeyFromWeakCallbackInfo(
4125 const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004126 return data.GetParameter()->key;
4127 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004128 static void DisposeCallbackData(WeakCallbackDataType* data) { delete data; }
4129 static void Dispose(v8::Isolate* isolate, v8::Global<V> value, K key) {
4130 CHECK_EQ(IntKeyToVoidPointer(key),
4131 v8::Object::GetAlignedPointerFromInternalField(value, 0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004132 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004133 static void OnWeakCallback(
4134 const v8::WeakCallbackInfo<WeakCallbackDataType>&) {}
4135 static void DisposeWeak(
4136 const v8::WeakCallbackInfo<WeakCallbackDataType>& info) {
4137 K key = KeyFromWeakCallbackInfo(info);
4138 CHECK_EQ(IntKeyToVoidPointer(key), info.GetInternalField(0));
4139 DisposeCallbackData(info.GetParameter());
4140 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004141};
4142
4143
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004144template <typename Map>
4145void TestGlobalValueMap() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004146 LocalContext env;
4147 v8::Isolate* isolate = env->GetIsolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004148 v8::Global<ObjectTemplate> templ;
4149 {
4150 HandleScope scope(isolate);
4151 auto t = ObjectTemplate::New(isolate);
4152 t->SetInternalFieldCount(1);
4153 templ.Reset(isolate, t);
4154 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004155 Map map(isolate);
4156 v8::internal::GlobalHandles* global_handles =
4157 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
4158 int initial_handle_count = global_handles->global_handles_count();
4159 CHECK_EQ(0, static_cast<int>(map.Size()));
4160 {
4161 HandleScope scope(isolate);
4162 Local<v8::Object> obj = map.Get(7);
4163 CHECK(obj.IsEmpty());
4164 Local<v8::Object> expected = v8::Object::New(isolate);
4165 map.Set(7, expected);
4166 CHECK_EQ(1, static_cast<int>(map.Size()));
4167 obj = map.Get(7);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004168 CHECK(expected->Equals(env.local(), obj).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004169 {
4170 typename Map::PersistentValueReference ref = map.GetReference(7);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004171 CHECK(expected->Equals(env.local(), ref.NewLocal(isolate)).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004172 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004173 v8::Global<v8::Object> removed = map.Remove(7);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004174 CHECK_EQ(0, static_cast<int>(map.Size()));
4175 CHECK(expected == removed);
4176 removed = map.Remove(7);
4177 CHECK(removed.IsEmpty());
4178 map.Set(8, expected);
4179 CHECK_EQ(1, static_cast<int>(map.Size()));
4180 map.Set(8, expected);
4181 CHECK_EQ(1, static_cast<int>(map.Size()));
4182 {
4183 typename Map::PersistentValueReference ref;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004184 Local<v8::Object> expected2 = NewObjectForIntKey(isolate, templ, 8);
4185 removed = map.Set(8, v8::Global<v8::Object>(isolate, expected2), &ref);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004186 CHECK_EQ(1, static_cast<int>(map.Size()));
4187 CHECK(expected == removed);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004188 CHECK(expected2->Equals(env.local(), ref.NewLocal(isolate)).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004189 }
4190 }
4191 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
4192 if (map.IsWeak()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004193 CcTest::i_isolate()->heap()->CollectAllGarbage(
4194 i::Heap::kAbortIncrementalMarkingMask);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004195 } else {
4196 map.Clear();
4197 }
4198 CHECK_EQ(0, static_cast<int>(map.Size()));
4199 CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004200 {
4201 HandleScope scope(isolate);
4202 Local<v8::Object> value = NewObjectForIntKey(isolate, templ, 9);
4203 map.Set(9, value);
4204 map.Clear();
4205 }
4206 CHECK_EQ(0, static_cast<int>(map.Size()));
4207 CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004208}
4209
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004210} // namespace
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004211
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004212
4213TEST(GlobalValueMap) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004214 // Default case, w/o weak callbacks:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004215 TestGlobalValueMap<v8::StdGlobalValueMap<int, v8::Object>>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004216
4217 // Custom traits with weak callbacks:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004218 typedef v8::GlobalValueMap<int, v8::Object,
4219 PhantomStdMapTraits<int, v8::Object>> WeakMap;
4220 TestGlobalValueMap<WeakMap>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004221}
4222
4223
4224TEST(PersistentValueVector) {
4225 LocalContext env;
4226 v8::Isolate* isolate = env->GetIsolate();
4227 v8::internal::GlobalHandles* global_handles =
4228 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
4229 int handle_count = global_handles->global_handles_count();
4230 HandleScope scope(isolate);
4231
4232 v8::PersistentValueVector<v8::Object> vector(isolate);
4233
4234 Local<v8::Object> obj1 = v8::Object::New(isolate);
4235 Local<v8::Object> obj2 = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004236 v8::Global<v8::Object> obj3(isolate, v8::Object::New(isolate));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004237
4238 CHECK(vector.IsEmpty());
4239 CHECK_EQ(0, static_cast<int>(vector.Size()));
4240
4241 vector.ReserveCapacity(3);
4242 CHECK(vector.IsEmpty());
4243
4244 vector.Append(obj1);
4245 vector.Append(obj2);
4246 vector.Append(obj1);
4247 vector.Append(obj3.Pass());
4248 vector.Append(obj1);
4249
4250 CHECK(!vector.IsEmpty());
4251 CHECK_EQ(5, static_cast<int>(vector.Size()));
4252 CHECK(obj3.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004253 CHECK(obj1->Equals(env.local(), vector.Get(0)).FromJust());
4254 CHECK(obj1->Equals(env.local(), vector.Get(2)).FromJust());
4255 CHECK(obj1->Equals(env.local(), vector.Get(4)).FromJust());
4256 CHECK(obj2->Equals(env.local(), vector.Get(1)).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004257
4258 CHECK_EQ(5 + handle_count, global_handles->global_handles_count());
4259
4260 vector.Clear();
4261 CHECK(vector.IsEmpty());
4262 CHECK_EQ(0, static_cast<int>(vector.Size()));
4263 CHECK_EQ(handle_count, global_handles->global_handles_count());
4264}
4265
4266
4267THREADED_TEST(GlobalHandleUpcast) {
4268 v8::Isolate* isolate = CcTest::isolate();
4269 v8::HandleScope scope(isolate);
4270 v8::Local<String> local = v8::Local<String>::New(isolate, v8_str("str"));
4271 v8::Persistent<String> global_string(isolate, local);
4272 v8::Persistent<Value>& global_value =
4273 v8::Persistent<Value>::Cast(global_string);
4274 CHECK(v8::Local<v8::Value>::New(isolate, global_value)->IsString());
4275 CHECK(global_string == v8::Persistent<String>::Cast(global_value));
4276 global_string.Reset();
4277}
4278
4279
4280THREADED_TEST(HandleEquality) {
4281 v8::Isolate* isolate = CcTest::isolate();
4282 v8::Persistent<String> global1;
4283 v8::Persistent<String> global2;
4284 {
4285 v8::HandleScope scope(isolate);
4286 global1.Reset(isolate, v8_str("str"));
4287 global2.Reset(isolate, v8_str("str2"));
4288 }
4289 CHECK_EQ(global1 == global1, true);
4290 CHECK_EQ(global1 != global1, false);
4291 {
4292 v8::HandleScope scope(isolate);
4293 Local<String> local1 = Local<String>::New(isolate, global1);
4294 Local<String> local2 = Local<String>::New(isolate, global2);
4295
4296 CHECK_EQ(global1 == local1, true);
4297 CHECK_EQ(global1 != local1, false);
4298 CHECK_EQ(local1 == global1, true);
4299 CHECK_EQ(local1 != global1, false);
4300
4301 CHECK_EQ(global1 == local2, false);
4302 CHECK_EQ(global1 != local2, true);
4303 CHECK_EQ(local2 == global1, false);
4304 CHECK_EQ(local2 != global1, true);
4305
4306 CHECK_EQ(local1 == local2, false);
4307 CHECK_EQ(local1 != local2, true);
4308
4309 Local<String> anotherLocal1 = Local<String>::New(isolate, global1);
4310 CHECK_EQ(local1 == anotherLocal1, true);
4311 CHECK_EQ(local1 != anotherLocal1, false);
4312 }
4313 global1.Reset();
4314 global2.Reset();
4315}
4316
4317
4318THREADED_TEST(LocalHandle) {
4319 v8::HandleScope scope(CcTest::isolate());
4320 v8::Local<String> local =
4321 v8::Local<String>::New(CcTest::isolate(), v8_str("str"));
4322 CHECK_EQ(local->Length(), 3);
Steve Blocka7e24c12009-10-30 11:49:00 +00004323}
4324
4325
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004326class WeakCallCounter {
4327 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004328 explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) {}
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004329 int id() { return id_; }
4330 void increment() { number_of_weak_calls_++; }
4331 int NumberOfWeakCalls() { return number_of_weak_calls_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004332
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004333 private:
4334 int id_;
4335 int number_of_weak_calls_;
4336};
4337
4338
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004339template <typename T>
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004340struct WeakCallCounterAndPersistent {
4341 explicit WeakCallCounterAndPersistent(WeakCallCounter* counter)
4342 : counter(counter) {}
4343 WeakCallCounter* counter;
4344 v8::Persistent<T> handle;
4345};
4346
4347
4348template <typename T>
4349static void WeakPointerCallback(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004350 const v8::WeakCallbackInfo<WeakCallCounterAndPersistent<T>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004351 CHECK_EQ(1234, data.GetParameter()->counter->id());
4352 data.GetParameter()->counter->increment();
4353 data.GetParameter()->handle.Reset();
4354}
4355
4356
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004357template <typename T>
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004358static UniqueId MakeUniqueId(const Persistent<T>& p) {
4359 return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
Steve Block44f0eee2011-05-26 01:26:41 +01004360}
4361
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004362
Steve Block44f0eee2011-05-26 01:26:41 +01004363THREADED_TEST(ApiObjectGroups) {
Steve Block44f0eee2011-05-26 01:26:41 +01004364 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004365 v8::Isolate* iso = env->GetIsolate();
4366 HandleScope scope(iso);
Steve Block44f0eee2011-05-26 01:26:41 +01004367
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004368 WeakCallCounter counter(1234);
4369
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004370 WeakCallCounterAndPersistent<Value> g1s1(&counter);
4371 WeakCallCounterAndPersistent<Value> g1s2(&counter);
4372 WeakCallCounterAndPersistent<Value> g1c1(&counter);
4373 WeakCallCounterAndPersistent<Value> g2s1(&counter);
4374 WeakCallCounterAndPersistent<Value> g2s2(&counter);
4375 WeakCallCounterAndPersistent<Value> g2c1(&counter);
Steve Block44f0eee2011-05-26 01:26:41 +01004376
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004377 {
4378 HandleScope scope(iso);
4379 g1s1.handle.Reset(iso, Object::New(iso));
4380 g1s2.handle.Reset(iso, Object::New(iso));
4381 g1c1.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004382 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
4383 v8::WeakCallbackType::kParameter);
4384 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
4385 v8::WeakCallbackType::kParameter);
4386 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
4387 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004388
4389 g2s1.handle.Reset(iso, Object::New(iso));
4390 g2s2.handle.Reset(iso, Object::New(iso));
4391 g2c1.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004392 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
4393 v8::WeakCallbackType::kParameter);
4394 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
4395 v8::WeakCallbackType::kParameter);
4396 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
4397 v8::WeakCallbackType::kParameter);
Steve Block44f0eee2011-05-26 01:26:41 +01004398 }
4399
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004400 WeakCallCounterAndPersistent<Value> root(&counter);
4401 root.handle.Reset(iso, g1s1.handle); // make a root.
Steve Block44f0eee2011-05-26 01:26:41 +01004402
4403 // Connect group 1 and 2, make a cycle.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004404 {
4405 HandleScope scope(iso);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004406 CHECK(Local<Object>::New(iso, g1s2.handle.As<Object>())
4407 ->Set(env.local(), 0, Local<Value>::New(iso, g2s2.handle))
4408 .FromJust());
4409 CHECK(Local<Object>::New(iso, g2s1.handle.As<Object>())
4410 ->Set(env.local(), 0, Local<Value>::New(iso, g1s1.handle))
4411 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004412 }
Steve Block44f0eee2011-05-26 01:26:41 +01004413
4414 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004415 UniqueId id1 = MakeUniqueId(g1s1.handle);
4416 UniqueId id2 = MakeUniqueId(g2s2.handle);
4417 iso->SetObjectGroupId(g1s1.handle, id1);
4418 iso->SetObjectGroupId(g1s2.handle, id1);
4419 iso->SetReferenceFromGroup(id1, g1c1.handle);
4420 iso->SetObjectGroupId(g2s1.handle, id2);
4421 iso->SetObjectGroupId(g2s2.handle, id2);
4422 iso->SetReferenceFromGroup(id2, g2c1.handle);
Steve Block44f0eee2011-05-26 01:26:41 +01004423 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004424 // Do a single full GC, ensure incremental marking is stopped.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004425 v8::internal::Heap* heap =
4426 reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
4427 heap->CollectAllGarbage();
Steve Block44f0eee2011-05-26 01:26:41 +01004428
4429 // All object should be alive.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004430 CHECK_EQ(0, counter.NumberOfWeakCalls());
Steve Block44f0eee2011-05-26 01:26:41 +01004431
4432 // Weaken the root.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004433 root.handle.SetWeak(&root, &WeakPointerCallback,
4434 v8::WeakCallbackType::kParameter);
Steve Block44f0eee2011-05-26 01:26:41 +01004435 // But make children strong roots---all the objects (except for children)
4436 // should be collectable now.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004437 g1c1.handle.ClearWeak();
4438 g2c1.handle.ClearWeak();
Steve Block44f0eee2011-05-26 01:26:41 +01004439
4440 // Groups are deleted, rebuild groups.
4441 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004442 UniqueId id1 = MakeUniqueId(g1s1.handle);
4443 UniqueId id2 = MakeUniqueId(g2s2.handle);
4444 iso->SetObjectGroupId(g1s1.handle, id1);
4445 iso->SetObjectGroupId(g1s2.handle, id1);
4446 iso->SetReferenceFromGroup(id1, g1c1.handle);
4447 iso->SetObjectGroupId(g2s1.handle, id2);
4448 iso->SetObjectGroupId(g2s2.handle, id2);
4449 iso->SetReferenceFromGroup(id2, g2c1.handle);
Steve Block44f0eee2011-05-26 01:26:41 +01004450 }
4451
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004452 heap->CollectAllGarbage();
Steve Block44f0eee2011-05-26 01:26:41 +01004453
4454 // All objects should be gone. 5 global handles in total.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004455 CHECK_EQ(5, counter.NumberOfWeakCalls());
Steve Block44f0eee2011-05-26 01:26:41 +01004456
4457 // And now make children weak again and collect them.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004458 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
4459 v8::WeakCallbackType::kParameter);
4460 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
4461 v8::WeakCallbackType::kParameter);
Steve Block44f0eee2011-05-26 01:26:41 +01004462
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004463 heap->CollectAllGarbage();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004464 CHECK_EQ(7, counter.NumberOfWeakCalls());
Steve Block44f0eee2011-05-26 01:26:41 +01004465}
4466
4467
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004468THREADED_TEST(ApiObjectGroupsForSubtypes) {
Steve Block44f0eee2011-05-26 01:26:41 +01004469 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004470 v8::Isolate* iso = env->GetIsolate();
4471 HandleScope scope(iso);
Steve Block44f0eee2011-05-26 01:26:41 +01004472
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004473 WeakCallCounter counter(1234);
Steve Block44f0eee2011-05-26 01:26:41 +01004474
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004475 WeakCallCounterAndPersistent<Object> g1s1(&counter);
4476 WeakCallCounterAndPersistent<String> g1s2(&counter);
4477 WeakCallCounterAndPersistent<String> g1c1(&counter);
4478 WeakCallCounterAndPersistent<Object> g2s1(&counter);
4479 WeakCallCounterAndPersistent<String> g2s2(&counter);
4480 WeakCallCounterAndPersistent<String> g2c1(&counter);
Steve Block44f0eee2011-05-26 01:26:41 +01004481
4482 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004483 HandleScope scope(iso);
4484 g1s1.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004485 g1s2.handle.Reset(iso, v8_str("foo1"));
4486 g1c1.handle.Reset(iso, v8_str("foo2"));
4487 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
4488 v8::WeakCallbackType::kParameter);
4489 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
4490 v8::WeakCallbackType::kParameter);
4491 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
4492 v8::WeakCallbackType::kParameter);
Steve Block44f0eee2011-05-26 01:26:41 +01004493
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004494 g2s1.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004495 g2s2.handle.Reset(iso, v8_str("foo3"));
4496 g2c1.handle.Reset(iso, v8_str("foo4"));
4497 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
4498 v8::WeakCallbackType::kParameter);
4499 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
4500 v8::WeakCallbackType::kParameter);
4501 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
4502 v8::WeakCallbackType::kParameter);
Steve Block44f0eee2011-05-26 01:26:41 +01004503 }
4504
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004505 WeakCallCounterAndPersistent<Value> root(&counter);
4506 root.handle.Reset(iso, g1s1.handle); // make a root.
Steve Block44f0eee2011-05-26 01:26:41 +01004507
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004508 // Connect group 1 and 2, make a cycle.
Steve Block44f0eee2011-05-26 01:26:41 +01004509 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004510 HandleScope scope(iso);
4511 CHECK(Local<Object>::New(iso, g1s1.handle)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004512 ->Set(env.local(), 0, Local<Object>::New(iso, g2s1.handle))
4513 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004514 CHECK(Local<Object>::New(iso, g2s1.handle)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004515 ->Set(env.local(), 0, Local<Object>::New(iso, g1s1.handle))
4516 .FromJust());
Steve Block44f0eee2011-05-26 01:26:41 +01004517 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004518
4519 {
4520 UniqueId id1 = MakeUniqueId(g1s1.handle);
4521 UniqueId id2 = MakeUniqueId(g2s2.handle);
4522 iso->SetObjectGroupId(g1s1.handle, id1);
4523 iso->SetObjectGroupId(g1s2.handle, id1);
4524 iso->SetReference(g1s1.handle, g1c1.handle);
4525 iso->SetObjectGroupId(g2s1.handle, id2);
4526 iso->SetObjectGroupId(g2s2.handle, id2);
4527 iso->SetReferenceFromGroup(id2, g2c1.handle);
4528 }
4529 // Do a single full GC, ensure incremental marking is stopped.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004530 v8::internal::Heap* heap =
4531 reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
4532 heap->CollectAllGarbage();
Steve Block44f0eee2011-05-26 01:26:41 +01004533
4534 // All object should be alive.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004535 CHECK_EQ(0, counter.NumberOfWeakCalls());
Steve Block44f0eee2011-05-26 01:26:41 +01004536
4537 // Weaken the root.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004538 root.handle.SetWeak(&root, &WeakPointerCallback,
4539 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004540 // But make children strong roots---all the objects (except for children)
4541 // should be collectable now.
4542 g1c1.handle.ClearWeak();
4543 g2c1.handle.ClearWeak();
Steve Block44f0eee2011-05-26 01:26:41 +01004544
4545 // Groups are deleted, rebuild groups.
4546 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004547 UniqueId id1 = MakeUniqueId(g1s1.handle);
4548 UniqueId id2 = MakeUniqueId(g2s2.handle);
4549 iso->SetObjectGroupId(g1s1.handle, id1);
4550 iso->SetObjectGroupId(g1s2.handle, id1);
4551 iso->SetReference(g1s1.handle, g1c1.handle);
4552 iso->SetObjectGroupId(g2s1.handle, id2);
4553 iso->SetObjectGroupId(g2s2.handle, id2);
4554 iso->SetReferenceFromGroup(id2, g2c1.handle);
Steve Block44f0eee2011-05-26 01:26:41 +01004555 }
4556
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004557 heap->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004558
4559 // All objects should be gone. 5 global handles in total.
4560 CHECK_EQ(5, counter.NumberOfWeakCalls());
4561
4562 // And now make children weak again and collect them.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004563 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
4564 v8::WeakCallbackType::kParameter);
4565 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
4566 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004567
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004568 heap->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004569 CHECK_EQ(7, counter.NumberOfWeakCalls());
4570}
4571
4572
4573THREADED_TEST(ApiObjectGroupsCycle) {
4574 LocalContext env;
4575 v8::Isolate* iso = env->GetIsolate();
4576 HandleScope scope(iso);
4577
4578 WeakCallCounter counter(1234);
4579
4580 WeakCallCounterAndPersistent<Value> g1s1(&counter);
4581 WeakCallCounterAndPersistent<Value> g1s2(&counter);
4582 WeakCallCounterAndPersistent<Value> g2s1(&counter);
4583 WeakCallCounterAndPersistent<Value> g2s2(&counter);
4584 WeakCallCounterAndPersistent<Value> g3s1(&counter);
4585 WeakCallCounterAndPersistent<Value> g3s2(&counter);
4586 WeakCallCounterAndPersistent<Value> g4s1(&counter);
4587 WeakCallCounterAndPersistent<Value> g4s2(&counter);
4588
4589 {
4590 HandleScope scope(iso);
4591 g1s1.handle.Reset(iso, Object::New(iso));
4592 g1s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004593 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
4594 v8::WeakCallbackType::kParameter);
4595 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
4596 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004597 CHECK(g1s1.handle.IsWeak());
4598 CHECK(g1s2.handle.IsWeak());
4599
4600 g2s1.handle.Reset(iso, Object::New(iso));
4601 g2s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004602 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
4603 v8::WeakCallbackType::kParameter);
4604 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
4605 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004606 CHECK(g2s1.handle.IsWeak());
4607 CHECK(g2s2.handle.IsWeak());
4608
4609 g3s1.handle.Reset(iso, Object::New(iso));
4610 g3s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004611 g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback,
4612 v8::WeakCallbackType::kParameter);
4613 g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback,
4614 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004615 CHECK(g3s1.handle.IsWeak());
4616 CHECK(g3s2.handle.IsWeak());
4617
4618 g4s1.handle.Reset(iso, Object::New(iso));
4619 g4s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004620 g4s1.handle.SetWeak(&g4s1, &WeakPointerCallback,
4621 v8::WeakCallbackType::kParameter);
4622 g4s2.handle.SetWeak(&g4s2, &WeakPointerCallback,
4623 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004624 CHECK(g4s1.handle.IsWeak());
4625 CHECK(g4s2.handle.IsWeak());
4626 }
4627
4628 WeakCallCounterAndPersistent<Value> root(&counter);
4629 root.handle.Reset(iso, g1s1.handle); // make a root.
4630
4631 // Connect groups. We're building the following cycle:
4632 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
4633 // groups.
4634 {
4635 UniqueId id1 = MakeUniqueId(g1s1.handle);
4636 UniqueId id2 = MakeUniqueId(g2s1.handle);
4637 UniqueId id3 = MakeUniqueId(g3s1.handle);
4638 UniqueId id4 = MakeUniqueId(g4s1.handle);
4639 iso->SetObjectGroupId(g1s1.handle, id1);
4640 iso->SetObjectGroupId(g1s2.handle, id1);
4641 iso->SetReferenceFromGroup(id1, g2s1.handle);
4642 iso->SetObjectGroupId(g2s1.handle, id2);
4643 iso->SetObjectGroupId(g2s2.handle, id2);
4644 iso->SetReferenceFromGroup(id2, g3s1.handle);
4645 iso->SetObjectGroupId(g3s1.handle, id3);
4646 iso->SetObjectGroupId(g3s2.handle, id3);
4647 iso->SetReferenceFromGroup(id3, g4s1.handle);
4648 iso->SetObjectGroupId(g4s1.handle, id4);
4649 iso->SetObjectGroupId(g4s2.handle, id4);
4650 iso->SetReferenceFromGroup(id4, g1s1.handle);
4651 }
4652 // Do a single full GC
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004653 v8::internal::Heap* heap =
4654 reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
4655 heap->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004656
4657 // All object should be alive.
4658 CHECK_EQ(0, counter.NumberOfWeakCalls());
4659
4660 // Weaken the root.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004661 root.handle.SetWeak(&root, &WeakPointerCallback,
4662 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004663
4664 // Groups are deleted, rebuild groups.
4665 {
4666 UniqueId id1 = MakeUniqueId(g1s1.handle);
4667 UniqueId id2 = MakeUniqueId(g2s1.handle);
4668 UniqueId id3 = MakeUniqueId(g3s1.handle);
4669 UniqueId id4 = MakeUniqueId(g4s1.handle);
4670 iso->SetObjectGroupId(g1s1.handle, id1);
4671 iso->SetObjectGroupId(g1s2.handle, id1);
4672 iso->SetReferenceFromGroup(id1, g2s1.handle);
4673 iso->SetObjectGroupId(g2s1.handle, id2);
4674 iso->SetObjectGroupId(g2s2.handle, id2);
4675 iso->SetReferenceFromGroup(id2, g3s1.handle);
4676 iso->SetObjectGroupId(g3s1.handle, id3);
4677 iso->SetObjectGroupId(g3s2.handle, id3);
4678 iso->SetReferenceFromGroup(id3, g4s1.handle);
4679 iso->SetObjectGroupId(g4s1.handle, id4);
4680 iso->SetObjectGroupId(g4s2.handle, id4);
4681 iso->SetReferenceFromGroup(id4, g1s1.handle);
4682 }
4683
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004684 heap->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004685
4686 // All objects should be gone. 9 global handles in total.
4687 CHECK_EQ(9, counter.NumberOfWeakCalls());
4688}
4689
4690
4691// TODO(mstarzinger): This should be a THREADED_TEST but causes failures
4692// on the buildbots, so was made non-threaded for the time being.
4693TEST(ApiObjectGroupsCycleForScavenger) {
4694 i::FLAG_stress_compaction = false;
4695 i::FLAG_gc_global = false;
4696 LocalContext env;
4697 v8::Isolate* iso = env->GetIsolate();
4698 HandleScope scope(iso);
4699
4700 WeakCallCounter counter(1234);
4701
4702 WeakCallCounterAndPersistent<Value> g1s1(&counter);
4703 WeakCallCounterAndPersistent<Value> g1s2(&counter);
4704 WeakCallCounterAndPersistent<Value> g2s1(&counter);
4705 WeakCallCounterAndPersistent<Value> g2s2(&counter);
4706 WeakCallCounterAndPersistent<Value> g3s1(&counter);
4707 WeakCallCounterAndPersistent<Value> g3s2(&counter);
4708
4709 {
4710 HandleScope scope(iso);
4711 g1s1.handle.Reset(iso, Object::New(iso));
4712 g1s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004713 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
4714 v8::WeakCallbackType::kParameter);
4715 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
4716 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004717
4718 g2s1.handle.Reset(iso, Object::New(iso));
4719 g2s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004720 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
4721 v8::WeakCallbackType::kParameter);
4722 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
4723 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004724
4725 g3s1.handle.Reset(iso, Object::New(iso));
4726 g3s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004727 g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback,
4728 v8::WeakCallbackType::kParameter);
4729 g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback,
4730 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004731 }
4732
4733 // Make a root.
4734 WeakCallCounterAndPersistent<Value> root(&counter);
4735 root.handle.Reset(iso, g1s1.handle);
4736 root.handle.MarkPartiallyDependent();
4737
4738 // Connect groups. We're building the following cycle:
4739 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
4740 // groups.
4741 {
4742 HandleScope handle_scope(iso);
4743 g1s1.handle.MarkPartiallyDependent();
4744 g1s2.handle.MarkPartiallyDependent();
4745 g2s1.handle.MarkPartiallyDependent();
4746 g2s2.handle.MarkPartiallyDependent();
4747 g3s1.handle.MarkPartiallyDependent();
4748 g3s2.handle.MarkPartiallyDependent();
4749 iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
4750 iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004751 Local<Object>::New(iso, g1s1.handle.As<Object>())
4752 ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g2s1.handle))
4753 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004754 iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
4755 iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004756 Local<Object>::New(iso, g2s1.handle.As<Object>())
4757 ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g3s1.handle))
4758 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004759 iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
4760 iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004761 Local<Object>::New(iso, g3s1.handle.As<Object>())
4762 ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g1s1.handle))
4763 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004764 }
4765
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004766 v8::internal::Heap* heap =
4767 reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
4768 heap->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004769
4770 // All objects should be alive.
4771 CHECK_EQ(0, counter.NumberOfWeakCalls());
4772
4773 // Weaken the root.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004774 root.handle.SetWeak(&root, &WeakPointerCallback,
4775 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004776 root.handle.MarkPartiallyDependent();
4777
4778 // Groups are deleted, rebuild groups.
4779 {
4780 HandleScope handle_scope(iso);
4781 g1s1.handle.MarkPartiallyDependent();
4782 g1s2.handle.MarkPartiallyDependent();
4783 g2s1.handle.MarkPartiallyDependent();
4784 g2s2.handle.MarkPartiallyDependent();
4785 g3s1.handle.MarkPartiallyDependent();
4786 g3s2.handle.MarkPartiallyDependent();
4787 iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
4788 iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004789 Local<Object>::New(iso, g1s1.handle.As<Object>())
4790 ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g2s1.handle))
4791 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004792 iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
4793 iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004794 Local<Object>::New(iso, g2s1.handle.As<Object>())
4795 ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g3s1.handle))
4796 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004797 iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
4798 iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004799 Local<Object>::New(iso, g3s1.handle.As<Object>())
4800 ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g1s1.handle))
4801 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004802 }
4803
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004804 heap->CollectAllGarbage();
Steve Block44f0eee2011-05-26 01:26:41 +01004805
4806 // All objects should be gone. 7 global handles in total.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004807 CHECK_EQ(7, counter.NumberOfWeakCalls());
Steve Block44f0eee2011-05-26 01:26:41 +01004808}
4809
4810
Steve Blocka7e24c12009-10-30 11:49:00 +00004811THREADED_TEST(ScriptException) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004812 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004813 v8::HandleScope scope(env->GetIsolate());
4814 Local<Script> script = v8_compile("throw 'panama!';");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004815 v8::TryCatch try_catch(env->GetIsolate());
4816 v8::MaybeLocal<Value> result = script->Run(env.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00004817 CHECK(result.IsEmpty());
4818 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004819 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004820 CHECK_EQ(0, strcmp(*exception_value, "panama!"));
Steve Blocka7e24c12009-10-30 11:49:00 +00004821}
4822
4823
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004824TEST(TryCatchCustomException) {
4825 LocalContext env;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004826 v8::Isolate* isolate = env->GetIsolate();
4827 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004828 v8::TryCatch try_catch(isolate);
4829 CompileRun(
4830 "function CustomError() { this.a = 'b'; }"
4831 "(function f() { throw new CustomError(); })();");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004832 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004833 CHECK(try_catch.Exception()
4834 ->ToObject(env.local())
4835 .ToLocalChecked()
4836 ->Get(env.local(), v8_str("a"))
4837 .ToLocalChecked()
4838 ->Equals(env.local(), v8_str("b"))
4839 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004840}
4841
4842
Steve Blocka7e24c12009-10-30 11:49:00 +00004843bool message_received;
4844
4845
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004846static void check_message_0(v8::Local<v8::Message> message,
4847 v8::Local<Value> data) {
4848 CHECK_EQ(5.76, data->NumberValue(CcTest::isolate()->GetCurrentContext())
4849 .FromJust());
4850 CHECK_EQ(6.75, message->GetScriptOrigin()
4851 .ResourceName()
4852 ->NumberValue(CcTest::isolate()->GetCurrentContext())
4853 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004854 CHECK(!message->IsSharedCrossOrigin());
Steve Blocka7e24c12009-10-30 11:49:00 +00004855 message_received = true;
4856}
4857
4858
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004859THREADED_TEST(MessageHandler0) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004860 message_received = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004861 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00004862 CHECK(!message_received);
Steve Blocka7e24c12009-10-30 11:49:00 +00004863 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004864 CcTest::isolate()->AddMessageListener(check_message_0, v8_num(5.76));
4865 v8::Local<v8::Script> script = CompileWithOrigin("throw 'error'", "6.75");
4866 CHECK(script->Run(context.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00004867 CHECK(message_received);
4868 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004869 CcTest::isolate()->RemoveMessageListeners(check_message_0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004870}
4871
4872
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004873static void check_message_1(v8::Local<v8::Message> message,
4874 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004875 CHECK(data->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004876 CHECK_EQ(1337,
4877 data->Int32Value(CcTest::isolate()->GetCurrentContext()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004878 CHECK(!message->IsSharedCrossOrigin());
4879 message_received = true;
4880}
4881
4882
4883TEST(MessageHandler1) {
4884 message_received = false;
4885 v8::HandleScope scope(CcTest::isolate());
4886 CHECK(!message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004887 CcTest::isolate()->AddMessageListener(check_message_1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004888 LocalContext context;
4889 CompileRun("throw 1337;");
4890 CHECK(message_received);
4891 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004892 CcTest::isolate()->RemoveMessageListeners(check_message_1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004893}
4894
4895
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004896static void check_message_2(v8::Local<v8::Message> message,
4897 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004898 LocalContext context;
4899 CHECK(data->IsObject());
4900 v8::Local<v8::Value> hidden_property =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004901 v8::Object::Cast(*data)
4902 ->GetPrivate(
4903 context.local(),
4904 v8::Private::ForApi(CcTest::isolate(), v8_str("hidden key")))
4905 .ToLocalChecked();
4906 CHECK(v8_str("hidden value")
4907 ->Equals(context.local(), hidden_property)
4908 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004909 CHECK(!message->IsSharedCrossOrigin());
4910 message_received = true;
4911}
4912
4913
4914TEST(MessageHandler2) {
4915 message_received = false;
4916 v8::HandleScope scope(CcTest::isolate());
4917 CHECK(!message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004918 CcTest::isolate()->AddMessageListener(check_message_2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004919 LocalContext context;
4920 v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004921 v8::Object::Cast(*error)
4922 ->SetPrivate(context.local(),
4923 v8::Private::ForApi(CcTest::isolate(), v8_str("hidden key")),
4924 v8_str("hidden value"))
4925 .FromJust();
4926 CHECK(context->Global()
4927 ->Set(context.local(), v8_str("error"), error)
4928 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004929 CompileRun("throw error;");
4930 CHECK(message_received);
4931 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004932 CcTest::isolate()->RemoveMessageListeners(check_message_2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004933}
4934
4935
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004936static void check_message_3(v8::Local<v8::Message> message,
4937 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004938 CHECK(message->IsSharedCrossOrigin());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004939 CHECK(message->GetScriptOrigin().Options().IsSharedCrossOrigin());
4940 CHECK(message->GetScriptOrigin().Options().IsEmbedderDebugScript());
4941 CHECK(message->GetScriptOrigin().Options().IsOpaque());
4942 CHECK_EQ(6.75, message->GetScriptOrigin()
4943 .ResourceName()
4944 ->NumberValue(CcTest::isolate()->GetCurrentContext())
4945 .FromJust());
4946 CHECK_EQ(7.40, message->GetScriptOrigin()
4947 .SourceMapUrl()
4948 ->NumberValue(CcTest::isolate()->GetCurrentContext())
4949 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004950 message_received = true;
4951}
4952
4953
4954TEST(MessageHandler3) {
4955 message_received = false;
4956 v8::Isolate* isolate = CcTest::isolate();
4957 v8::HandleScope scope(isolate);
4958 CHECK(!message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004959 isolate->AddMessageListener(check_message_3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004960 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004961 v8::ScriptOrigin origin = v8::ScriptOrigin(
4962 v8_str("6.75"), v8::Integer::New(isolate, 1),
4963 v8::Integer::New(isolate, 2), v8::True(isolate), Local<v8::Integer>(),
4964 v8::True(isolate), v8_str("7.40"), v8::True(isolate));
4965 v8::Local<v8::Script> script =
4966 Script::Compile(context.local(), v8_str("throw 'error'"), &origin)
4967 .ToLocalChecked();
4968 CHECK(script->Run(context.local()).IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004969 CHECK(message_received);
4970 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004971 isolate->RemoveMessageListeners(check_message_3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004972}
4973
4974
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004975static void check_message_4(v8::Local<v8::Message> message,
4976 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004977 CHECK(!message->IsSharedCrossOrigin());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004978 CHECK_EQ(6.75, message->GetScriptOrigin()
4979 .ResourceName()
4980 ->NumberValue(CcTest::isolate()->GetCurrentContext())
4981 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004982 message_received = true;
4983}
4984
4985
4986TEST(MessageHandler4) {
4987 message_received = false;
4988 v8::Isolate* isolate = CcTest::isolate();
4989 v8::HandleScope scope(isolate);
4990 CHECK(!message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004991 isolate->AddMessageListener(check_message_4);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004992 LocalContext context;
4993 v8::ScriptOrigin origin =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004994 v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
4995 v8::Integer::New(isolate, 2), v8::False(isolate));
4996 v8::Local<v8::Script> script =
4997 Script::Compile(context.local(), v8_str("throw 'error'"), &origin)
4998 .ToLocalChecked();
4999 CHECK(script->Run(context.local()).IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005000 CHECK(message_received);
5001 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005002 isolate->RemoveMessageListeners(check_message_4);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005003}
5004
5005
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005006static void check_message_5a(v8::Local<v8::Message> message,
5007 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005008 CHECK(message->IsSharedCrossOrigin());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005009 CHECK_EQ(6.75, message->GetScriptOrigin()
5010 .ResourceName()
5011 ->NumberValue(CcTest::isolate()->GetCurrentContext())
5012 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005013 message_received = true;
5014}
5015
5016
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005017static void check_message_5b(v8::Local<v8::Message> message,
5018 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005019 CHECK(!message->IsSharedCrossOrigin());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005020 CHECK_EQ(6.75, message->GetScriptOrigin()
5021 .ResourceName()
5022 ->NumberValue(CcTest::isolate()->GetCurrentContext())
5023 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005024 message_received = true;
5025}
5026
5027
5028TEST(MessageHandler5) {
5029 message_received = false;
5030 v8::Isolate* isolate = CcTest::isolate();
5031 v8::HandleScope scope(isolate);
5032 CHECK(!message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005033 isolate->AddMessageListener(check_message_5a);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005034 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005035 v8::ScriptOrigin origin1 =
5036 v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
5037 v8::Integer::New(isolate, 2), v8::True(isolate));
5038 v8::Local<v8::Script> script =
5039 Script::Compile(context.local(), v8_str("throw 'error'"), &origin1)
5040 .ToLocalChecked();
5041 CHECK(script->Run(context.local()).IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005042 CHECK(message_received);
5043 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005044 isolate->RemoveMessageListeners(check_message_5a);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005045
5046 message_received = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005047 isolate->AddMessageListener(check_message_5b);
5048 v8::ScriptOrigin origin2 =
5049 v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
5050 v8::Integer::New(isolate, 2), v8::False(isolate));
5051 script = Script::Compile(context.local(), v8_str("throw 'error'"), &origin2)
5052 .ToLocalChecked();
5053 CHECK(script->Run(context.local()).IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005054 CHECK(message_received);
5055 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005056 isolate->RemoveMessageListeners(check_message_5b);
5057}
5058
5059
5060TEST(NativeWeakMap) {
5061 v8::Isolate* isolate = CcTest::isolate();
5062 HandleScope scope(isolate);
5063 Local<v8::NativeWeakMap> weak_map(v8::NativeWeakMap::New(isolate));
5064 CHECK(!weak_map.IsEmpty());
5065
5066 LocalContext env;
5067 Local<Object> value = v8::Object::New(isolate);
5068
5069 Local<Object> local1 = v8::Object::New(isolate);
5070 CHECK(!weak_map->Has(local1));
5071 CHECK(weak_map->Get(local1)->IsUndefined());
5072 weak_map->Set(local1, value);
5073 CHECK(weak_map->Has(local1));
5074 CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
5075
5076 WeakCallCounter counter(1234);
5077 WeakCallCounterAndPersistent<Value> o1(&counter);
5078 WeakCallCounterAndPersistent<Value> o2(&counter);
5079 WeakCallCounterAndPersistent<Value> s1(&counter);
5080 {
5081 HandleScope scope(isolate);
5082 Local<v8::Object> obj1 = v8::Object::New(isolate);
5083 Local<v8::Object> obj2 = v8::Object::New(isolate);
5084 Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
5085
5086 weak_map->Set(obj1, value);
5087 weak_map->Set(obj2, value);
5088 weak_map->Set(sym1, value);
5089
5090 o1.handle.Reset(isolate, obj1);
5091 o2.handle.Reset(isolate, obj2);
5092 s1.handle.Reset(isolate, sym1);
5093
5094 CHECK(weak_map->Has(local1));
5095 CHECK(weak_map->Has(obj1));
5096 CHECK(weak_map->Has(obj2));
5097 CHECK(weak_map->Has(sym1));
5098
5099 CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
5100 CHECK(value->Equals(env.local(), weak_map->Get(obj1)).FromJust());
5101 CHECK(value->Equals(env.local(), weak_map->Get(obj2)).FromJust());
5102 CHECK(value->Equals(env.local(), weak_map->Get(sym1)).FromJust());
5103 }
5104 CcTest::heap()->CollectAllGarbage();
5105 {
5106 HandleScope scope(isolate);
5107 CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
5108 CHECK(value->Equals(env.local(),
5109 weak_map->Get(Local<Value>::New(isolate, o1.handle)))
5110 .FromJust());
5111 CHECK(value->Equals(env.local(),
5112 weak_map->Get(Local<Value>::New(isolate, o2.handle)))
5113 .FromJust());
5114 CHECK(value->Equals(env.local(),
5115 weak_map->Get(Local<Value>::New(isolate, s1.handle)))
5116 .FromJust());
5117 }
5118
5119 o1.handle.SetWeak(&o1, &WeakPointerCallback,
5120 v8::WeakCallbackType::kParameter);
5121 o2.handle.SetWeak(&o2, &WeakPointerCallback,
5122 v8::WeakCallbackType::kParameter);
5123 s1.handle.SetWeak(&s1, &WeakPointerCallback,
5124 v8::WeakCallbackType::kParameter);
5125
5126 CcTest::heap()->CollectAllGarbage();
5127 CHECK_EQ(3, counter.NumberOfWeakCalls());
5128
5129 CHECK(o1.handle.IsEmpty());
5130 CHECK(o2.handle.IsEmpty());
5131 CHECK(s1.handle.IsEmpty());
5132
5133 CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
5134 CHECK(weak_map->Delete(local1));
5135 CHECK(!weak_map->Has(local1));
5136 CHECK(weak_map->Get(local1)->IsUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +00005137}
5138
5139
5140THREADED_TEST(GetSetProperty) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005141 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005142 v8::Isolate* isolate = context->GetIsolate();
5143 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005144 CHECK(context->Global()
5145 ->Set(context.local(), v8_str("foo"), v8_num(14))
5146 .FromJust());
5147 CHECK(context->Global()
5148 ->Set(context.local(), v8_str("12"), v8_num(92))
5149 .FromJust());
5150 CHECK(context->Global()
5151 ->Set(context.local(), v8::Integer::New(isolate, 16), v8_num(32))
5152 .FromJust());
5153 CHECK(context->Global()
5154 ->Set(context.local(), v8_num(13), v8_num(56))
5155 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005156 Local<Value> foo = CompileRun("this.foo");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005157 CHECK_EQ(14, foo->Int32Value(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005158 Local<Value> twelve = CompileRun("this[12]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005159 CHECK_EQ(92, twelve->Int32Value(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005160 Local<Value> sixteen = CompileRun("this[16]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005161 CHECK_EQ(32, sixteen->Int32Value(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005162 Local<Value> thirteen = CompileRun("this[13]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005163 CHECK_EQ(56, thirteen->Int32Value(context.local()).FromJust());
5164 CHECK_EQ(92, context->Global()
5165 ->Get(context.local(), v8::Integer::New(isolate, 12))
5166 .ToLocalChecked()
5167 ->Int32Value(context.local())
5168 .FromJust());
5169 CHECK_EQ(92, context->Global()
5170 ->Get(context.local(), v8_str("12"))
5171 .ToLocalChecked()
5172 ->Int32Value(context.local())
5173 .FromJust());
5174 CHECK_EQ(92, context->Global()
5175 ->Get(context.local(), v8_num(12))
5176 .ToLocalChecked()
5177 ->Int32Value(context.local())
5178 .FromJust());
5179 CHECK_EQ(32, context->Global()
5180 ->Get(context.local(), v8::Integer::New(isolate, 16))
5181 .ToLocalChecked()
5182 ->Int32Value(context.local())
5183 .FromJust());
5184 CHECK_EQ(32, context->Global()
5185 ->Get(context.local(), v8_str("16"))
5186 .ToLocalChecked()
5187 ->Int32Value(context.local())
5188 .FromJust());
5189 CHECK_EQ(32, context->Global()
5190 ->Get(context.local(), v8_num(16))
5191 .ToLocalChecked()
5192 ->Int32Value(context.local())
5193 .FromJust());
5194 CHECK_EQ(56, context->Global()
5195 ->Get(context.local(), v8::Integer::New(isolate, 13))
5196 .ToLocalChecked()
5197 ->Int32Value(context.local())
5198 .FromJust());
5199 CHECK_EQ(56, context->Global()
5200 ->Get(context.local(), v8_str("13"))
5201 .ToLocalChecked()
5202 ->Int32Value(context.local())
5203 .FromJust());
5204 CHECK_EQ(56, context->Global()
5205 ->Get(context.local(), v8_num(13))
5206 .ToLocalChecked()
5207 ->Int32Value(context.local())
5208 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005209}
5210
5211
5212THREADED_TEST(PropertyAttributes) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005213 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005214 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005215 // none
5216 Local<String> prop = v8_str("none");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005217 CHECK(context->Global()->Set(context.local(), prop, v8_num(7)).FromJust());
5218 CHECK_EQ(v8::None, context->Global()
5219 ->GetPropertyAttributes(context.local(), prop)
5220 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005221 // read-only
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005222 prop = v8_str("read_only");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005223 context->Global()
5224 ->DefineOwnProperty(context.local(), prop, v8_num(7), v8::ReadOnly)
5225 .FromJust();
5226 CHECK_EQ(7, context->Global()
5227 ->Get(context.local(), prop)
5228 .ToLocalChecked()
5229 ->Int32Value(context.local())
5230 .FromJust());
5231 CHECK_EQ(v8::ReadOnly, context->Global()
5232 ->GetPropertyAttributes(context.local(), prop)
5233 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005234 CompileRun("read_only = 9");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005235 CHECK_EQ(7, context->Global()
5236 ->Get(context.local(), prop)
5237 .ToLocalChecked()
5238 ->Int32Value(context.local())
5239 .FromJust());
5240 CHECK(context->Global()->Set(context.local(), prop, v8_num(10)).FromJust());
5241 CHECK_EQ(7, context->Global()
5242 ->Get(context.local(), prop)
5243 .ToLocalChecked()
5244 ->Int32Value(context.local())
5245 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005246 // dont-delete
5247 prop = v8_str("dont_delete");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005248 context->Global()
5249 ->DefineOwnProperty(context.local(), prop, v8_num(13), v8::DontDelete)
5250 .FromJust();
5251 CHECK_EQ(13, context->Global()
5252 ->Get(context.local(), prop)
5253 .ToLocalChecked()
5254 ->Int32Value(context.local())
5255 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005256 CompileRun("delete dont_delete");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005257 CHECK_EQ(13, context->Global()
5258 ->Get(context.local(), prop)
5259 .ToLocalChecked()
5260 ->Int32Value(context.local())
5261 .FromJust());
5262 CHECK_EQ(v8::DontDelete, context->Global()
5263 ->GetPropertyAttributes(context.local(), prop)
5264 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005265 // dont-enum
5266 prop = v8_str("dont_enum");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005267 context->Global()
5268 ->DefineOwnProperty(context.local(), prop, v8_num(28), v8::DontEnum)
5269 .FromJust();
5270 CHECK_EQ(v8::DontEnum, context->Global()
5271 ->GetPropertyAttributes(context.local(), prop)
5272 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005273 // absent
5274 prop = v8_str("absent");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005275 CHECK_EQ(v8::None, context->Global()
5276 ->GetPropertyAttributes(context.local(), prop)
5277 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005278 Local<Value> fake_prop = v8_num(1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005279 CHECK_EQ(v8::None, context->Global()
5280 ->GetPropertyAttributes(context.local(), fake_prop)
5281 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005282 // exception
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005283 TryCatch try_catch(context->GetIsolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005284 Local<Value> exception =
5285 CompileRun("({ toString: function() { throw 'exception';} })");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005286 CHECK(context->Global()
5287 ->GetPropertyAttributes(context.local(), exception)
5288 .IsNothing());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005289 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005290 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005291 CHECK_EQ(0, strcmp("exception", *exception_value));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005292 try_catch.Reset();
Steve Blocka7e24c12009-10-30 11:49:00 +00005293}
5294
5295
5296THREADED_TEST(Array) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005297 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005298 v8::HandleScope scope(context->GetIsolate());
5299 Local<v8::Array> array = v8::Array::New(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005300 CHECK_EQ(0u, array->Length());
5301 CHECK(array->Get(context.local(), 0).ToLocalChecked()->IsUndefined());
5302 CHECK(!array->Has(context.local(), 0).FromJust());
5303 CHECK(array->Get(context.local(), 100).ToLocalChecked()->IsUndefined());
5304 CHECK(!array->Has(context.local(), 100).FromJust());
5305 CHECK(array->Set(context.local(), 2, v8_num(7)).FromJust());
5306 CHECK_EQ(3u, array->Length());
5307 CHECK(!array->Has(context.local(), 0).FromJust());
5308 CHECK(!array->Has(context.local(), 1).FromJust());
5309 CHECK(array->Has(context.local(), 2).FromJust());
5310 CHECK_EQ(7, array->Get(context.local(), 2)
5311 .ToLocalChecked()
5312 ->Int32Value(context.local())
5313 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005314 Local<Value> obj = CompileRun("[1, 2, 3]");
Steve Block6ded16b2010-05-10 14:33:55 +01005315 Local<v8::Array> arr = obj.As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005316 CHECK_EQ(3u, arr->Length());
5317 CHECK_EQ(1, arr->Get(context.local(), 0)
5318 .ToLocalChecked()
5319 ->Int32Value(context.local())
5320 .FromJust());
5321 CHECK_EQ(2, arr->Get(context.local(), 1)
5322 .ToLocalChecked()
5323 ->Int32Value(context.local())
5324 .FromJust());
5325 CHECK_EQ(3, arr->Get(context.local(), 2)
5326 .ToLocalChecked()
5327 ->Int32Value(context.local())
5328 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005329 array = v8::Array::New(context->GetIsolate(), 27);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005330 CHECK_EQ(27u, array->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005331 array = v8::Array::New(context->GetIsolate(), -27);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005332 CHECK_EQ(0u, array->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +00005333}
5334
5335
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005336void HandleF(const v8::FunctionCallbackInfo<v8::Value>& args) {
5337 v8::EscapableHandleScope scope(args.GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00005338 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005339 Local<v8::Array> result = v8::Array::New(args.GetIsolate(), args.Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005340 for (int i = 0; i < args.Length(); i++) {
5341 CHECK(result->Set(CcTest::isolate()->GetCurrentContext(), i, args[i])
5342 .FromJust());
5343 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005344 args.GetReturnValue().Set(scope.Escape(result));
Steve Blocka7e24c12009-10-30 11:49:00 +00005345}
5346
5347
5348THREADED_TEST(Vector) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005349 v8::Isolate* isolate = CcTest::isolate();
5350 v8::HandleScope scope(isolate);
5351 Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
5352 global->Set(v8_str("f"), v8::FunctionTemplate::New(isolate, HandleF));
Steve Blocka7e24c12009-10-30 11:49:00 +00005353 LocalContext context(0, global);
5354
5355 const char* fun = "f()";
Steve Block6ded16b2010-05-10 14:33:55 +01005356 Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005357 CHECK_EQ(0u, a0->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +00005358
5359 const char* fun2 = "f(11)";
Steve Block6ded16b2010-05-10 14:33:55 +01005360 Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005361 CHECK_EQ(1u, a1->Length());
5362 CHECK_EQ(11, a1->Get(context.local(), 0)
5363 .ToLocalChecked()
5364 ->Int32Value(context.local())
5365 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005366
5367 const char* fun3 = "f(12, 13)";
Steve Block6ded16b2010-05-10 14:33:55 +01005368 Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005369 CHECK_EQ(2u, a2->Length());
5370 CHECK_EQ(12, a2->Get(context.local(), 0)
5371 .ToLocalChecked()
5372 ->Int32Value(context.local())
5373 .FromJust());
5374 CHECK_EQ(13, a2->Get(context.local(), 1)
5375 .ToLocalChecked()
5376 ->Int32Value(context.local())
5377 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005378
5379 const char* fun4 = "f(14, 15, 16)";
Steve Block6ded16b2010-05-10 14:33:55 +01005380 Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005381 CHECK_EQ(3u, a3->Length());
5382 CHECK_EQ(14, a3->Get(context.local(), 0)
5383 .ToLocalChecked()
5384 ->Int32Value(context.local())
5385 .FromJust());
5386 CHECK_EQ(15, a3->Get(context.local(), 1)
5387 .ToLocalChecked()
5388 ->Int32Value(context.local())
5389 .FromJust());
5390 CHECK_EQ(16, a3->Get(context.local(), 2)
5391 .ToLocalChecked()
5392 ->Int32Value(context.local())
5393 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005394
5395 const char* fun5 = "f(17, 18, 19, 20)";
Steve Block6ded16b2010-05-10 14:33:55 +01005396 Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005397 CHECK_EQ(4u, a4->Length());
5398 CHECK_EQ(17, a4->Get(context.local(), 0)
5399 .ToLocalChecked()
5400 ->Int32Value(context.local())
5401 .FromJust());
5402 CHECK_EQ(18, a4->Get(context.local(), 1)
5403 .ToLocalChecked()
5404 ->Int32Value(context.local())
5405 .FromJust());
5406 CHECK_EQ(19, a4->Get(context.local(), 2)
5407 .ToLocalChecked()
5408 ->Int32Value(context.local())
5409 .FromJust());
5410 CHECK_EQ(20, a4->Get(context.local(), 3)
5411 .ToLocalChecked()
5412 ->Int32Value(context.local())
5413 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005414}
5415
5416
5417THREADED_TEST(FunctionCall) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005418 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005419 v8::Isolate* isolate = context->GetIsolate();
5420 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005421 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005422 "function Foo() {"
5423 " var result = [];"
5424 " for (var i = 0; i < arguments.length; i++) {"
5425 " result.push(arguments[i]);"
5426 " }"
5427 " return result;"
5428 "}"
5429 "function ReturnThisSloppy() {"
5430 " return this;"
5431 "}"
5432 "function ReturnThisStrict() {"
5433 " 'use strict';"
5434 " return this;"
5435 "}");
5436 Local<Function> Foo = Local<Function>::Cast(
5437 context->Global()->Get(context.local(), v8_str("Foo")).ToLocalChecked());
5438 Local<Function> ReturnThisSloppy = Local<Function>::Cast(
5439 context->Global()
5440 ->Get(context.local(), v8_str("ReturnThisSloppy"))
5441 .ToLocalChecked());
5442 Local<Function> ReturnThisStrict = Local<Function>::Cast(
5443 context->Global()
5444 ->Get(context.local(), v8_str("ReturnThisStrict"))
5445 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00005446
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005447 v8::Local<Value>* args0 = NULL;
5448 Local<v8::Array> a0 = Local<v8::Array>::Cast(
5449 Foo->Call(context.local(), Foo, 0, args0).ToLocalChecked());
5450 CHECK_EQ(0u, a0->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +00005451
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005452 v8::Local<Value> args1[] = {v8_num(1.1)};
5453 Local<v8::Array> a1 = Local<v8::Array>::Cast(
5454 Foo->Call(context.local(), Foo, 1, args1).ToLocalChecked());
5455 CHECK_EQ(1u, a1->Length());
5456 CHECK_EQ(1.1, a1->Get(context.local(), v8::Integer::New(isolate, 0))
5457 .ToLocalChecked()
5458 ->NumberValue(context.local())
5459 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005460
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005461 v8::Local<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
5462 Local<v8::Array> a2 = Local<v8::Array>::Cast(
5463 Foo->Call(context.local(), Foo, 2, args2).ToLocalChecked());
5464 CHECK_EQ(2u, a2->Length());
5465 CHECK_EQ(2.2, a2->Get(context.local(), v8::Integer::New(isolate, 0))
5466 .ToLocalChecked()
5467 ->NumberValue(context.local())
5468 .FromJust());
5469 CHECK_EQ(3.3, a2->Get(context.local(), v8::Integer::New(isolate, 1))
5470 .ToLocalChecked()
5471 ->NumberValue(context.local())
5472 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005473
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005474 v8::Local<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
5475 Local<v8::Array> a3 = Local<v8::Array>::Cast(
5476 Foo->Call(context.local(), Foo, 3, args3).ToLocalChecked());
5477 CHECK_EQ(3u, a3->Length());
5478 CHECK_EQ(4.4, a3->Get(context.local(), v8::Integer::New(isolate, 0))
5479 .ToLocalChecked()
5480 ->NumberValue(context.local())
5481 .FromJust());
5482 CHECK_EQ(5.5, a3->Get(context.local(), v8::Integer::New(isolate, 1))
5483 .ToLocalChecked()
5484 ->NumberValue(context.local())
5485 .FromJust());
5486 CHECK_EQ(6.6, a3->Get(context.local(), v8::Integer::New(isolate, 2))
5487 .ToLocalChecked()
5488 ->NumberValue(context.local())
5489 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005490
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005491 v8::Local<Value> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
5492 v8_num(10.11)};
5493 Local<v8::Array> a4 = Local<v8::Array>::Cast(
5494 Foo->Call(context.local(), Foo, 4, args4).ToLocalChecked());
5495 CHECK_EQ(4u, a4->Length());
5496 CHECK_EQ(7.7, a4->Get(context.local(), v8::Integer::New(isolate, 0))
5497 .ToLocalChecked()
5498 ->NumberValue(context.local())
5499 .FromJust());
5500 CHECK_EQ(8.8, a4->Get(context.local(), v8::Integer::New(isolate, 1))
5501 .ToLocalChecked()
5502 ->NumberValue(context.local())
5503 .FromJust());
5504 CHECK_EQ(9.9, a4->Get(context.local(), v8::Integer::New(isolate, 2))
5505 .ToLocalChecked()
5506 ->NumberValue(context.local())
5507 .FromJust());
5508 CHECK_EQ(10.11, a4->Get(context.local(), v8::Integer::New(isolate, 3))
5509 .ToLocalChecked()
5510 ->NumberValue(context.local())
5511 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005512
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005513 Local<v8::Value> r1 =
5514 ReturnThisSloppy->Call(context.local(), v8::Undefined(isolate), 0, NULL)
5515 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005516 CHECK(r1->StrictEquals(context->Global()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005517 Local<v8::Value> r2 =
5518 ReturnThisSloppy->Call(context.local(), v8::Null(isolate), 0, NULL)
5519 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005520 CHECK(r2->StrictEquals(context->Global()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005521 Local<v8::Value> r3 =
5522 ReturnThisSloppy->Call(context.local(), v8_num(42), 0, NULL)
5523 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005524 CHECK(r3->IsNumberObject());
5525 CHECK_EQ(42.0, r3.As<v8::NumberObject>()->ValueOf());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005526 Local<v8::Value> r4 =
5527 ReturnThisSloppy->Call(context.local(), v8_str("hello"), 0, NULL)
5528 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005529 CHECK(r4->IsStringObject());
5530 CHECK(r4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005531 Local<v8::Value> r5 =
5532 ReturnThisSloppy->Call(context.local(), v8::True(isolate), 0, NULL)
5533 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005534 CHECK(r5->IsBooleanObject());
5535 CHECK(r5.As<v8::BooleanObject>()->ValueOf());
Steve Blocka7e24c12009-10-30 11:49:00 +00005536
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005537 Local<v8::Value> r6 =
5538 ReturnThisStrict->Call(context.local(), v8::Undefined(isolate), 0, NULL)
5539 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005540 CHECK(r6->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005541 Local<v8::Value> r7 =
5542 ReturnThisStrict->Call(context.local(), v8::Null(isolate), 0, NULL)
5543 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005544 CHECK(r7->IsNull());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005545 Local<v8::Value> r8 =
5546 ReturnThisStrict->Call(context.local(), v8_num(42), 0, NULL)
5547 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005548 CHECK(r8->StrictEquals(v8_num(42)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005549 Local<v8::Value> r9 =
5550 ReturnThisStrict->Call(context.local(), v8_str("hello"), 0, NULL)
5551 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005552 CHECK(r9->StrictEquals(v8_str("hello")));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005553 Local<v8::Value> r10 =
5554 ReturnThisStrict->Call(context.local(), v8::True(isolate), 0, NULL)
5555 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005556 CHECK(r10->StrictEquals(v8::True(isolate)));
Steve Blocka7e24c12009-10-30 11:49:00 +00005557}
5558
5559
5560THREADED_TEST(ConstructCall) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005561 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005562 v8::Isolate* isolate = context->GetIsolate();
5563 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005564 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005565 "function Foo() {"
5566 " var result = [];"
5567 " for (var i = 0; i < arguments.length; i++) {"
5568 " result.push(arguments[i]);"
5569 " }"
5570 " return result;"
5571 "}");
5572 Local<Function> Foo = Local<Function>::Cast(
5573 context->Global()->Get(context.local(), v8_str("Foo")).ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00005574
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005575 v8::Local<Value>* args0 = NULL;
5576 Local<v8::Array> a0 = Local<v8::Array>::Cast(
5577 Foo->NewInstance(context.local(), 0, args0).ToLocalChecked());
5578 CHECK_EQ(0u, a0->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +00005579
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005580 v8::Local<Value> args1[] = {v8_num(1.1)};
5581 Local<v8::Array> a1 = Local<v8::Array>::Cast(
5582 Foo->NewInstance(context.local(), 1, args1).ToLocalChecked());
5583 CHECK_EQ(1u, a1->Length());
5584 CHECK_EQ(1.1, a1->Get(context.local(), v8::Integer::New(isolate, 0))
5585 .ToLocalChecked()
5586 ->NumberValue(context.local())
5587 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005588
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005589 v8::Local<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
5590 Local<v8::Array> a2 = Local<v8::Array>::Cast(
5591 Foo->NewInstance(context.local(), 2, args2).ToLocalChecked());
5592 CHECK_EQ(2u, a2->Length());
5593 CHECK_EQ(2.2, a2->Get(context.local(), v8::Integer::New(isolate, 0))
5594 .ToLocalChecked()
5595 ->NumberValue(context.local())
5596 .FromJust());
5597 CHECK_EQ(3.3, a2->Get(context.local(), v8::Integer::New(isolate, 1))
5598 .ToLocalChecked()
5599 ->NumberValue(context.local())
5600 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005601
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005602 v8::Local<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
5603 Local<v8::Array> a3 = Local<v8::Array>::Cast(
5604 Foo->NewInstance(context.local(), 3, args3).ToLocalChecked());
5605 CHECK_EQ(3u, a3->Length());
5606 CHECK_EQ(4.4, a3->Get(context.local(), v8::Integer::New(isolate, 0))
5607 .ToLocalChecked()
5608 ->NumberValue(context.local())
5609 .FromJust());
5610 CHECK_EQ(5.5, a3->Get(context.local(), v8::Integer::New(isolate, 1))
5611 .ToLocalChecked()
5612 ->NumberValue(context.local())
5613 .FromJust());
5614 CHECK_EQ(6.6, a3->Get(context.local(), v8::Integer::New(isolate, 2))
5615 .ToLocalChecked()
5616 ->NumberValue(context.local())
5617 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005618
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005619 v8::Local<Value> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
5620 v8_num(10.11)};
5621 Local<v8::Array> a4 = Local<v8::Array>::Cast(
5622 Foo->NewInstance(context.local(), 4, args4).ToLocalChecked());
5623 CHECK_EQ(4u, a4->Length());
5624 CHECK_EQ(7.7, a4->Get(context.local(), v8::Integer::New(isolate, 0))
5625 .ToLocalChecked()
5626 ->NumberValue(context.local())
5627 .FromJust());
5628 CHECK_EQ(8.8, a4->Get(context.local(), v8::Integer::New(isolate, 1))
5629 .ToLocalChecked()
5630 ->NumberValue(context.local())
5631 .FromJust());
5632 CHECK_EQ(9.9, a4->Get(context.local(), v8::Integer::New(isolate, 2))
5633 .ToLocalChecked()
5634 ->NumberValue(context.local())
5635 .FromJust());
5636 CHECK_EQ(10.11, a4->Get(context.local(), v8::Integer::New(isolate, 3))
5637 .ToLocalChecked()
5638 ->NumberValue(context.local())
5639 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005640}
5641
5642
Steve Block6ded16b2010-05-10 14:33:55 +01005643THREADED_TEST(ConversionNumber) {
Steve Block6ded16b2010-05-10 14:33:55 +01005644 LocalContext env;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005645 v8::Isolate* isolate = env->GetIsolate();
5646 v8::HandleScope scope(isolate);
Steve Block6ded16b2010-05-10 14:33:55 +01005647 // Very large number.
5648 CompileRun("var obj = Math.pow(2,32) * 1237;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005649 Local<Value> obj =
5650 env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5651 CHECK_EQ(5312874545152.0,
5652 obj->ToNumber(env.local()).ToLocalChecked()->Value());
5653 CHECK_EQ(0, obj->ToInt32(env.local()).ToLocalChecked()->Value());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005654 CHECK(0u ==
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005655 obj->ToUint32(env.local())
5656 .ToLocalChecked()
5657 ->Value()); // NOLINT - no CHECK_EQ for unsigned.
Steve Block6ded16b2010-05-10 14:33:55 +01005658 // Large number.
5659 CompileRun("var obj = -1234567890123;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005660 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5661 CHECK_EQ(-1234567890123.0,
5662 obj->ToNumber(env.local()).ToLocalChecked()->Value());
5663 CHECK_EQ(-1912276171, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5664 CHECK(2382691125u ==
5665 obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005666 // Small positive integer.
5667 CompileRun("var obj = 42;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005668 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5669 CHECK_EQ(42.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
5670 CHECK_EQ(42, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5671 CHECK(42u == obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005672 // Negative integer.
5673 CompileRun("var obj = -37;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005674 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5675 CHECK_EQ(-37.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
5676 CHECK_EQ(-37, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5677 CHECK(4294967259u ==
5678 obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005679 // Positive non-int32 integer.
5680 CompileRun("var obj = 0x81234567;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005681 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5682 CHECK_EQ(2166572391.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
5683 CHECK_EQ(-2128394905, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5684 CHECK(2166572391u ==
5685 obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005686 // Fraction.
5687 CompileRun("var obj = 42.3;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005688 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5689 CHECK_EQ(42.3, obj->ToNumber(env.local()).ToLocalChecked()->Value());
5690 CHECK_EQ(42, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5691 CHECK(42u == obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005692 // Large negative fraction.
5693 CompileRun("var obj = -5726623061.75;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005694 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5695 CHECK_EQ(-5726623061.75,
5696 obj->ToNumber(env.local()).ToLocalChecked()->Value());
5697 CHECK_EQ(-1431655765, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5698 CHECK(2863311531u ==
5699 obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005700}
5701
5702
5703THREADED_TEST(isNumberType) {
Steve Block6ded16b2010-05-10 14:33:55 +01005704 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005705 v8::HandleScope scope(env->GetIsolate());
Steve Block6ded16b2010-05-10 14:33:55 +01005706 // Very large number.
5707 CompileRun("var obj = Math.pow(2,32) * 1237;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005708 Local<Value> obj =
5709 env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005710 CHECK(!obj->IsInt32());
5711 CHECK(!obj->IsUint32());
5712 // Large negative number.
5713 CompileRun("var obj = -1234567890123;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005714 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005715 CHECK(!obj->IsInt32());
5716 CHECK(!obj->IsUint32());
5717 // Small positive integer.
5718 CompileRun("var obj = 42;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005719 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005720 CHECK(obj->IsInt32());
5721 CHECK(obj->IsUint32());
5722 // Negative integer.
5723 CompileRun("var obj = -37;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005724 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005725 CHECK(obj->IsInt32());
5726 CHECK(!obj->IsUint32());
5727 // Positive non-int32 integer.
5728 CompileRun("var obj = 0x81234567;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005729 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005730 CHECK(!obj->IsInt32());
5731 CHECK(obj->IsUint32());
5732 // Fraction.
5733 CompileRun("var obj = 42.3;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005734 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005735 CHECK(!obj->IsInt32());
5736 CHECK(!obj->IsUint32());
5737 // Large negative fraction.
5738 CompileRun("var obj = -5726623061.75;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005739 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005740 CHECK(!obj->IsInt32());
5741 CHECK(!obj->IsUint32());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005742 // Positive zero
5743 CompileRun("var obj = 0.0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005744 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005745 CHECK(obj->IsInt32());
5746 CHECK(obj->IsUint32());
5747 // Positive zero
5748 CompileRun("var obj = -0.0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005749 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005750 CHECK(!obj->IsInt32());
5751 CHECK(!obj->IsUint32());
Steve Block6ded16b2010-05-10 14:33:55 +01005752}
5753
5754
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005755static void CheckUncle(v8::TryCatch* try_catch) {
5756 CHECK(try_catch->HasCaught());
5757 String::Utf8Value str_value(try_catch->Exception());
5758 CHECK_EQ(0, strcmp(*str_value, "uncle?"));
5759 try_catch->Reset();
5760}
5761
5762
Steve Blocka7e24c12009-10-30 11:49:00 +00005763THREADED_TEST(ConversionException) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005764 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005765 v8::Isolate* isolate = env->GetIsolate();
5766 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005767 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005768 "function TestClass() { };"
5769 "TestClass.prototype.toString = function () { throw 'uncle?'; };"
5770 "var obj = new TestClass();");
5771 Local<Value> obj =
5772 env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00005773
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005774 v8::TryCatch try_catch(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005775
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005776 CHECK(obj->ToString(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005777 CheckUncle(&try_catch);
5778
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005779 CHECK(obj->ToNumber(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005780 CheckUncle(&try_catch);
5781
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005782 CHECK(obj->ToInteger(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005783 CheckUncle(&try_catch);
5784
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005785 CHECK(obj->ToUint32(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005786 CheckUncle(&try_catch);
5787
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005788 CHECK(obj->ToInt32(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005789 CheckUncle(&try_catch);
5790
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005791 CHECK(v8::Undefined(isolate)->ToObject(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005792 CHECK(try_catch.HasCaught());
5793 try_catch.Reset();
5794
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005795 CHECK(obj->Int32Value(env.local()).IsNothing());
Steve Blocka7e24c12009-10-30 11:49:00 +00005796 CheckUncle(&try_catch);
5797
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005798 CHECK(obj->Uint32Value(env.local()).IsNothing());
Steve Blocka7e24c12009-10-30 11:49:00 +00005799 CheckUncle(&try_catch);
5800
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005801 CHECK(obj->NumberValue(env.local()).IsNothing());
Steve Blocka7e24c12009-10-30 11:49:00 +00005802 CheckUncle(&try_catch);
5803
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005804 CHECK(obj->IntegerValue(env.local()).IsNothing());
Steve Blocka7e24c12009-10-30 11:49:00 +00005805 CheckUncle(&try_catch);
5806}
5807
5808
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005809void ThrowFromC(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005810 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005811 args.GetIsolate()->ThrowException(v8_str("konto"));
Steve Blocka7e24c12009-10-30 11:49:00 +00005812}
5813
5814
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005815void CCatcher(const v8::FunctionCallbackInfo<v8::Value>& args) {
5816 if (args.Length() < 1) {
5817 args.GetReturnValue().Set(false);
5818 return;
5819 }
5820 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005821 v8::TryCatch try_catch(args.GetIsolate());
5822 Local<Value> result =
5823 CompileRun(args[0]
5824 ->ToString(args.GetIsolate()->GetCurrentContext())
5825 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00005826 CHECK(!try_catch.HasCaught() || result.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005827 args.GetReturnValue().Set(try_catch.HasCaught());
Steve Blocka7e24c12009-10-30 11:49:00 +00005828}
5829
5830
5831THREADED_TEST(APICatch) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005832 v8::Isolate* isolate = CcTest::isolate();
5833 v8::HandleScope scope(isolate);
5834 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005835 templ->Set(v8_str("ThrowFromC"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005836 v8::FunctionTemplate::New(isolate, ThrowFromC));
Steve Blocka7e24c12009-10-30 11:49:00 +00005837 LocalContext context(0, templ);
5838 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005839 "var thrown = false;"
5840 "try {"
5841 " ThrowFromC();"
5842 "} catch (e) {"
5843 " thrown = true;"
5844 "}");
5845 Local<Value> thrown = context->Global()
5846 ->Get(context.local(), v8_str("thrown"))
5847 .ToLocalChecked();
5848 CHECK(thrown->BooleanValue(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005849}
5850
5851
5852THREADED_TEST(APIThrowTryCatch) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005853 v8::Isolate* isolate = CcTest::isolate();
5854 v8::HandleScope scope(isolate);
5855 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005856 templ->Set(v8_str("ThrowFromC"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005857 v8::FunctionTemplate::New(isolate, ThrowFromC));
Steve Blocka7e24c12009-10-30 11:49:00 +00005858 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005859 v8::TryCatch try_catch(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005860 CompileRun("ThrowFromC();");
5861 CHECK(try_catch.HasCaught());
5862}
5863
5864
5865// Test that a try-finally block doesn't shadow a try-catch block
5866// when setting up an external handler.
5867//
5868// BUG(271): Some of the exception propagation does not work on the
5869// ARM simulator because the simulator separates the C++ stack and the
5870// JS stack. This test therefore fails on the simulator. The test is
5871// not threaded to allow the threading tests to run on the simulator.
5872TEST(TryCatchInTryFinally) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005873 v8::Isolate* isolate = CcTest::isolate();
5874 v8::HandleScope scope(isolate);
5875 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005876 templ->Set(v8_str("CCatcher"), v8::FunctionTemplate::New(isolate, CCatcher));
Steve Blocka7e24c12009-10-30 11:49:00 +00005877 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005878 Local<Value> result = CompileRun(
5879 "try {"
5880 " try {"
5881 " CCatcher('throw 7;');"
5882 " } finally {"
5883 " }"
5884 "} catch (e) {"
5885 "}");
Steve Blocka7e24c12009-10-30 11:49:00 +00005886 CHECK(result->IsTrue());
5887}
5888
5889
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005890static void check_custom_error_tostring(v8::Local<v8::Message> message,
5891 v8::Local<v8::Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005892 const char* uncaught_error = "Uncaught MyError toString";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005893 CHECK(message->Get()
5894 ->Equals(CcTest::isolate()->GetCurrentContext(),
5895 v8_str(uncaught_error))
5896 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005897}
5898
5899
5900TEST(CustomErrorToString) {
5901 LocalContext context;
5902 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005903 context->GetIsolate()->AddMessageListener(check_custom_error_tostring);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005904 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005905 "function MyError(name, message) { "
5906 " this.name = name; "
5907 " this.message = message; "
5908 "} "
5909 "MyError.prototype = Object.create(Error.prototype); "
5910 "MyError.prototype.toString = function() { "
5911 " return 'MyError toString'; "
5912 "}; "
5913 "throw new MyError('my name', 'my message'); ");
5914 context->GetIsolate()->RemoveMessageListeners(check_custom_error_tostring);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005915}
5916
5917
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005918static void check_custom_error_message(v8::Local<v8::Message> message,
5919 v8::Local<v8::Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005920 const char* uncaught_error = "Uncaught MyError: my message";
5921 printf("%s\n", *v8::String::Utf8Value(message->Get()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005922 CHECK(message->Get()
5923 ->Equals(CcTest::isolate()->GetCurrentContext(),
5924 v8_str(uncaught_error))
5925 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005926}
5927
5928
5929TEST(CustomErrorMessage) {
5930 LocalContext context;
5931 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005932 context->GetIsolate()->AddMessageListener(check_custom_error_message);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005933
5934 // Handlebars.
5935 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005936 "function MyError(msg) { "
5937 " this.name = 'MyError'; "
5938 " this.message = msg; "
5939 "} "
5940 "MyError.prototype = new Error(); "
5941 "throw new MyError('my message'); ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005942
5943 // Closure.
5944 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005945 "function MyError(msg) { "
5946 " this.name = 'MyError'; "
5947 " this.message = msg; "
5948 "} "
5949 "inherits = function(childCtor, parentCtor) { "
5950 " function tempCtor() {}; "
5951 " tempCtor.prototype = parentCtor.prototype; "
5952 " childCtor.superClass_ = parentCtor.prototype; "
5953 " childCtor.prototype = new tempCtor(); "
5954 " childCtor.prototype.constructor = childCtor; "
5955 "}; "
5956 "inherits(MyError, Error); "
5957 "throw new MyError('my message'); ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005958
5959 // Object.create.
5960 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005961 "function MyError(msg) { "
5962 " this.name = 'MyError'; "
5963 " this.message = msg; "
5964 "} "
5965 "MyError.prototype = Object.create(Error.prototype); "
5966 "throw new MyError('my message'); ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005967
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005968 context->GetIsolate()->RemoveMessageListeners(check_custom_error_message);
Ben Murdochb8e0da22011-05-16 14:20:40 +01005969}
5970
5971
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005972static void check_custom_rethrowing_message(v8::Local<v8::Message> message,
5973 v8::Local<v8::Value> data) {
5974 const char* uncaught_error = "Uncaught exception";
5975 CHECK(message->Get()
5976 ->Equals(CcTest::isolate()->GetCurrentContext(),
5977 v8_str(uncaught_error))
5978 .FromJust());
5979}
5980
5981
5982TEST(CustomErrorRethrowsOnToString) {
5983 LocalContext context;
5984 v8::HandleScope scope(context->GetIsolate());
5985 context->GetIsolate()->AddMessageListener(check_custom_rethrowing_message);
5986
5987 CompileRun(
5988 "var e = { toString: function() { throw e; } };"
5989 "try { throw e; } finally {}");
5990
5991 context->GetIsolate()->RemoveMessageListeners(
5992 check_custom_rethrowing_message);
5993}
5994
5995
5996static void receive_message(v8::Local<v8::Message> message,
5997 v8::Local<v8::Value> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005998 message->Get();
5999 message_received = true;
6000}
6001
6002
6003TEST(APIThrowMessage) {
6004 message_received = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006005 v8::Isolate* isolate = CcTest::isolate();
6006 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006007 isolate->AddMessageListener(receive_message);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006008 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00006009 templ->Set(v8_str("ThrowFromC"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006010 v8::FunctionTemplate::New(isolate, ThrowFromC));
Steve Blocka7e24c12009-10-30 11:49:00 +00006011 LocalContext context(0, templ);
6012 CompileRun("ThrowFromC();");
6013 CHECK(message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006014 isolate->RemoveMessageListeners(receive_message);
Steve Blocka7e24c12009-10-30 11:49:00 +00006015}
6016
6017
6018TEST(APIThrowMessageAndVerboseTryCatch) {
6019 message_received = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006020 v8::Isolate* isolate = CcTest::isolate();
6021 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006022 isolate->AddMessageListener(receive_message);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006023 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00006024 templ->Set(v8_str("ThrowFromC"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006025 v8::FunctionTemplate::New(isolate, ThrowFromC));
Steve Blocka7e24c12009-10-30 11:49:00 +00006026 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006027 v8::TryCatch try_catch(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00006028 try_catch.SetVerbose(true);
6029 Local<Value> result = CompileRun("ThrowFromC();");
6030 CHECK(try_catch.HasCaught());
6031 CHECK(result.IsEmpty());
6032 CHECK(message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006033 isolate->RemoveMessageListeners(receive_message);
Steve Blocka7e24c12009-10-30 11:49:00 +00006034}
6035
6036
Ben Murdoch8b112d22011-06-08 16:22:53 +01006037TEST(APIStackOverflowAndVerboseTryCatch) {
6038 message_received = false;
Ben Murdoch8b112d22011-06-08 16:22:53 +01006039 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006040 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006041 context->GetIsolate()->AddMessageListener(receive_message);
6042 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +01006043 try_catch.SetVerbose(true);
6044 Local<Value> result = CompileRun("function foo() { foo(); } foo();");
6045 CHECK(try_catch.HasCaught());
6046 CHECK(result.IsEmpty());
6047 CHECK(message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006048 context->GetIsolate()->RemoveMessageListeners(receive_message);
Ben Murdoch8b112d22011-06-08 16:22:53 +01006049}
6050
6051
Steve Blocka7e24c12009-10-30 11:49:00 +00006052THREADED_TEST(ExternalScriptException) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006053 v8::Isolate* isolate = CcTest::isolate();
6054 v8::HandleScope scope(isolate);
6055 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00006056 templ->Set(v8_str("ThrowFromC"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006057 v8::FunctionTemplate::New(isolate, ThrowFromC));
Steve Blocka7e24c12009-10-30 11:49:00 +00006058 LocalContext context(0, templ);
6059
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006060 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006061 Local<Value> result = CompileRun("ThrowFromC(); throw 'panama';");
Steve Blocka7e24c12009-10-30 11:49:00 +00006062 CHECK(result.IsEmpty());
6063 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006064 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006065 CHECK_EQ(0, strcmp("konto", *exception_value));
Steve Blocka7e24c12009-10-30 11:49:00 +00006066}
6067
6068
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006069void CThrowCountDown(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006070 ApiTestFuzzer::Fuzz();
6071 CHECK_EQ(4, args.Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006072 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
6073 int count = args[0]->Int32Value(context).FromJust();
6074 int cInterval = args[2]->Int32Value(context).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00006075 if (count == 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006076 args.GetIsolate()->ThrowException(v8_str("FromC"));
6077 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00006078 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006079 Local<v8::Object> global = context->Global();
6080 Local<Value> fun =
6081 global->Get(context, v8_str("JSThrowCountDown")).ToLocalChecked();
6082 v8::Local<Value> argv[] = {v8_num(count - 1), args[1], args[2], args[3]};
Steve Blocka7e24c12009-10-30 11:49:00 +00006083 if (count % cInterval == 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006084 v8::TryCatch try_catch(args.GetIsolate());
6085 Local<Value> result = fun.As<Function>()
6086 ->Call(context, global, 4, argv)
6087 .FromMaybe(Local<Value>());
6088 int expected = args[3]->Int32Value(context).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00006089 if (try_catch.HasCaught()) {
6090 CHECK_EQ(expected, count);
6091 CHECK(result.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006092 CHECK(!CcTest::i_isolate()->has_scheduled_exception());
Steve Blocka7e24c12009-10-30 11:49:00 +00006093 } else {
6094 CHECK_NE(expected, count);
6095 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006096 args.GetReturnValue().Set(result);
6097 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00006098 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006099 args.GetReturnValue().Set(fun.As<Function>()
6100 ->Call(context, global, 4, argv)
6101 .FromMaybe(v8::Local<v8::Value>()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006102 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00006103 }
6104 }
6105}
6106
6107
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006108void JSCheck(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006109 ApiTestFuzzer::Fuzz();
6110 CHECK_EQ(3, args.Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006111 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
6112 bool equality = args[0]->BooleanValue(context).FromJust();
6113 int count = args[1]->Int32Value(context).FromJust();
6114 int expected = args[2]->Int32Value(context).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00006115 if (equality) {
6116 CHECK_EQ(count, expected);
6117 } else {
6118 CHECK_NE(count, expected);
6119 }
Steve Blocka7e24c12009-10-30 11:49:00 +00006120}
6121
6122
6123THREADED_TEST(EvalInTryFinally) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006124 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006125 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006126 v8::TryCatch try_catch(context->GetIsolate());
6127 CompileRun(
6128 "(function() {"
6129 " try {"
6130 " eval('asldkf (*&^&*^');"
6131 " } finally {"
6132 " return;"
6133 " }"
6134 "})()");
Steve Blocka7e24c12009-10-30 11:49:00 +00006135 CHECK(!try_catch.HasCaught());
6136}
6137
6138
6139// This test works by making a stack of alternating JavaScript and C
6140// activations. These activations set up exception handlers with regular
6141// intervals, one interval for C activations and another for JavaScript
6142// activations. When enough activations have been created an exception is
6143// thrown and we check that the right activation catches the exception and that
6144// no other activations do. The right activation is always the topmost one with
6145// a handler, regardless of whether it is in JavaScript or C.
6146//
6147// The notation used to describe a test case looks like this:
6148//
6149// *JS[4] *C[3] @JS[2] C[1] JS[0]
6150//
6151// Each entry is an activation, either JS or C. The index is the count at that
6152// level. Stars identify activations with exception handlers, the @ identifies
6153// the exception handler that should catch the exception.
6154//
6155// BUG(271): Some of the exception propagation does not work on the
6156// ARM simulator because the simulator separates the C++ stack and the
6157// JS stack. This test therefore fails on the simulator. The test is
6158// not threaded to allow the threading tests to run on the simulator.
6159TEST(ExceptionOrder) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006160 v8::Isolate* isolate = CcTest::isolate();
6161 v8::HandleScope scope(isolate);
6162 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6163 templ->Set(v8_str("check"), v8::FunctionTemplate::New(isolate, JSCheck));
Steve Blocka7e24c12009-10-30 11:49:00 +00006164 templ->Set(v8_str("CThrowCountDown"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006165 v8::FunctionTemplate::New(isolate, CThrowCountDown));
Steve Blocka7e24c12009-10-30 11:49:00 +00006166 LocalContext context(0, templ);
6167 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006168 "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
6169 " if (count == 0) throw 'FromJS';"
6170 " if (count % jsInterval == 0) {"
6171 " try {"
6172 " var value = CThrowCountDown(count - 1,"
6173 " jsInterval,"
6174 " cInterval,"
6175 " expected);"
6176 " check(false, count, expected);"
6177 " return value;"
6178 " } catch (e) {"
6179 " check(true, count, expected);"
6180 " }"
6181 " } else {"
6182 " return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
6183 " }"
6184 "}");
6185 Local<Function> fun = Local<Function>::Cast(
6186 context->Global()
6187 ->Get(context.local(), v8_str("JSThrowCountDown"))
6188 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00006189
6190 const int argc = 4;
6191 // count jsInterval cInterval expected
6192
6193 // *JS[4] *C[3] @JS[2] C[1] JS[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006194 v8::Local<Value> a0[argc] = {v8_num(4), v8_num(2), v8_num(3), v8_num(2)};
6195 fun->Call(context.local(), fun, argc, a0).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006196
6197 // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006198 v8::Local<Value> a1[argc] = {v8_num(5), v8_num(6), v8_num(1), v8_num(2)};
6199 fun->Call(context.local(), fun, argc, a1).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006200
6201 // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006202 v8::Local<Value> a2[argc] = {v8_num(6), v8_num(7), v8_num(5), v8_num(5)};
6203 fun->Call(context.local(), fun, argc, a2).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006204
6205 // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006206 v8::Local<Value> a3[argc] = {v8_num(6), v8_num(6), v8_num(7), v8_num(6)};
6207 fun->Call(context.local(), fun, argc, a3).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006208
6209 // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006210 v8::Local<Value> a4[argc] = {v8_num(6), v8_num(4), v8_num(5), v8_num(4)};
6211 fun->Call(context.local(), fun, argc, a4).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006212
6213 // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006214 v8::Local<Value> a5[argc] = {v8_num(6), v8_num(4), v8_num(3), v8_num(3)};
6215 fun->Call(context.local(), fun, argc, a5).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006216}
6217
6218
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006219void ThrowValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006220 ApiTestFuzzer::Fuzz();
6221 CHECK_EQ(1, args.Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006222 args.GetIsolate()->ThrowException(args[0]);
Steve Blocka7e24c12009-10-30 11:49:00 +00006223}
6224
6225
6226THREADED_TEST(ThrowValues) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006227 v8::Isolate* isolate = CcTest::isolate();
6228 v8::HandleScope scope(isolate);
6229 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6230 templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(isolate, ThrowValue));
Steve Blocka7e24c12009-10-30 11:49:00 +00006231 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006232 v8::Local<v8::Array> result = v8::Local<v8::Array>::Cast(
6233 CompileRun("function Run(obj) {"
6234 " try {"
6235 " Throw(obj);"
6236 " } catch (e) {"
6237 " return e;"
6238 " }"
6239 " return 'no exception';"
6240 "}"
6241 "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
6242 CHECK_EQ(5u, result->Length());
6243 CHECK(result->Get(context.local(), v8::Integer::New(isolate, 0))
6244 .ToLocalChecked()
6245 ->IsString());
6246 CHECK(result->Get(context.local(), v8::Integer::New(isolate, 1))
6247 .ToLocalChecked()
6248 ->IsNumber());
6249 CHECK_EQ(1, result->Get(context.local(), v8::Integer::New(isolate, 1))
6250 .ToLocalChecked()
6251 ->Int32Value(context.local())
6252 .FromJust());
6253 CHECK(result->Get(context.local(), v8::Integer::New(isolate, 2))
6254 .ToLocalChecked()
6255 ->IsNumber());
6256 CHECK_EQ(0, result->Get(context.local(), v8::Integer::New(isolate, 2))
6257 .ToLocalChecked()
6258 ->Int32Value(context.local())
6259 .FromJust());
6260 CHECK(result->Get(context.local(), v8::Integer::New(isolate, 3))
6261 .ToLocalChecked()
6262 ->IsNull());
6263 CHECK(result->Get(context.local(), v8::Integer::New(isolate, 4))
6264 .ToLocalChecked()
6265 ->IsUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +00006266}
6267
6268
6269THREADED_TEST(CatchZero) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006270 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006271 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006272 v8::TryCatch try_catch(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006273 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006274 CompileRun("throw 10");
Steve Blocka7e24c12009-10-30 11:49:00 +00006275 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006276 CHECK_EQ(10, try_catch.Exception()->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006277 try_catch.Reset();
6278 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006279 CompileRun("throw 0");
Steve Blocka7e24c12009-10-30 11:49:00 +00006280 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006281 CHECK_EQ(0, try_catch.Exception()->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006282}
6283
6284
6285THREADED_TEST(CatchExceptionFromWith) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006286 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006287 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006288 v8::TryCatch try_catch(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006289 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006290 CompileRun("var o = {}; with (o) { throw 42; }");
Steve Blocka7e24c12009-10-30 11:49:00 +00006291 CHECK(try_catch.HasCaught());
6292}
6293
6294
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006295THREADED_TEST(TryCatchAndFinallyHidingException) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006296 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006297 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006298 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006299 CHECK(!try_catch.HasCaught());
6300 CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
6301 CompileRun("f({toString: function() { throw 42; }});");
6302 CHECK(!try_catch.HasCaught());
6303}
6304
6305
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006306void WithTryCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006307 v8::TryCatch try_catch(args.GetIsolate());
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006308}
6309
6310
6311THREADED_TEST(TryCatchAndFinally) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006312 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006313 v8::Isolate* isolate = context->GetIsolate();
6314 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006315 CHECK(context->Global()
6316 ->Set(context.local(), v8_str("native_with_try_catch"),
6317 v8::FunctionTemplate::New(isolate, WithTryCatch)
6318 ->GetFunction(context.local())
6319 .ToLocalChecked())
6320 .FromJust());
6321 v8::TryCatch try_catch(isolate);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006322 CHECK(!try_catch.HasCaught());
6323 CompileRun(
6324 "try {\n"
6325 " throw new Error('a');\n"
6326 "} finally {\n"
6327 " native_with_try_catch();\n"
6328 "}\n");
6329 CHECK(try_catch.HasCaught());
6330}
6331
6332
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006333static void TryCatchNested1Helper(int depth) {
6334 if (depth > 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006335 v8::TryCatch try_catch(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006336 try_catch.SetVerbose(true);
6337 TryCatchNested1Helper(depth - 1);
6338 CHECK(try_catch.HasCaught());
6339 try_catch.ReThrow();
6340 } else {
6341 CcTest::isolate()->ThrowException(v8_str("E1"));
6342 }
6343}
6344
6345
6346static void TryCatchNested2Helper(int depth) {
6347 if (depth > 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006348 v8::TryCatch try_catch(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006349 try_catch.SetVerbose(true);
6350 TryCatchNested2Helper(depth - 1);
6351 CHECK(try_catch.HasCaught());
6352 try_catch.ReThrow();
6353 } else {
6354 CompileRun("throw 'E2';");
6355 }
6356}
6357
6358
6359TEST(TryCatchNested) {
6360 v8::V8::Initialize();
Steve Blocka7e24c12009-10-30 11:49:00 +00006361 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006362 v8::HandleScope scope(context->GetIsolate());
6363
6364 {
6365 // Test nested try-catch with a native throw in the end.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006366 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006367 TryCatchNested1Helper(5);
6368 CHECK(try_catch.HasCaught());
6369 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E1"));
6370 }
6371
6372 {
6373 // Test nested try-catch with a JavaScript throw in the end.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006374 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006375 TryCatchNested2Helper(5);
6376 CHECK(try_catch.HasCaught());
6377 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E2"));
6378 }
6379}
6380
6381
6382void TryCatchMixedNestingCheck(v8::TryCatch* try_catch) {
6383 CHECK(try_catch->HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006384 Local<Message> message = try_catch->Message();
6385 Local<Value> resource = message->GetScriptOrigin().ResourceName();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006386 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(resource), "inner"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006387 CHECK_EQ(0,
6388 strcmp(*v8::String::Utf8Value(message->Get()), "Uncaught Error: a"));
6389 CHECK_EQ(1, message->GetLineNumber(CcTest::isolate()->GetCurrentContext())
6390 .FromJust());
6391 CHECK_EQ(0, message->GetStartColumn(CcTest::isolate()->GetCurrentContext())
6392 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006393}
6394
6395
6396void TryCatchMixedNestingHelper(
6397 const v8::FunctionCallbackInfo<v8::Value>& args) {
6398 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006399 v8::TryCatch try_catch(args.GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006400 CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
6401 CHECK(try_catch.HasCaught());
6402 TryCatchMixedNestingCheck(&try_catch);
6403 try_catch.ReThrow();
6404}
6405
6406
6407// This test ensures that an outer TryCatch in the following situation:
6408// C++/TryCatch -> JS -> C++/TryCatch -> JS w/ SyntaxError
6409// does not clobber the Message object generated for the inner TryCatch.
6410// This exercises the ability of TryCatch.ReThrow() to restore the
6411// inner pending Message before throwing the exception again.
6412TEST(TryCatchMixedNesting) {
6413 v8::Isolate* isolate = CcTest::isolate();
6414 v8::HandleScope scope(isolate);
6415 v8::V8::Initialize();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006416 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006417 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6418 templ->Set(v8_str("TryCatchMixedNestingHelper"),
6419 v8::FunctionTemplate::New(isolate, TryCatchMixedNestingHelper));
6420 LocalContext context(0, templ);
6421 CompileRunWithOrigin("TryCatchMixedNestingHelper();\n", "outer", 1, 1);
6422 TryCatchMixedNestingCheck(&try_catch);
6423}
6424
6425
6426void TryCatchNativeHelper(const v8::FunctionCallbackInfo<v8::Value>& args) {
6427 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006428 v8::TryCatch try_catch(args.GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006429 args.GetIsolate()->ThrowException(v8_str("boom"));
6430 CHECK(try_catch.HasCaught());
6431}
6432
6433
6434TEST(TryCatchNative) {
6435 v8::Isolate* isolate = CcTest::isolate();
6436 v8::HandleScope scope(isolate);
6437 v8::V8::Initialize();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006438 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006439 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6440 templ->Set(v8_str("TryCatchNativeHelper"),
6441 v8::FunctionTemplate::New(isolate, TryCatchNativeHelper));
6442 LocalContext context(0, templ);
6443 CompileRun("TryCatchNativeHelper();");
6444 CHECK(!try_catch.HasCaught());
6445}
6446
6447
6448void TryCatchNativeResetHelper(
6449 const v8::FunctionCallbackInfo<v8::Value>& args) {
6450 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006451 v8::TryCatch try_catch(args.GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006452 args.GetIsolate()->ThrowException(v8_str("boom"));
6453 CHECK(try_catch.HasCaught());
6454 try_catch.Reset();
6455 CHECK(!try_catch.HasCaught());
6456}
6457
6458
6459TEST(TryCatchNativeReset) {
6460 v8::Isolate* isolate = CcTest::isolate();
6461 v8::HandleScope scope(isolate);
6462 v8::V8::Initialize();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006463 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006464 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6465 templ->Set(v8_str("TryCatchNativeResetHelper"),
6466 v8::FunctionTemplate::New(isolate, TryCatchNativeResetHelper));
6467 LocalContext context(0, templ);
6468 CompileRun("TryCatchNativeResetHelper();");
6469 CHECK(!try_catch.HasCaught());
6470}
6471
6472
6473THREADED_TEST(Equality) {
6474 LocalContext context;
6475 v8::Isolate* isolate = context->GetIsolate();
6476 v8::HandleScope scope(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006477 // Check that equality works at all before relying on CHECK_EQ
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006478 CHECK(v8_str("a")->Equals(context.local(), v8_str("a")).FromJust());
6479 CHECK(!v8_str("a")->Equals(context.local(), v8_str("b")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006480
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006481 CHECK(v8_str("a")->Equals(context.local(), v8_str("a")).FromJust());
6482 CHECK(!v8_str("a")->Equals(context.local(), v8_str("b")).FromJust());
6483 CHECK(v8_num(1)->Equals(context.local(), v8_num(1)).FromJust());
6484 CHECK(v8_num(1.00)->Equals(context.local(), v8_num(1)).FromJust());
6485 CHECK(!v8_num(1)->Equals(context.local(), v8_num(2)).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006486
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006487 // Assume String is not internalized.
Steve Blocka7e24c12009-10-30 11:49:00 +00006488 CHECK(v8_str("a")->StrictEquals(v8_str("a")));
6489 CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
6490 CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
6491 CHECK(v8_num(1)->StrictEquals(v8_num(1)));
6492 CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006493 CHECK(v8_num(0.0)->StrictEquals(v8_num(-0.0)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006494 Local<Value> not_a_number = v8_num(std::numeric_limits<double>::quiet_NaN());
Steve Blocka7e24c12009-10-30 11:49:00 +00006495 CHECK(!not_a_number->StrictEquals(not_a_number));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006496 CHECK(v8::False(isolate)->StrictEquals(v8::False(isolate)));
6497 CHECK(!v8::False(isolate)->StrictEquals(v8::Undefined(isolate)));
Steve Blocka7e24c12009-10-30 11:49:00 +00006498
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006499 v8::Local<v8::Object> obj = v8::Object::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006500 v8::Persistent<v8::Object> alias(isolate, obj);
6501 CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
6502 alias.Reset();
6503
6504 CHECK(v8_str("a")->SameValue(v8_str("a")));
6505 CHECK(!v8_str("a")->SameValue(v8_str("b")));
6506 CHECK(!v8_str("5")->SameValue(v8_num(5)));
6507 CHECK(v8_num(1)->SameValue(v8_num(1)));
6508 CHECK(!v8_num(1)->SameValue(v8_num(2)));
6509 CHECK(!v8_num(0.0)->SameValue(v8_num(-0.0)));
6510 CHECK(not_a_number->SameValue(not_a_number));
6511 CHECK(v8::False(isolate)->SameValue(v8::False(isolate)));
6512 CHECK(!v8::False(isolate)->SameValue(v8::Undefined(isolate)));
Steve Blocka7e24c12009-10-30 11:49:00 +00006513}
6514
6515
6516THREADED_TEST(MultiRun) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006517 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006518 v8::HandleScope scope(context->GetIsolate());
6519 Local<Script> script = v8_compile("x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006520 for (int i = 0; i < 10; i++) {
6521 script->Run(context.local()).IsEmpty();
6522 }
Steve Blocka7e24c12009-10-30 11:49:00 +00006523}
6524
6525
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006526static void GetXValue(Local<Name> name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006527 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006528 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006529 CHECK(info.Data()
6530 ->Equals(CcTest::isolate()->GetCurrentContext(), v8_str("donut"))
6531 .FromJust());
6532 CHECK(name->Equals(CcTest::isolate()->GetCurrentContext(), v8_str("x"))
6533 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006534 info.GetReturnValue().Set(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00006535}
6536
6537
6538THREADED_TEST(SimplePropertyRead) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006539 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006540 v8::Isolate* isolate = context->GetIsolate();
6541 v8::HandleScope scope(isolate);
6542 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6543 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006544 CHECK(context->Global()
6545 ->Set(context.local(), v8_str("obj"),
6546 templ->NewInstance(context.local()).ToLocalChecked())
6547 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006548 Local<Script> script = v8_compile("obj.x");
Steve Blocka7e24c12009-10-30 11:49:00 +00006549 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006550 Local<Value> result = script->Run(context.local()).ToLocalChecked();
6551 CHECK(result->Equals(context.local(), v8_str("x")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006552 }
6553}
6554
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006555
Andrei Popescu31002712010-02-23 13:46:05 +00006556THREADED_TEST(DefinePropertyOnAPIAccessor) {
Andrei Popescu31002712010-02-23 13:46:05 +00006557 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006558 v8::Isolate* isolate = context->GetIsolate();
6559 v8::HandleScope scope(isolate);
6560 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6561 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006562 CHECK(context->Global()
6563 ->Set(context.local(), v8_str("obj"),
6564 templ->NewInstance(context.local()).ToLocalChecked())
6565 .FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +00006566
6567 // Uses getOwnPropertyDescriptor to check the configurable status
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006568 Local<Script> script_desc = v8_compile(
6569 "var prop = Object.getOwnPropertyDescriptor( "
6570 "obj, 'x');"
6571 "prop.configurable;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006572 Local<Value> result = script_desc->Run(context.local()).ToLocalChecked();
6573 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), true);
Andrei Popescu31002712010-02-23 13:46:05 +00006574
6575 // Redefine get - but still configurable
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006576 Local<Script> script_define = v8_compile(
6577 "var desc = { get: function(){return 42; },"
6578 " configurable: true };"
6579 "Object.defineProperty(obj, 'x', desc);"
6580 "obj.x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006581 result = script_define->Run(context.local()).ToLocalChecked();
6582 CHECK(result->Equals(context.local(), v8_num(42)).FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +00006583
6584 // Check that the accessor is still configurable
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006585 result = script_desc->Run(context.local()).ToLocalChecked();
6586 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), true);
Andrei Popescu31002712010-02-23 13:46:05 +00006587
6588 // Redefine to a non-configurable
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006589 script_define = v8_compile(
6590 "var desc = { get: function(){return 43; },"
6591 " configurable: false };"
6592 "Object.defineProperty(obj, 'x', desc);"
6593 "obj.x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006594 result = script_define->Run(context.local()).ToLocalChecked();
6595 CHECK(result->Equals(context.local(), v8_num(43)).FromJust());
6596 result = script_desc->Run(context.local()).ToLocalChecked();
6597 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), false);
Andrei Popescu31002712010-02-23 13:46:05 +00006598
6599 // Make sure that it is not possible to redefine again
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006600 v8::TryCatch try_catch(isolate);
6601 CHECK(script_define->Run(context.local()).IsEmpty());
Andrei Popescu31002712010-02-23 13:46:05 +00006602 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006603 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006604 CHECK_EQ(0,
6605 strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
Andrei Popescu31002712010-02-23 13:46:05 +00006606}
6607
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006608
Andrei Popescu31002712010-02-23 13:46:05 +00006609THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006610 v8::Isolate* isolate = CcTest::isolate();
6611 v8::HandleScope scope(isolate);
6612 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Andrei Popescu31002712010-02-23 13:46:05 +00006613 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
6614 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006615 CHECK(context->Global()
6616 ->Set(context.local(), v8_str("obj"),
6617 templ->NewInstance(context.local()).ToLocalChecked())
6618 .FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +00006619
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006620 Local<Script> script_desc = v8_compile(
6621 "var prop ="
6622 "Object.getOwnPropertyDescriptor( "
6623 "obj, 'x');"
6624 "prop.configurable;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006625 Local<Value> result = script_desc->Run(context.local()).ToLocalChecked();
6626 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), true);
Andrei Popescu31002712010-02-23 13:46:05 +00006627
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006628 Local<Script> script_define = v8_compile(
6629 "var desc = {get: function(){return 42; },"
6630 " configurable: true };"
6631 "Object.defineProperty(obj, 'x', desc);"
6632 "obj.x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006633 result = script_define->Run(context.local()).ToLocalChecked();
6634 CHECK(result->Equals(context.local(), v8_num(42)).FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +00006635
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006636 result = script_desc->Run(context.local()).ToLocalChecked();
6637 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), true);
Andrei Popescu31002712010-02-23 13:46:05 +00006638
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006639 script_define = v8_compile(
6640 "var desc = {get: function(){return 43; },"
6641 " configurable: false };"
6642 "Object.defineProperty(obj, 'x', desc);"
6643 "obj.x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006644 result = script_define->Run(context.local()).ToLocalChecked();
6645 CHECK(result->Equals(context.local(), v8_num(43)).FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +00006646
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006647 result = script_desc->Run(context.local()).ToLocalChecked();
6648 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), false);
Andrei Popescu31002712010-02-23 13:46:05 +00006649
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006650 v8::TryCatch try_catch(isolate);
6651 CHECK(script_define->Run(context.local()).IsEmpty());
Andrei Popescu31002712010-02-23 13:46:05 +00006652 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006653 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006654 CHECK_EQ(0,
6655 strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
Andrei Popescu31002712010-02-23 13:46:05 +00006656}
6657
6658
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006659static v8::Local<v8::Object> GetGlobalProperty(LocalContext* context,
6660 char const* name) {
6661 return v8::Local<v8::Object>::Cast(
6662 (*context)
6663 ->Global()
6664 ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(name))
6665 .ToLocalChecked());
Leon Clarkef7060e22010-06-03 12:02:55 +01006666}
Andrei Popescu31002712010-02-23 13:46:05 +00006667
6668
Leon Clarkef7060e22010-06-03 12:02:55 +01006669THREADED_TEST(DefineAPIAccessorOnObject) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006670 v8::Isolate* isolate = CcTest::isolate();
6671 v8::HandleScope scope(isolate);
6672 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Leon Clarkef7060e22010-06-03 12:02:55 +01006673 LocalContext context;
6674
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006675 CHECK(context->Global()
6676 ->Set(context.local(), v8_str("obj1"),
6677 templ->NewInstance(context.local()).ToLocalChecked())
6678 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006679 CompileRun("var obj2 = {};");
6680
6681 CHECK(CompileRun("obj1.x")->IsUndefined());
6682 CHECK(CompileRun("obj2.x")->IsUndefined());
6683
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006684 CHECK(GetGlobalProperty(&context, "obj1")
6685 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6686 v8_str("donut"))
6687 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006688
6689 ExpectString("obj1.x", "x");
6690 CHECK(CompileRun("obj2.x")->IsUndefined());
6691
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006692 CHECK(GetGlobalProperty(&context, "obj2")
6693 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6694 v8_str("donut"))
6695 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006696
6697 ExpectString("obj1.x", "x");
6698 ExpectString("obj2.x", "x");
6699
6700 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
6701 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
6702
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006703 CompileRun(
6704 "Object.defineProperty(obj1, 'x',"
6705 "{ get: function() { return 'y'; }, configurable: true })");
Leon Clarkef7060e22010-06-03 12:02:55 +01006706
6707 ExpectString("obj1.x", "y");
6708 ExpectString("obj2.x", "x");
6709
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006710 CompileRun(
6711 "Object.defineProperty(obj2, 'x',"
6712 "{ get: function() { return 'y'; }, configurable: true })");
Leon Clarkef7060e22010-06-03 12:02:55 +01006713
6714 ExpectString("obj1.x", "y");
6715 ExpectString("obj2.x", "y");
6716
6717 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
6718 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
6719
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006720 CHECK(GetGlobalProperty(&context, "obj1")
6721 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6722 v8_str("donut"))
6723 .FromJust());
6724 CHECK(GetGlobalProperty(&context, "obj2")
6725 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6726 v8_str("donut"))
6727 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006728
6729 ExpectString("obj1.x", "x");
6730 ExpectString("obj2.x", "x");
6731
6732 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
6733 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
6734
6735 // Define getters/setters, but now make them not configurable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006736 CompileRun(
6737 "Object.defineProperty(obj1, 'x',"
6738 "{ get: function() { return 'z'; }, configurable: false })");
6739 CompileRun(
6740 "Object.defineProperty(obj2, 'x',"
6741 "{ get: function() { return 'z'; }, configurable: false })");
Leon Clarkef7060e22010-06-03 12:02:55 +01006742 ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
6743 ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
6744
6745 ExpectString("obj1.x", "z");
6746 ExpectString("obj2.x", "z");
6747
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006748 CHECK(GetGlobalProperty(&context, "obj1")
6749 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6750 v8_str("donut"))
6751 .IsNothing());
6752 CHECK(GetGlobalProperty(&context, "obj2")
6753 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6754 v8_str("donut"))
6755 .IsNothing());
Leon Clarkef7060e22010-06-03 12:02:55 +01006756
6757 ExpectString("obj1.x", "z");
6758 ExpectString("obj2.x", "z");
6759}
6760
6761
6762THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006763 v8::Isolate* isolate = CcTest::isolate();
6764 v8::HandleScope scope(isolate);
6765 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Leon Clarkef7060e22010-06-03 12:02:55 +01006766 LocalContext context;
6767
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006768 CHECK(context->Global()
6769 ->Set(context.local(), v8_str("obj1"),
6770 templ->NewInstance(context.local()).ToLocalChecked())
6771 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006772 CompileRun("var obj2 = {};");
6773
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006774 CHECK(GetGlobalProperty(&context, "obj1")
6775 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6776 v8_str("donut"), v8::DEFAULT, v8::DontDelete)
6777 .FromJust());
6778 CHECK(GetGlobalProperty(&context, "obj2")
6779 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6780 v8_str("donut"), v8::DEFAULT, v8::DontDelete)
6781 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006782
6783 ExpectString("obj1.x", "x");
6784 ExpectString("obj2.x", "x");
6785
6786 ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
6787 ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
6788
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006789 CHECK(GetGlobalProperty(&context, "obj1")
6790 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6791 v8_str("donut"))
6792 .IsNothing());
6793 CHECK(GetGlobalProperty(&context, "obj2")
6794 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6795 v8_str("donut"))
6796 .IsNothing());
Leon Clarkef7060e22010-06-03 12:02:55 +01006797
6798 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006799 v8::TryCatch try_catch(isolate);
6800 CompileRun(
6801 "Object.defineProperty(obj1, 'x',"
Leon Clarkef7060e22010-06-03 12:02:55 +01006802 "{get: function() { return 'func'; }})");
6803 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006804 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006805 CHECK_EQ(
6806 0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
Leon Clarkef7060e22010-06-03 12:02:55 +01006807 }
6808 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006809 v8::TryCatch try_catch(isolate);
6810 CompileRun(
6811 "Object.defineProperty(obj2, 'x',"
Leon Clarkef7060e22010-06-03 12:02:55 +01006812 "{get: function() { return 'func'; }})");
6813 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006814 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006815 CHECK_EQ(
6816 0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
Leon Clarkef7060e22010-06-03 12:02:55 +01006817 }
6818}
6819
6820
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006821static void Get239Value(Local<Name> name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006822 const v8::PropertyCallbackInfo<v8::Value>& info) {
Leon Clarkef7060e22010-06-03 12:02:55 +01006823 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006824 CHECK(info.Data()
6825 ->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("donut"))
6826 .FromJust());
6827 CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("239"))
6828 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006829 info.GetReturnValue().Set(name);
Leon Clarkef7060e22010-06-03 12:02:55 +01006830}
6831
6832
6833THREADED_TEST(ElementAPIAccessor) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006834 v8::Isolate* isolate = CcTest::isolate();
6835 v8::HandleScope scope(isolate);
6836 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Leon Clarkef7060e22010-06-03 12:02:55 +01006837 LocalContext context;
6838
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006839 CHECK(context->Global()
6840 ->Set(context.local(), v8_str("obj1"),
6841 templ->NewInstance(context.local()).ToLocalChecked())
6842 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006843 CompileRun("var obj2 = {};");
6844
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006845 CHECK(GetGlobalProperty(&context, "obj1")
6846 ->SetAccessor(context.local(), v8_str("239"), Get239Value, NULL,
6847 v8_str("donut"))
6848 .FromJust());
6849 CHECK(GetGlobalProperty(&context, "obj2")
6850 ->SetAccessor(context.local(), v8_str("239"), Get239Value, NULL,
6851 v8_str("donut"))
6852 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006853
6854 ExpectString("obj1[239]", "239");
6855 ExpectString("obj2[239]", "239");
6856 ExpectString("obj1['239']", "239");
6857 ExpectString("obj2['239']", "239");
6858}
6859
Steve Blocka7e24c12009-10-30 11:49:00 +00006860
6861v8::Persistent<Value> xValue;
6862
6863
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006864static void SetXValue(Local<Name> name, Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006865 const v8::PropertyCallbackInfo<void>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006866 Local<Context> context = info.GetIsolate()->GetCurrentContext();
6867 CHECK(value->Equals(context, v8_num(4)).FromJust());
6868 CHECK(info.Data()->Equals(context, v8_str("donut")).FromJust());
6869 CHECK(name->Equals(context, v8_str("x")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006870 CHECK(xValue.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006871 xValue.Reset(info.GetIsolate(), value);
Steve Blocka7e24c12009-10-30 11:49:00 +00006872}
6873
6874
6875THREADED_TEST(SimplePropertyWrite) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006876 v8::Isolate* isolate = CcTest::isolate();
6877 v8::HandleScope scope(isolate);
6878 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00006879 templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
6880 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006881 CHECK(context->Global()
6882 ->Set(context.local(), v8_str("obj"),
6883 templ->NewInstance(context.local()).ToLocalChecked())
6884 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006885 Local<Script> script = v8_compile("obj.x = 4");
Steve Blocka7e24c12009-10-30 11:49:00 +00006886 for (int i = 0; i < 10; i++) {
6887 CHECK(xValue.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006888 script->Run(context.local()).ToLocalChecked();
6889 CHECK(v8_num(4)
6890 ->Equals(context.local(),
6891 Local<Value>::New(CcTest::isolate(), xValue))
6892 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006893 xValue.Reset();
Steve Blocka7e24c12009-10-30 11:49:00 +00006894 }
6895}
6896
6897
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006898THREADED_TEST(SetterOnly) {
6899 v8::Isolate* isolate = CcTest::isolate();
6900 v8::HandleScope scope(isolate);
6901 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6902 templ->SetAccessor(v8_str("x"), NULL, SetXValue, v8_str("donut"));
6903 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006904 CHECK(context->Global()
6905 ->Set(context.local(), v8_str("obj"),
6906 templ->NewInstance(context.local()).ToLocalChecked())
6907 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006908 Local<Script> script = v8_compile("obj.x = 4; obj.x");
6909 for (int i = 0; i < 10; i++) {
6910 CHECK(xValue.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006911 script->Run(context.local()).ToLocalChecked();
6912 CHECK(v8_num(4)
6913 ->Equals(context.local(),
6914 Local<Value>::New(CcTest::isolate(), xValue))
6915 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006916 xValue.Reset();
6917 }
6918}
6919
6920
6921THREADED_TEST(NoAccessors) {
6922 v8::Isolate* isolate = CcTest::isolate();
6923 v8::HandleScope scope(isolate);
6924 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006925 templ->SetAccessor(v8_str("x"), static_cast<v8::AccessorGetterCallback>(NULL),
6926 NULL, v8_str("donut"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006927 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006928 CHECK(context->Global()
6929 ->Set(context.local(), v8_str("obj"),
6930 templ->NewInstance(context.local()).ToLocalChecked())
6931 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006932 Local<Script> script = v8_compile("obj.x = 4; obj.x");
6933 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006934 script->Run(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006935 }
6936}
6937
6938
Steve Blocka7e24c12009-10-30 11:49:00 +00006939THREADED_TEST(MultiContexts) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006940 v8::Isolate* isolate = CcTest::isolate();
6941 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006942 v8::Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6943 templ->Set(v8_str("dummy"),
6944 v8::FunctionTemplate::New(isolate, DummyCallHandler));
Steve Blocka7e24c12009-10-30 11:49:00 +00006945
6946 Local<String> password = v8_str("Password");
6947
6948 // Create an environment
6949 LocalContext context0(0, templ);
6950 context0->SetSecurityToken(password);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006951 v8::Local<v8::Object> global0 = context0->Global();
6952 CHECK(global0->Set(context0.local(), v8_str("custom"), v8_num(1234))
6953 .FromJust());
6954 CHECK_EQ(1234, global0->Get(context0.local(), v8_str("custom"))
6955 .ToLocalChecked()
6956 ->Int32Value(context0.local())
6957 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006958
6959 // Create an independent environment
6960 LocalContext context1(0, templ);
6961 context1->SetSecurityToken(password);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006962 v8::Local<v8::Object> global1 = context1->Global();
6963 CHECK(global1->Set(context1.local(), v8_str("custom"), v8_num(1234))
6964 .FromJust());
6965 CHECK(!global0->Equals(context1.local(), global1).FromJust());
6966 CHECK_EQ(1234, global0->Get(context1.local(), v8_str("custom"))
6967 .ToLocalChecked()
6968 ->Int32Value(context0.local())
6969 .FromJust());
6970 CHECK_EQ(1234, global1->Get(context1.local(), v8_str("custom"))
6971 .ToLocalChecked()
6972 ->Int32Value(context1.local())
6973 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006974
6975 // Now create a new context with the old global
6976 LocalContext context2(0, templ, global1);
6977 context2->SetSecurityToken(password);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006978 v8::Local<v8::Object> global2 = context2->Global();
6979 CHECK(global1->Equals(context2.local(), global2).FromJust());
6980 CHECK_EQ(0, global1->Get(context2.local(), v8_str("custom"))
6981 .ToLocalChecked()
6982 ->Int32Value(context1.local())
6983 .FromJust());
6984 CHECK_EQ(0, global2->Get(context2.local(), v8_str("custom"))
6985 .ToLocalChecked()
6986 ->Int32Value(context2.local())
6987 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006988}
6989
6990
6991THREADED_TEST(FunctionPrototypeAcrossContexts) {
6992 // Make sure that functions created by cloning boilerplates cannot
6993 // communicate through their __proto__ field.
6994
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006995 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006996
6997 LocalContext env0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006998 v8::Local<v8::Object> global0 = env0->Global();
6999 v8::Local<v8::Object> object0 = global0->Get(env0.local(), v8_str("Object"))
7000 .ToLocalChecked()
7001 .As<v8::Object>();
7002 v8::Local<v8::Object> tostring0 =
7003 object0->Get(env0.local(), v8_str("toString"))
7004 .ToLocalChecked()
7005 .As<v8::Object>();
7006 v8::Local<v8::Object> proto0 =
7007 tostring0->Get(env0.local(), v8_str("__proto__"))
7008 .ToLocalChecked()
7009 .As<v8::Object>();
7010 CHECK(proto0->Set(env0.local(), v8_str("custom"), v8_num(1234)).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007011
7012 LocalContext env1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007013 v8::Local<v8::Object> global1 = env1->Global();
7014 v8::Local<v8::Object> object1 = global1->Get(env1.local(), v8_str("Object"))
7015 .ToLocalChecked()
7016 .As<v8::Object>();
7017 v8::Local<v8::Object> tostring1 =
7018 object1->Get(env1.local(), v8_str("toString"))
7019 .ToLocalChecked()
7020 .As<v8::Object>();
7021 v8::Local<v8::Object> proto1 =
7022 tostring1->Get(env1.local(), v8_str("__proto__"))
7023 .ToLocalChecked()
7024 .As<v8::Object>();
7025 CHECK(!proto1->Has(env1.local(), v8_str("custom")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007026}
7027
7028
7029THREADED_TEST(Regress892105) {
7030 // Make sure that object and array literals created by cloning
7031 // boilerplates cannot communicate through their __proto__
7032 // field. This is rather difficult to check, but we try to add stuff
7033 // to Object.prototype and Array.prototype and create a new
7034 // environment. This should succeed.
7035
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007036 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007037
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007038 Local<String> source = v8_str(
7039 "Object.prototype.obj = 1234;"
7040 "Array.prototype.arr = 4567;"
7041 "8901");
Steve Blocka7e24c12009-10-30 11:49:00 +00007042
7043 LocalContext env0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007044 Local<Script> script0 = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007045 CHECK_EQ(8901.0, script0->Run(env0.local())
7046 .ToLocalChecked()
7047 ->NumberValue(env0.local())
7048 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007049
7050 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007051 Local<Script> script1 = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007052 CHECK_EQ(8901.0, script1->Run(env1.local())
7053 .ToLocalChecked()
7054 ->NumberValue(env1.local())
7055 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007056}
7057
7058
Steve Blocka7e24c12009-10-30 11:49:00 +00007059THREADED_TEST(UndetectableObject) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007060 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007061 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007062
7063 Local<v8::FunctionTemplate> desc =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007064 v8::FunctionTemplate::New(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007065 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
7066
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007067 Local<v8::Object> obj = desc->GetFunction(env.local())
7068 .ToLocalChecked()
7069 ->NewInstance(env.local())
7070 .ToLocalChecked();
7071 CHECK(
7072 env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007073
7074 ExpectString("undetectable.toString()", "[object Object]");
7075 ExpectString("typeof undetectable", "undefined");
7076 ExpectString("typeof(undetectable)", "undefined");
7077 ExpectBoolean("typeof undetectable == 'undefined'", true);
7078 ExpectBoolean("typeof undetectable == 'object'", false);
7079 ExpectBoolean("if (undetectable) { true; } else { false; }", false);
7080 ExpectBoolean("!undetectable", true);
7081
7082 ExpectObject("true&&undetectable", obj);
7083 ExpectBoolean("false&&undetectable", false);
7084 ExpectBoolean("true||undetectable", true);
7085 ExpectObject("false||undetectable", obj);
7086
7087 ExpectObject("undetectable&&true", obj);
7088 ExpectObject("undetectable&&false", obj);
7089 ExpectBoolean("undetectable||true", true);
7090 ExpectBoolean("undetectable||false", false);
7091
7092 ExpectBoolean("undetectable==null", true);
7093 ExpectBoolean("null==undetectable", true);
7094 ExpectBoolean("undetectable==undefined", true);
7095 ExpectBoolean("undefined==undetectable", true);
7096 ExpectBoolean("undetectable==undetectable", true);
7097
7098
7099 ExpectBoolean("undetectable===null", false);
7100 ExpectBoolean("null===undetectable", false);
7101 ExpectBoolean("undetectable===undefined", false);
7102 ExpectBoolean("undefined===undetectable", false);
7103 ExpectBoolean("undetectable===undetectable", true);
7104}
7105
7106
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007107THREADED_TEST(VoidLiteral) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007108 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007109 v8::Isolate* isolate = env->GetIsolate();
7110 v8::HandleScope scope(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007111
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007112 Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007113 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
7114
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007115 Local<v8::Object> obj = desc->GetFunction(env.local())
7116 .ToLocalChecked()
7117 ->NewInstance(env.local())
7118 .ToLocalChecked();
7119 CHECK(
7120 env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007121
7122 ExpectBoolean("undefined == void 0", true);
7123 ExpectBoolean("undetectable == void 0", true);
7124 ExpectBoolean("null == void 0", true);
7125 ExpectBoolean("undefined === void 0", true);
7126 ExpectBoolean("undetectable === void 0", false);
7127 ExpectBoolean("null === void 0", false);
7128
7129 ExpectBoolean("void 0 == undefined", true);
7130 ExpectBoolean("void 0 == undetectable", true);
7131 ExpectBoolean("void 0 == null", true);
7132 ExpectBoolean("void 0 === undefined", true);
7133 ExpectBoolean("void 0 === undetectable", false);
7134 ExpectBoolean("void 0 === null", false);
7135
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007136 ExpectString(
7137 "(function() {"
7138 " try {"
7139 " return x === void 0;"
7140 " } catch(e) {"
7141 " return e.toString();"
7142 " }"
7143 "})()",
7144 "ReferenceError: x is not defined");
7145 ExpectString(
7146 "(function() {"
7147 " try {"
7148 " return void 0 === x;"
7149 " } catch(e) {"
7150 " return e.toString();"
7151 " }"
7152 "})()",
7153 "ReferenceError: x is not defined");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007154}
7155
Steve Block8defd9f2010-07-08 12:39:36 +01007156
7157THREADED_TEST(ExtensibleOnUndetectable) {
Steve Block8defd9f2010-07-08 12:39:36 +01007158 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007159 v8::Isolate* isolate = env->GetIsolate();
7160 v8::HandleScope scope(isolate);
Steve Block8defd9f2010-07-08 12:39:36 +01007161
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007162 Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
Steve Block8defd9f2010-07-08 12:39:36 +01007163 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
7164
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007165 Local<v8::Object> obj = desc->GetFunction(env.local())
7166 .ToLocalChecked()
7167 ->NewInstance(env.local())
7168 .ToLocalChecked();
7169 CHECK(
7170 env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +01007171
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007172 Local<String> source = v8_str(
7173 "undetectable.x = 42;"
7174 "undetectable.x");
Steve Block8defd9f2010-07-08 12:39:36 +01007175
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007176 Local<Script> script = v8_compile(source);
Steve Block8defd9f2010-07-08 12:39:36 +01007177
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007178 CHECK(v8::Integer::New(isolate, 42)
7179 ->Equals(env.local(), script->Run(env.local()).ToLocalChecked())
7180 .FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +01007181
7182 ExpectBoolean("Object.isExtensible(undetectable)", true);
7183
7184 source = v8_str("Object.preventExtensions(undetectable);");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007185 script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007186 script->Run(env.local()).ToLocalChecked();
Steve Block8defd9f2010-07-08 12:39:36 +01007187 ExpectBoolean("Object.isExtensible(undetectable)", false);
7188
7189 source = v8_str("undetectable.y = 2000;");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007190 script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007191 script->Run(env.local()).ToLocalChecked();
Steve Block44f0eee2011-05-26 01:26:41 +01007192 ExpectBoolean("undetectable.y == undefined", true);
Steve Block8defd9f2010-07-08 12:39:36 +01007193}
7194
7195
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007196// The point of this test is type checking. We run it only so compilers
7197// don't complain about an unused function.
7198TEST(PersistentHandles) {
7199 LocalContext env;
7200 v8::Isolate* isolate = CcTest::isolate();
7201 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00007202 Local<String> str = v8_str("foo");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007203 v8::Persistent<String> p_str(isolate, str);
7204 p_str.Reset();
7205 Local<Script> scr = v8_compile("");
7206 v8::Persistent<Script> p_scr(isolate, scr);
7207 p_scr.Reset();
7208 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
7209 v8::Persistent<ObjectTemplate> p_templ(isolate, templ);
7210 p_templ.Reset();
Steve Blocka7e24c12009-10-30 11:49:00 +00007211}
7212
7213
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007214static void HandleLogDelegator(
7215 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007216 ApiTestFuzzer::Fuzz();
Steve Blocka7e24c12009-10-30 11:49:00 +00007217}
7218
7219
7220THREADED_TEST(GlobalObjectTemplate) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007221 v8::Isolate* isolate = CcTest::isolate();
7222 v8::HandleScope handle_scope(isolate);
7223 Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00007224 global_template->Set(v8_str("JSNI_Log"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007225 v8::FunctionTemplate::New(isolate, HandleLogDelegator));
7226 v8::Local<Context> context = Context::New(isolate, 0, global_template);
Steve Blocka7e24c12009-10-30 11:49:00 +00007227 Context::Scope context_scope(context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007228 CompileRun("JSNI_Log('LOG')");
Steve Blocka7e24c12009-10-30 11:49:00 +00007229}
7230
7231
7232static const char* kSimpleExtensionSource =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007233 "function Foo() {"
7234 " return 4;"
7235 "}";
Steve Blocka7e24c12009-10-30 11:49:00 +00007236
7237
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007238TEST(SimpleExtensions) {
7239 v8::HandleScope handle_scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007240 v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007241 const char* extension_names[] = {"simpletest"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007242 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007243 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Steve Blocka7e24c12009-10-30 11:49:00 +00007244 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007245 v8::Local<Value> result = CompileRun("Foo()");
7246 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
7247 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007248}
7249
7250
7251static const char* kStackTraceFromExtensionSource =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007252 "function foo() {"
7253 " throw new Error();"
7254 "}"
7255 "function bar() {"
7256 " foo();"
7257 "}";
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007258
7259
7260TEST(StackTraceInExtension) {
7261 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007262 v8::RegisterExtension(
7263 new Extension("stacktracetest", kStackTraceFromExtensionSource));
7264 const char* extension_names[] = {"stacktracetest"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007265 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007266 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007267 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007268 CompileRun(
7269 "function user() { bar(); }"
7270 "var error;"
7271 "try{ user(); } catch (e) { error = e; }");
7272 CHECK_EQ(-1, v8_run_int32value(v8_compile("error.stack.indexOf('foo')")));
7273 CHECK_EQ(-1, v8_run_int32value(v8_compile("error.stack.indexOf('bar')")));
7274 CHECK_NE(-1, v8_run_int32value(v8_compile("error.stack.indexOf('user')")));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007275}
7276
7277
7278TEST(NullExtensions) {
7279 v8::HandleScope handle_scope(CcTest::isolate());
7280 v8::RegisterExtension(new Extension("nulltest", NULL));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007281 const char* extension_names[] = {"nulltest"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007282 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007283 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007284 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007285 v8::Local<Value> result = CompileRun("1+3");
7286 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
7287 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007288}
7289
7290
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007291static const char* kEmbeddedExtensionSource =
7292 "function Ret54321(){return 54321;}~~@@$"
7293 "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
7294static const int kEmbeddedExtensionSourceValidLen = 34;
7295
7296
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007297TEST(ExtensionMissingSourceLength) {
7298 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007299 v8::RegisterExtension(
7300 new Extension("srclentest_fail", kEmbeddedExtensionSource));
7301 const char* extension_names[] = {"srclentest_fail"};
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007302 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007303 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
7304 CHECK(0 == *context);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007305}
7306
7307
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007308TEST(ExtensionWithSourceLength) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007309 for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
7310 source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007311 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007312 i::ScopedVector<char> extension_name(32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007313 i::SNPrintF(extension_name, "ext #%d", source_len);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007314 v8::RegisterExtension(new Extension(
7315 extension_name.start(), kEmbeddedExtensionSource, 0, 0, source_len));
7316 const char* extension_names[1] = {extension_name.start()};
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007317 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007318 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007319 if (source_len == kEmbeddedExtensionSourceValidLen) {
7320 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007321 v8::Local<Value> result = CompileRun("Ret54321()");
7322 CHECK(v8::Integer::New(CcTest::isolate(), 54321)
7323 ->Equals(context, result)
7324 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007325 } else {
7326 // Anything but exactly the right length should fail to compile.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007327 CHECK(0 == *context);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007328 }
7329 }
7330}
7331
7332
Steve Blocka7e24c12009-10-30 11:49:00 +00007333static const char* kEvalExtensionSource1 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007334 "function UseEval1() {"
7335 " var x = 42;"
7336 " return eval('x');"
7337 "}";
Steve Blocka7e24c12009-10-30 11:49:00 +00007338
7339
7340static const char* kEvalExtensionSource2 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007341 "(function() {"
7342 " var x = 42;"
7343 " function e() {"
7344 " return eval('x');"
7345 " }"
7346 " this.UseEval2 = e;"
7347 "})()";
Steve Blocka7e24c12009-10-30 11:49:00 +00007348
7349
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007350TEST(UseEvalFromExtension) {
7351 v8::HandleScope handle_scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007352 v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
7353 v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007354 const char* extension_names[] = {"evaltest1", "evaltest2"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007355 v8::ExtensionConfiguration extensions(2, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007356 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Steve Blocka7e24c12009-10-30 11:49:00 +00007357 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007358 v8::Local<Value> result = CompileRun("UseEval1()");
7359 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
7360 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007361 result = CompileRun("UseEval2()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007362 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
7363 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007364}
7365
7366
7367static const char* kWithExtensionSource1 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007368 "function UseWith1() {"
7369 " var x = 42;"
7370 " with({x:87}) { return x; }"
7371 "}";
Steve Blocka7e24c12009-10-30 11:49:00 +00007372
7373
7374static const char* kWithExtensionSource2 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007375 "(function() {"
7376 " var x = 42;"
7377 " function e() {"
7378 " with ({x:87}) { return x; }"
7379 " }"
7380 " this.UseWith2 = e;"
7381 "})()";
Steve Blocka7e24c12009-10-30 11:49:00 +00007382
7383
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007384TEST(UseWithFromExtension) {
7385 v8::HandleScope handle_scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007386 v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
7387 v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007388 const char* extension_names[] = {"withtest1", "withtest2"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007389 v8::ExtensionConfiguration extensions(2, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007390 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Steve Blocka7e24c12009-10-30 11:49:00 +00007391 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007392 v8::Local<Value> result = CompileRun("UseWith1()");
7393 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 87))
7394 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007395 result = CompileRun("UseWith2()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007396 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 87))
7397 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007398}
7399
7400
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007401TEST(AutoExtensions) {
7402 v8::HandleScope handle_scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007403 Extension* extension = new Extension("autotest", kSimpleExtensionSource);
7404 extension->set_auto_enable(true);
7405 v8::RegisterExtension(extension);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007406 v8::Local<Context> context = Context::New(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007407 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007408 v8::Local<Value> result = CompileRun("Foo()");
7409 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
7410 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007411}
7412
7413
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007414static const char* kSyntaxErrorInExtensionSource = "[";
Steve Blockd0582a62009-12-15 09:54:21 +00007415
7416
7417// Test that a syntax error in an extension does not cause a fatal
7418// error but results in an empty context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007419TEST(SyntaxErrorExtensions) {
7420 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007421 v8::RegisterExtension(
7422 new Extension("syntaxerror", kSyntaxErrorInExtensionSource));
7423 const char* extension_names[] = {"syntaxerror"};
Steve Blockd0582a62009-12-15 09:54:21 +00007424 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007425 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Steve Blockd0582a62009-12-15 09:54:21 +00007426 CHECK(context.IsEmpty());
7427}
7428
7429
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007430static const char* kExceptionInExtensionSource = "throw 42";
Steve Blockd0582a62009-12-15 09:54:21 +00007431
7432
7433// Test that an exception when installing an extension does not cause
7434// a fatal error but results in an empty context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007435TEST(ExceptionExtensions) {
7436 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007437 v8::RegisterExtension(
7438 new Extension("exception", kExceptionInExtensionSource));
7439 const char* extension_names[] = {"exception"};
Steve Blockd0582a62009-12-15 09:54:21 +00007440 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007441 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Steve Blockd0582a62009-12-15 09:54:21 +00007442 CHECK(context.IsEmpty());
7443}
7444
7445
Iain Merrick9ac36c92010-09-13 15:29:50 +01007446static const char* kNativeCallInExtensionSource =
7447 "function call_runtime_last_index_of(x) {"
7448 " return %StringLastIndexOf(x, 'bob', 10);"
7449 "}";
7450
7451
7452static const char* kNativeCallTest =
7453 "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
7454
7455// Test that a native runtime calls are supported in extensions.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007456TEST(NativeCallInExtensions) {
7457 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007458 v8::RegisterExtension(
7459 new Extension("nativecall", kNativeCallInExtensionSource));
7460 const char* extension_names[] = {"nativecall"};
Iain Merrick9ac36c92010-09-13 15:29:50 +01007461 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007462 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Iain Merrick9ac36c92010-09-13 15:29:50 +01007463 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007464 v8::Local<Value> result = CompileRun(kNativeCallTest);
7465 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 3))
7466 .FromJust());
Iain Merrick9ac36c92010-09-13 15:29:50 +01007467}
7468
7469
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007470class NativeFunctionExtension : public Extension {
7471 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007472 NativeFunctionExtension(const char* name, const char* source,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007473 v8::FunctionCallback fun = &Echo)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007474 : Extension(name, source), function_(fun) {}
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007475
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007476 virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
7477 v8::Isolate* isolate, v8::Local<v8::String> name) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007478 return v8::FunctionTemplate::New(isolate, function_);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007479 }
7480
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007481 static void Echo(const v8::FunctionCallbackInfo<v8::Value>& args) {
7482 if (args.Length() >= 1) args.GetReturnValue().Set(args[0]);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007483 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007484
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007485 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007486 v8::FunctionCallback function_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007487};
7488
7489
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007490TEST(NativeFunctionDeclaration) {
7491 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007492 const char* name = "nativedecl";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007493 v8::RegisterExtension(
7494 new NativeFunctionExtension(name, "native function foo();"));
7495 const char* extension_names[] = {name};
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007496 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007497 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007498 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007499 v8::Local<Value> result = CompileRun("foo(42);");
7500 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
7501 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007502}
7503
7504
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007505TEST(NativeFunctionDeclarationError) {
7506 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007507 const char* name = "nativedeclerr";
7508 // Syntax error in extension code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007509 v8::RegisterExtension(
7510 new NativeFunctionExtension(name, "native\nfunction foo();"));
7511 const char* extension_names[] = {name};
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007512 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007513 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007514 CHECK(context.IsEmpty());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007515}
7516
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007517
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007518TEST(NativeFunctionDeclarationErrorEscape) {
7519 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007520 const char* name = "nativedeclerresc";
7521 // Syntax error in extension code - escape code in "native" means that
7522 // it's not treated as a keyword.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007523 v8::RegisterExtension(
7524 new NativeFunctionExtension(name, "nativ\\u0065 function foo();"));
7525 const char* extension_names[] = {name};
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007526 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007527 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007528 CHECK(context.IsEmpty());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007529}
7530
7531
Steve Blocka7e24c12009-10-30 11:49:00 +00007532static void CheckDependencies(const char* name, const char* expected) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007533 v8::HandleScope handle_scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007534 v8::ExtensionConfiguration config(1, &name);
7535 LocalContext context(&config);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007536 CHECK(
7537 v8_str(expected)
7538 ->Equals(context.local(), context->Global()
7539 ->Get(context.local(), v8_str("loaded"))
7540 .ToLocalChecked())
7541 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007542}
7543
7544
7545/*
7546 * Configuration:
7547 *
7548 * /-- B <--\
7549 * A <- -- D <-- E
7550 * \-- C <--/
7551 */
7552THREADED_TEST(ExtensionDependency) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007553 static const char* kEDeps[] = {"D"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007554 v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007555 static const char* kDDeps[] = {"B", "C"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007556 v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007557 static const char* kBCDeps[] = {"A"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007558 v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
7559 v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
7560 v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
7561 CheckDependencies("A", "undefinedA");
7562 CheckDependencies("B", "undefinedAB");
7563 CheckDependencies("C", "undefinedAC");
7564 CheckDependencies("D", "undefinedABCD");
7565 CheckDependencies("E", "undefinedABCDE");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007566 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007567 static const char* exts[2] = {"C", "E"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007568 v8::ExtensionConfiguration config(2, exts);
7569 LocalContext context(&config);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007570 CHECK(
7571 v8_str("undefinedACBDE")
7572 ->Equals(context.local(), context->Global()
7573 ->Get(context.local(), v8_str("loaded"))
7574 .ToLocalChecked())
7575 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007576}
7577
7578
7579static const char* kExtensionTestScript =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007580 "native function A();"
7581 "native function B();"
7582 "native function C();"
7583 "function Foo(i) {"
7584 " if (i == 0) return A();"
7585 " if (i == 1) return B();"
7586 " if (i == 2) return C();"
7587 "}";
Steve Blocka7e24c12009-10-30 11:49:00 +00007588
7589
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007590static void CallFun(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007591 ApiTestFuzzer::Fuzz();
Leon Clarkee46be812010-01-19 14:06:41 +00007592 if (args.IsConstructCall()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007593 CHECK(args.This()
7594 ->Set(args.GetIsolate()->GetCurrentContext(), v8_str("data"),
7595 args.Data())
7596 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007597 args.GetReturnValue().SetNull();
7598 return;
Leon Clarkee46be812010-01-19 14:06:41 +00007599 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007600 args.GetReturnValue().Set(args.Data());
Steve Blocka7e24c12009-10-30 11:49:00 +00007601}
7602
7603
7604class FunctionExtension : public Extension {
7605 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007606 FunctionExtension() : Extension("functiontest", kExtensionTestScript) {}
7607 virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
7608 v8::Isolate* isolate, v8::Local<String> name);
Steve Blocka7e24c12009-10-30 11:49:00 +00007609};
7610
7611
7612static int lookup_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007613v8::Local<v8::FunctionTemplate> FunctionExtension::GetNativeFunctionTemplate(
7614 v8::Isolate* isolate, v8::Local<String> name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007615 lookup_count++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007616 if (name->Equals(isolate->GetCurrentContext(), v8_str("A")).FromJust()) {
7617 return v8::FunctionTemplate::New(isolate, CallFun,
7618 v8::Integer::New(isolate, 8));
7619 } else if (name->Equals(isolate->GetCurrentContext(), v8_str("B"))
7620 .FromJust()) {
7621 return v8::FunctionTemplate::New(isolate, CallFun,
7622 v8::Integer::New(isolate, 7));
7623 } else if (name->Equals(isolate->GetCurrentContext(), v8_str("C"))
7624 .FromJust()) {
7625 return v8::FunctionTemplate::New(isolate, CallFun,
7626 v8::Integer::New(isolate, 6));
Steve Blocka7e24c12009-10-30 11:49:00 +00007627 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007628 return v8::Local<v8::FunctionTemplate>();
Steve Blocka7e24c12009-10-30 11:49:00 +00007629 }
7630}
7631
7632
7633THREADED_TEST(FunctionLookup) {
7634 v8::RegisterExtension(new FunctionExtension());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007635 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007636 static const char* exts[1] = {"functiontest"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007637 v8::ExtensionConfiguration config(1, exts);
7638 LocalContext context(&config);
7639 CHECK_EQ(3, lookup_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007640 CHECK(v8::Integer::New(CcTest::isolate(), 8)
7641 ->Equals(context.local(), CompileRun("Foo(0)"))
7642 .FromJust());
7643 CHECK(v8::Integer::New(CcTest::isolate(), 7)
7644 ->Equals(context.local(), CompileRun("Foo(1)"))
7645 .FromJust());
7646 CHECK(v8::Integer::New(CcTest::isolate(), 6)
7647 ->Equals(context.local(), CompileRun("Foo(2)"))
7648 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007649}
7650
7651
Leon Clarkee46be812010-01-19 14:06:41 +00007652THREADED_TEST(NativeFunctionConstructCall) {
7653 v8::RegisterExtension(new FunctionExtension());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007654 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007655 static const char* exts[1] = {"functiontest"};
Leon Clarkee46be812010-01-19 14:06:41 +00007656 v8::ExtensionConfiguration config(1, exts);
7657 LocalContext context(&config);
Leon Clarked91b9f72010-01-27 17:25:45 +00007658 for (int i = 0; i < 10; i++) {
7659 // Run a few times to ensure that allocation of objects doesn't
7660 // change behavior of a constructor function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007661 CHECK(v8::Integer::New(CcTest::isolate(), 8)
7662 ->Equals(context.local(), CompileRun("(new A()).data"))
7663 .FromJust());
7664 CHECK(v8::Integer::New(CcTest::isolate(), 7)
7665 ->Equals(context.local(), CompileRun("(new B()).data"))
7666 .FromJust());
7667 CHECK(v8::Integer::New(CcTest::isolate(), 6)
7668 ->Equals(context.local(), CompileRun("(new C()).data"))
7669 .FromJust());
Leon Clarked91b9f72010-01-27 17:25:45 +00007670 }
Leon Clarkee46be812010-01-19 14:06:41 +00007671}
7672
7673
Steve Blocka7e24c12009-10-30 11:49:00 +00007674static const char* last_location;
7675static const char* last_message;
7676void StoringErrorCallback(const char* location, const char* message) {
7677 if (last_location == NULL) {
7678 last_location = location;
7679 last_message = message;
7680 }
7681}
7682
7683
7684// ErrorReporting creates a circular extensions configuration and
7685// tests that the fatal error handler gets called. This renders V8
7686// unusable and therefore this test cannot be run in parallel.
7687TEST(ErrorReporting) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007688 CcTest::isolate()->SetFatalErrorHandler(StoringErrorCallback);
7689 static const char* aDeps[] = {"B"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007690 v8::RegisterExtension(new Extension("A", "", 1, aDeps));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007691 static const char* bDeps[] = {"A"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007692 v8::RegisterExtension(new Extension("B", "", 1, bDeps));
7693 last_location = NULL;
7694 v8::ExtensionConfiguration config(1, bDeps);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007695 v8::Local<Context> context = Context::New(CcTest::isolate(), &config);
Steve Blocka7e24c12009-10-30 11:49:00 +00007696 CHECK(context.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007697 CHECK(last_location);
Steve Blocka7e24c12009-10-30 11:49:00 +00007698}
7699
7700
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007701static void MissingScriptInfoMessageListener(v8::Local<v8::Message> message,
7702 v8::Local<Value> data) {
7703 v8::Isolate* isolate = CcTest::isolate();
7704 Local<Context> context = isolate->GetCurrentContext();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007705 CHECK(message->GetScriptOrigin().ResourceName()->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007706 CHECK(v8::Undefined(isolate)
7707 ->Equals(context, message->GetScriptOrigin().ResourceName())
7708 .FromJust());
7709 message->GetLineNumber(context).FromJust();
7710 message->GetSourceLine(context).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00007711}
7712
7713
7714THREADED_TEST(ErrorWithMissingScriptInfo) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007715 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007716 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007717 context->GetIsolate()->AddMessageListener(MissingScriptInfoMessageListener);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007718 CompileRun("throw Error()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007719 context->GetIsolate()->RemoveMessageListeners(
7720 MissingScriptInfoMessageListener);
Steve Blocka7e24c12009-10-30 11:49:00 +00007721}
7722
7723
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007724struct FlagAndPersistent {
7725 bool flag;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007726 v8::Global<v8::Object> handle;
Steve Blocka7e24c12009-10-30 11:49:00 +00007727};
7728
Steve Blocka7e24c12009-10-30 11:49:00 +00007729
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007730static void SetFlag(const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007731 data.GetParameter()->flag = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007732 data.GetParameter()->handle.Reset();
Steve Blockd0582a62009-12-15 09:54:21 +00007733}
7734
Steve Blockd0582a62009-12-15 09:54:21 +00007735
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007736static void IndependentWeakHandle(bool global_gc, bool interlinked) {
7737 v8::Isolate* iso = CcTest::isolate();
7738 v8::HandleScope scope(iso);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007739 v8::Local<Context> context = Context::New(iso);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007740 Context::Scope context_scope(context);
7741
7742 FlagAndPersistent object_a, object_b;
7743
7744 intptr_t big_heap_size;
7745
7746 {
7747 v8::HandleScope handle_scope(iso);
7748 Local<Object> a(v8::Object::New(iso));
7749 Local<Object> b(v8::Object::New(iso));
7750 object_a.handle.Reset(iso, a);
7751 object_b.handle.Reset(iso, b);
7752 if (interlinked) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007753 a->Set(context, v8_str("x"), b).FromJust();
7754 b->Set(context, v8_str("x"), a).FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007755 }
7756 if (global_gc) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007757 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007758 } else {
7759 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
7760 }
7761 // We are relying on this creating a big flag array and reserving the space
7762 // up front.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007763 v8::Local<Value> big_array = CompileRun("new Array(5000)");
7764 a->Set(context, v8_str("y"), big_array).FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007765 big_heap_size = CcTest::heap()->SizeOfObjects();
7766 }
7767
7768 object_a.flag = false;
7769 object_b.flag = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007770 object_a.handle.SetWeak(&object_a, &SetFlag,
7771 v8::WeakCallbackType::kParameter);
7772 object_b.handle.SetWeak(&object_b, &SetFlag,
7773 v8::WeakCallbackType::kParameter);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007774 CHECK(!object_b.handle.IsIndependent());
7775 object_a.handle.MarkIndependent();
7776 object_b.handle.MarkIndependent();
7777 CHECK(object_b.handle.IsIndependent());
7778 if (global_gc) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007779 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007780 } else {
7781 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
7782 }
7783 // A single GC should be enough to reclaim the memory, since we are using
7784 // phantom handles.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007785 CHECK_LT(CcTest::heap()->SizeOfObjects(), big_heap_size - 20000);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007786 CHECK(object_a.flag);
7787 CHECK(object_b.flag);
7788}
7789
7790
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007791TEST(IndependentWeakHandle) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007792 IndependentWeakHandle(false, false);
7793 IndependentWeakHandle(false, true);
7794 IndependentWeakHandle(true, false);
7795 IndependentWeakHandle(true, true);
7796}
7797
7798
7799class Trivial {
7800 public:
7801 explicit Trivial(int x) : x_(x) {}
7802
7803 int x() { return x_; }
7804 void set_x(int x) { x_ = x; }
7805
7806 private:
7807 int x_;
7808};
7809
7810
7811class Trivial2 {
7812 public:
7813 Trivial2(int x, int y) : y_(y), x_(x) {}
7814
7815 int x() { return x_; }
7816 void set_x(int x) { x_ = x; }
7817
7818 int y() { return y_; }
7819 void set_y(int y) { y_ = y; }
7820
7821 private:
7822 int y_;
7823 int x_;
7824};
7825
7826
7827void CheckInternalFields(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007828 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
7829 v8::Persistent<v8::Object>* handle = data.GetParameter();
7830 handle->Reset();
7831 Trivial* t1 = reinterpret_cast<Trivial*>(data.GetInternalField(0));
7832 Trivial2* t2 = reinterpret_cast<Trivial2*>(data.GetInternalField(1));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007833 CHECK_EQ(42, t1->x());
7834 CHECK_EQ(103, t2->x());
7835 t1->set_x(1729);
7836 t2->set_x(33550336);
7837}
7838
7839
7840void InternalFieldCallback(bool global_gc) {
7841 LocalContext env;
7842 v8::Isolate* isolate = env->GetIsolate();
7843 v8::HandleScope scope(isolate);
7844
7845 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
7846 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
7847 Trivial* t1;
7848 Trivial2* t2;
7849 instance_templ->SetInternalFieldCount(2);
7850 {
7851 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007852 Local<v8::Object> obj = templ->GetFunction(env.local())
7853 .ToLocalChecked()
7854 ->NewInstance(env.local())
7855 .ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007856 v8::Persistent<v8::Object> handle(isolate, obj);
7857 CHECK_EQ(2, obj->InternalFieldCount());
7858 CHECK(obj->GetInternalField(0)->IsUndefined());
7859 t1 = new Trivial(42);
7860 t2 = new Trivial2(103, 9);
7861
7862 obj->SetAlignedPointerInInternalField(0, t1);
7863 t1 = reinterpret_cast<Trivial*>(obj->GetAlignedPointerFromInternalField(0));
7864 CHECK_EQ(42, t1->x());
7865
7866 obj->SetAlignedPointerInInternalField(1, t2);
7867 t2 =
7868 reinterpret_cast<Trivial2*>(obj->GetAlignedPointerFromInternalField(1));
7869 CHECK_EQ(103, t2->x());
7870
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007871 handle.SetWeak<v8::Persistent<v8::Object>>(
7872 &handle, CheckInternalFields, v8::WeakCallbackType::kInternalFields);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007873 if (!global_gc) {
7874 handle.MarkIndependent();
7875 }
7876 }
7877 if (global_gc) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007878 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007879 } else {
7880 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
7881 }
7882
7883 CHECK_EQ(1729, t1->x());
7884 CHECK_EQ(33550336, t2->x());
7885
7886 delete t1;
7887 delete t2;
7888}
7889
7890
7891THREADED_TEST(InternalFieldCallback) {
7892 InternalFieldCallback(false);
7893 InternalFieldCallback(true);
7894}
7895
7896
7897static void ResetUseValueAndSetFlag(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007898 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007899 // Blink will reset the handle, and then use the other handle, so they
7900 // can't use the same backing slot.
7901 data.GetParameter()->handle.Reset();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007902 data.GetParameter()->flag = true;
7903}
7904
7905
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007906void v8::internal::HeapTester::ResetWeakHandle(bool global_gc) {
7907 using v8::Context;
7908 using v8::Local;
7909 using v8::Object;
7910
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007911 v8::Isolate* iso = CcTest::isolate();
7912 v8::HandleScope scope(iso);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007913 v8::Local<Context> context = Context::New(iso);
Steve Blockd0582a62009-12-15 09:54:21 +00007914 Context::Scope context_scope(context);
7915
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007916 FlagAndPersistent object_a, object_b;
Steve Blockd0582a62009-12-15 09:54:21 +00007917
7918 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007919 v8::HandleScope handle_scope(iso);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007920 Local<Object> a(v8::Object::New(iso));
7921 Local<Object> b(v8::Object::New(iso));
7922 object_a.handle.Reset(iso, a);
7923 object_b.handle.Reset(iso, b);
7924 if (global_gc) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007925 CcTest::heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007926 } else {
7927 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
7928 }
Steve Blockd0582a62009-12-15 09:54:21 +00007929 }
7930
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007931 object_a.flag = false;
7932 object_b.flag = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007933 object_a.handle.SetWeak(&object_a, &ResetUseValueAndSetFlag,
7934 v8::WeakCallbackType::kParameter);
7935 object_b.handle.SetWeak(&object_b, &ResetUseValueAndSetFlag,
7936 v8::WeakCallbackType::kParameter);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007937 if (!global_gc) {
7938 object_a.handle.MarkIndependent();
7939 object_b.handle.MarkIndependent();
7940 CHECK(object_b.handle.IsIndependent());
7941 }
7942 if (global_gc) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007943 CcTest::heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007944 } else {
7945 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
7946 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007947 CHECK(object_a.flag);
7948 CHECK(object_b.flag);
Ben Murdoch257744e2011-11-30 15:57:28 +00007949}
Steve Blockd0582a62009-12-15 09:54:21 +00007950
Ben Murdoch257744e2011-11-30 15:57:28 +00007951
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007952THREADED_HEAP_TEST(ResetWeakHandle) {
7953 v8::internal::HeapTester::ResetWeakHandle(false);
7954 v8::internal::HeapTester::ResetWeakHandle(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007955}
7956
7957
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007958static void InvokeScavenge() { CcTest::heap()->CollectGarbage(i::NEW_SPACE); }
Ben Murdoch257744e2011-11-30 15:57:28 +00007959
7960
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007961static void InvokeMarkSweep() { CcTest::heap()->CollectAllGarbage(); }
Ben Murdoch257744e2011-11-30 15:57:28 +00007962
7963
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007964static void ForceScavenge2(
7965 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007966 data.GetParameter()->flag = true;
Ben Murdoch257744e2011-11-30 15:57:28 +00007967 InvokeScavenge();
7968}
7969
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007970static void ForceScavenge1(
7971 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007972 data.GetParameter()->handle.Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007973 data.SetSecondPassCallback(ForceScavenge2);
7974}
7975
7976
7977static void ForceMarkSweep2(
7978 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007979 data.GetParameter()->flag = true;
Ben Murdoch257744e2011-11-30 15:57:28 +00007980 InvokeMarkSweep();
7981}
7982
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007983static void ForceMarkSweep1(
7984 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
7985 data.GetParameter()->handle.Reset();
7986 data.SetSecondPassCallback(ForceMarkSweep2);
7987}
7988
Ben Murdoch257744e2011-11-30 15:57:28 +00007989
7990THREADED_TEST(GCFromWeakCallbacks) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007991 v8::Isolate* isolate = CcTest::isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007992 v8::Locker locker(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007993 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007994 v8::Local<Context> context = Context::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +00007995 Context::Scope context_scope(context);
7996
7997 static const int kNumberOfGCTypes = 2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007998 typedef v8::WeakCallbackInfo<FlagAndPersistent>::Callback Callback;
7999 Callback gc_forcing_callback[kNumberOfGCTypes] = {&ForceScavenge1,
8000 &ForceMarkSweep1};
Ben Murdoch257744e2011-11-30 15:57:28 +00008001
8002 typedef void (*GCInvoker)();
8003 GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
8004
8005 for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
8006 for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008007 FlagAndPersistent object;
Ben Murdoch257744e2011-11-30 15:57:28 +00008008 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008009 v8::HandleScope handle_scope(isolate);
8010 object.handle.Reset(isolate, v8::Object::New(isolate));
Ben Murdoch257744e2011-11-30 15:57:28 +00008011 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008012 object.flag = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008013 object.handle.SetWeak(&object, gc_forcing_callback[inner_gc],
8014 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008015 object.handle.MarkIndependent();
Ben Murdoch257744e2011-11-30 15:57:28 +00008016 invoke_gc[outer_gc]();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008017 EmptyMessageQueues(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008018 CHECK(object.flag);
Ben Murdoch257744e2011-11-30 15:57:28 +00008019 }
Steve Blockd0582a62009-12-15 09:54:21 +00008020 }
Ben Murdoch257744e2011-11-30 15:57:28 +00008021}
8022
8023
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008024v8::Local<Function> args_fun;
Steve Blocka7e24c12009-10-30 11:49:00 +00008025
8026
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008027static void ArgumentsTestCallback(
8028 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008029 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008030 v8::Isolate* isolate = args.GetIsolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008031 Local<Context> context = isolate->GetCurrentContext();
Steve Blocka7e24c12009-10-30 11:49:00 +00008032 CHECK_EQ(3, args.Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008033 CHECK(v8::Integer::New(isolate, 1)->Equals(context, args[0]).FromJust());
8034 CHECK(v8::Integer::New(isolate, 2)->Equals(context, args[1]).FromJust());
8035 CHECK(v8::Integer::New(isolate, 3)->Equals(context, args[2]).FromJust());
8036 CHECK(v8::Undefined(isolate)->Equals(context, args[3]).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008037 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008038 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +00008039}
8040
8041
8042THREADED_TEST(Arguments) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008043 v8::Isolate* isolate = CcTest::isolate();
8044 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008045 v8::Local<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008046 global->Set(v8_str("f"),
8047 v8::FunctionTemplate::New(isolate, ArgumentsTestCallback));
Steve Blocka7e24c12009-10-30 11:49:00 +00008048 LocalContext context(NULL, global);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008049 args_fun = context->Global()
8050 ->Get(context.local(), v8_str("f"))
8051 .ToLocalChecked()
8052 .As<Function>();
8053 v8_compile("f(1, 2, 3)")->Run(context.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00008054}
8055
8056
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008057static int p_getter_count;
8058static int p_getter_count2;
Steve Blocka7e24c12009-10-30 11:49:00 +00008059
8060
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008061static void PGetter(Local<Name> name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008062 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008063 ApiTestFuzzer::Fuzz();
8064 p_getter_count++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008065 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
8066 v8::Local<v8::Object> global = context->Global();
8067 CHECK(
8068 info.Holder()
8069 ->Equals(context, global->Get(context, v8_str("o1")).ToLocalChecked())
8070 .FromJust());
8071 if (name->Equals(context, v8_str("p1")).FromJust()) {
8072 CHECK(info.This()
8073 ->Equals(context,
8074 global->Get(context, v8_str("o1")).ToLocalChecked())
8075 .FromJust());
8076 } else if (name->Equals(context, v8_str("p2")).FromJust()) {
8077 CHECK(info.This()
8078 ->Equals(context,
8079 global->Get(context, v8_str("o2")).ToLocalChecked())
8080 .FromJust());
8081 } else if (name->Equals(context, v8_str("p3")).FromJust()) {
8082 CHECK(info.This()
8083 ->Equals(context,
8084 global->Get(context, v8_str("o3")).ToLocalChecked())
8085 .FromJust());
8086 } else if (name->Equals(context, v8_str("p4")).FromJust()) {
8087 CHECK(info.This()
8088 ->Equals(context,
8089 global->Get(context, v8_str("o4")).ToLocalChecked())
8090 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008091 }
Steve Blocka7e24c12009-10-30 11:49:00 +00008092}
8093
8094
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008095static void RunHolderTest(v8::Local<v8::ObjectTemplate> obj) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008096 ApiTestFuzzer::Fuzz();
8097 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008098 CHECK(context->Global()
8099 ->Set(context.local(), v8_str("o1"),
8100 obj->NewInstance(context.local()).ToLocalChecked())
8101 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008102 CompileRun(
8103 "o1.__proto__ = { };"
8104 "var o2 = { __proto__: o1 };"
8105 "var o3 = { __proto__: o2 };"
8106 "var o4 = { __proto__: o3 };"
8107 "for (var i = 0; i < 10; i++) o4.p4;"
8108 "for (var i = 0; i < 10; i++) o3.p3;"
8109 "for (var i = 0; i < 10; i++) o2.p2;"
8110 "for (var i = 0; i < 10; i++) o1.p1;");
8111}
8112
8113
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008114static void PGetter2(Local<Name> name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008115 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008116 ApiTestFuzzer::Fuzz();
8117 p_getter_count2++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008118 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
8119 v8::Local<v8::Object> global = context->Global();
8120 CHECK(
8121 info.Holder()
8122 ->Equals(context, global->Get(context, v8_str("o1")).ToLocalChecked())
8123 .FromJust());
8124 if (name->Equals(context, v8_str("p1")).FromJust()) {
8125 CHECK(info.This()
8126 ->Equals(context,
8127 global->Get(context, v8_str("o1")).ToLocalChecked())
8128 .FromJust());
8129 } else if (name->Equals(context, v8_str("p2")).FromJust()) {
8130 CHECK(info.This()
8131 ->Equals(context,
8132 global->Get(context, v8_str("o2")).ToLocalChecked())
8133 .FromJust());
8134 } else if (name->Equals(context, v8_str("p3")).FromJust()) {
8135 CHECK(info.This()
8136 ->Equals(context,
8137 global->Get(context, v8_str("o3")).ToLocalChecked())
8138 .FromJust());
8139 } else if (name->Equals(context, v8_str("p4")).FromJust()) {
8140 CHECK(info.This()
8141 ->Equals(context,
8142 global->Get(context, v8_str("o4")).ToLocalChecked())
8143 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008144 }
Steve Blocka7e24c12009-10-30 11:49:00 +00008145}
8146
8147
8148THREADED_TEST(GetterHolders) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008149 v8::Isolate* isolate = CcTest::isolate();
8150 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008151 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00008152 obj->SetAccessor(v8_str("p1"), PGetter);
8153 obj->SetAccessor(v8_str("p2"), PGetter);
8154 obj->SetAccessor(v8_str("p3"), PGetter);
8155 obj->SetAccessor(v8_str("p4"), PGetter);
8156 p_getter_count = 0;
8157 RunHolderTest(obj);
8158 CHECK_EQ(40, p_getter_count);
8159}
8160
8161
8162THREADED_TEST(PreInterceptorHolders) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008163 v8::Isolate* isolate = CcTest::isolate();
8164 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008165 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008166 obj->SetHandler(v8::NamedPropertyHandlerConfiguration(PGetter2));
Steve Blocka7e24c12009-10-30 11:49:00 +00008167 p_getter_count2 = 0;
8168 RunHolderTest(obj);
8169 CHECK_EQ(40, p_getter_count2);
8170}
8171
8172
8173THREADED_TEST(ObjectInstantiation) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008174 v8::Isolate* isolate = CcTest::isolate();
8175 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008176 v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00008177 templ->SetAccessor(v8_str("t"), PGetter2);
8178 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008179 CHECK(context->Global()
8180 ->Set(context.local(), v8_str("o"),
8181 templ->NewInstance(context.local()).ToLocalChecked())
8182 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008183 for (int i = 0; i < 100; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008184 v8::HandleScope inner_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008185 v8::Local<v8::Object> obj =
8186 templ->NewInstance(context.local()).ToLocalChecked();
8187 CHECK(!obj->Equals(context.local(), context->Global()
8188 ->Get(context.local(), v8_str("o"))
8189 .ToLocalChecked())
8190 .FromJust());
8191 CHECK(
8192 context->Global()->Set(context.local(), v8_str("o2"), obj).FromJust());
8193 v8::Local<Value> value = CompileRun("o.__proto__ === o2.__proto__");
8194 CHECK(v8::True(isolate)->Equals(context.local(), value).FromJust());
8195 CHECK(context->Global()->Set(context.local(), v8_str("o"), obj).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008196 }
8197}
8198
8199
Ben Murdochb0fe1622011-05-05 13:52:32 +01008200static int StrCmp16(uint16_t* a, uint16_t* b) {
8201 while (true) {
8202 if (*a == 0 && *b == 0) return 0;
8203 if (*a != *b) return 0 + *a - *b;
8204 a++;
8205 b++;
8206 }
8207}
8208
8209
8210static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
8211 while (true) {
8212 if (n-- == 0) return 0;
8213 if (*a == 0 && *b == 0) return 0;
8214 if (*a != *b) return 0 + *a - *b;
8215 a++;
8216 b++;
8217 }
8218}
8219
8220
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008221int GetUtf8Length(Local<String> str) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008222 int len = str->Utf8Length();
8223 if (len < 0) {
8224 i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008225 i::String::Flatten(istr);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008226 len = str->Utf8Length();
8227 }
8228 return len;
8229}
8230
8231
Steve Blocka7e24c12009-10-30 11:49:00 +00008232THREADED_TEST(StringWrite) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008233 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008234 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008235 v8::Local<String> str = v8_str("abcde");
Ben Murdochb0fe1622011-05-05 13:52:32 +01008236 // abc<Icelandic eth><Unicode snowman>.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008237 v8::Local<String> str2 = v8_str("abc\303\260\342\230\203");
8238 v8::Local<String> str3 =
8239 v8::String::NewFromUtf8(context->GetIsolate(), "abc\0def",
8240 v8::NewStringType::kNormal, 7)
8241 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008242 // "ab" + lead surrogate + "cd" + trail surrogate + "ef"
8243 uint16_t orphans[8] = { 0x61, 0x62, 0xd800, 0x63, 0x64, 0xdc00, 0x65, 0x66 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008244 v8::Local<String> orphans_str =
8245 v8::String::NewFromTwoByte(context->GetIsolate(), orphans,
8246 v8::NewStringType::kNormal, 8)
8247 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008248 // single lead surrogate
8249 uint16_t lead[1] = { 0xd800 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008250 v8::Local<String> lead_str =
8251 v8::String::NewFromTwoByte(context->GetIsolate(), lead,
8252 v8::NewStringType::kNormal, 1)
8253 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008254 // single trail surrogate
8255 uint16_t trail[1] = { 0xdc00 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008256 v8::Local<String> trail_str =
8257 v8::String::NewFromTwoByte(context->GetIsolate(), trail,
8258 v8::NewStringType::kNormal, 1)
8259 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008260 // surrogate pair
8261 uint16_t pair[2] = { 0xd800, 0xdc00 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008262 v8::Local<String> pair_str =
8263 v8::String::NewFromTwoByte(context->GetIsolate(), pair,
8264 v8::NewStringType::kNormal, 2)
8265 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008266 const int kStride = 4; // Must match stride in for loops in JS below.
8267 CompileRun(
8268 "var left = '';"
8269 "for (var i = 0; i < 0xd800; i += 4) {"
8270 " left = left + String.fromCharCode(i);"
8271 "}");
8272 CompileRun(
8273 "var right = '';"
8274 "for (var i = 0; i < 0xd800; i += 4) {"
8275 " right = String.fromCharCode(i) + right;"
8276 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008277 v8::Local<v8::Object> global = context->Global();
8278 Local<String> left_tree = global->Get(context.local(), v8_str("left"))
8279 .ToLocalChecked()
8280 .As<String>();
8281 Local<String> right_tree = global->Get(context.local(), v8_str("right"))
8282 .ToLocalChecked()
8283 .As<String>();
Ben Murdochb0fe1622011-05-05 13:52:32 +01008284
8285 CHECK_EQ(5, str2->Length());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008286 CHECK_EQ(0xd800 / kStride, left_tree->Length());
8287 CHECK_EQ(0xd800 / kStride, right_tree->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +00008288
8289 char buf[100];
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008290 char utf8buf[0xd800 * 3];
Ben Murdochb0fe1622011-05-05 13:52:32 +01008291 uint16_t wbuf[100];
Steve Blocka7e24c12009-10-30 11:49:00 +00008292 int len;
Ben Murdochb0fe1622011-05-05 13:52:32 +01008293 int charlen;
8294
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008295 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008296 len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008297 CHECK_EQ(9, len);
8298 CHECK_EQ(5, charlen);
8299 CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008300
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008301 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008302 len = str2->WriteUtf8(utf8buf, 8, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008303 CHECK_EQ(8, len);
8304 CHECK_EQ(5, charlen);
8305 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008306
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008307 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008308 len = str2->WriteUtf8(utf8buf, 7, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008309 CHECK_EQ(5, len);
8310 CHECK_EQ(4, charlen);
8311 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008312
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008313 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008314 len = str2->WriteUtf8(utf8buf, 6, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008315 CHECK_EQ(5, len);
8316 CHECK_EQ(4, charlen);
8317 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008318
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008319 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008320 len = str2->WriteUtf8(utf8buf, 5, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008321 CHECK_EQ(5, len);
8322 CHECK_EQ(4, charlen);
8323 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008324
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008325 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008326 len = str2->WriteUtf8(utf8buf, 4, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008327 CHECK_EQ(3, len);
8328 CHECK_EQ(3, charlen);
8329 CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008330
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008331 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008332 len = str2->WriteUtf8(utf8buf, 3, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008333 CHECK_EQ(3, len);
8334 CHECK_EQ(3, charlen);
8335 CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008336
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008337 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008338 len = str2->WriteUtf8(utf8buf, 2, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008339 CHECK_EQ(2, len);
8340 CHECK_EQ(2, charlen);
8341 CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
Steve Blocka7e24c12009-10-30 11:49:00 +00008342
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008343 // allow orphan surrogates by default
8344 memset(utf8buf, 0x1, 1000);
8345 len = orphans_str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
8346 CHECK_EQ(13, len);
8347 CHECK_EQ(8, charlen);
8348 CHECK_EQ(0, strcmp(utf8buf, "ab\355\240\200cd\355\260\200ef"));
8349
8350 // replace orphan surrogates with unicode replacement character
8351 memset(utf8buf, 0x1, 1000);
8352 len = orphans_str->WriteUtf8(utf8buf,
8353 sizeof(utf8buf),
8354 &charlen,
8355 String::REPLACE_INVALID_UTF8);
8356 CHECK_EQ(13, len);
8357 CHECK_EQ(8, charlen);
8358 CHECK_EQ(0, strcmp(utf8buf, "ab\357\277\275cd\357\277\275ef"));
8359
8360 // replace single lead surrogate with unicode replacement character
8361 memset(utf8buf, 0x1, 1000);
8362 len = lead_str->WriteUtf8(utf8buf,
8363 sizeof(utf8buf),
8364 &charlen,
8365 String::REPLACE_INVALID_UTF8);
8366 CHECK_EQ(4, len);
8367 CHECK_EQ(1, charlen);
8368 CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
8369
8370 // replace single trail surrogate with unicode replacement character
8371 memset(utf8buf, 0x1, 1000);
8372 len = trail_str->WriteUtf8(utf8buf,
8373 sizeof(utf8buf),
8374 &charlen,
8375 String::REPLACE_INVALID_UTF8);
8376 CHECK_EQ(4, len);
8377 CHECK_EQ(1, charlen);
8378 CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
8379
8380 // do not replace / write anything if surrogate pair does not fit the buffer
8381 // space
8382 memset(utf8buf, 0x1, 1000);
8383 len = pair_str->WriteUtf8(utf8buf,
8384 3,
8385 &charlen,
8386 String::REPLACE_INVALID_UTF8);
8387 CHECK_EQ(0, len);
8388 CHECK_EQ(0, charlen);
8389
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008390 memset(utf8buf, 0x1, sizeof(utf8buf));
8391 len = GetUtf8Length(left_tree);
8392 int utf8_expected =
8393 (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride;
8394 CHECK_EQ(utf8_expected, len);
8395 len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
8396 CHECK_EQ(utf8_expected, len);
8397 CHECK_EQ(0xd800 / kStride, charlen);
8398 CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
8399 CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
8400 CHECK_EQ(0xc0 - kStride,
8401 static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
8402 CHECK_EQ(1, utf8buf[utf8_expected]);
8403
8404 memset(utf8buf, 0x1, sizeof(utf8buf));
8405 len = GetUtf8Length(right_tree);
8406 CHECK_EQ(utf8_expected, len);
8407 len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
8408 CHECK_EQ(utf8_expected, len);
8409 CHECK_EQ(0xd800 / kStride, charlen);
8410 CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0]));
8411 CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1]));
8412 CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2]));
8413 CHECK_EQ(1, utf8buf[utf8_expected]);
8414
Steve Blocka7e24c12009-10-30 11:49:00 +00008415 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008416 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008417 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
Steve Block44f0eee2011-05-26 01:26:41 +01008418 CHECK_EQ(5, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008419 len = str->Write(wbuf);
Steve Block44f0eee2011-05-26 01:26:41 +01008420 CHECK_EQ(5, len);
8421 CHECK_EQ(0, strcmp("abcde", buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008422 uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
Steve Block44f0eee2011-05-26 01:26:41 +01008423 CHECK_EQ(0, StrCmp16(answer1, wbuf));
Steve Blocka7e24c12009-10-30 11:49:00 +00008424
8425 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008426 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008427 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 4);
Steve Block44f0eee2011-05-26 01:26:41 +01008428 CHECK_EQ(4, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008429 len = str->Write(wbuf, 0, 4);
Steve Block44f0eee2011-05-26 01:26:41 +01008430 CHECK_EQ(4, len);
8431 CHECK_EQ(0, strncmp("abcd\1", buf, 5));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008432 uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
Steve Block44f0eee2011-05-26 01:26:41 +01008433 CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
Steve Blocka7e24c12009-10-30 11:49:00 +00008434
8435 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008436 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008437 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 5);
Steve Block44f0eee2011-05-26 01:26:41 +01008438 CHECK_EQ(5, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008439 len = str->Write(wbuf, 0, 5);
Steve Block44f0eee2011-05-26 01:26:41 +01008440 CHECK_EQ(5, len);
8441 CHECK_EQ(0, strncmp("abcde\1", buf, 6));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008442 uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
Steve Block44f0eee2011-05-26 01:26:41 +01008443 CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
Steve Blocka7e24c12009-10-30 11:49:00 +00008444
8445 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008446 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008447 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 6);
Steve Block44f0eee2011-05-26 01:26:41 +01008448 CHECK_EQ(5, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008449 len = str->Write(wbuf, 0, 6);
Steve Block44f0eee2011-05-26 01:26:41 +01008450 CHECK_EQ(5, len);
8451 CHECK_EQ(0, strcmp("abcde", buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008452 uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
Steve Block44f0eee2011-05-26 01:26:41 +01008453 CHECK_EQ(0, StrCmp16(answer4, wbuf));
Steve Blocka7e24c12009-10-30 11:49:00 +00008454
8455 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008456 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008457 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, -1);
Steve Block44f0eee2011-05-26 01:26:41 +01008458 CHECK_EQ(1, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008459 len = str->Write(wbuf, 4, -1);
Steve Block44f0eee2011-05-26 01:26:41 +01008460 CHECK_EQ(1, len);
8461 CHECK_EQ(0, strcmp("e", buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008462 uint16_t answer5[] = {'e', '\0'};
Steve Block44f0eee2011-05-26 01:26:41 +01008463 CHECK_EQ(0, StrCmp16(answer5, wbuf));
Steve Blocka7e24c12009-10-30 11:49:00 +00008464
8465 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008466 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008467 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 6);
Steve Block44f0eee2011-05-26 01:26:41 +01008468 CHECK_EQ(1, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008469 len = str->Write(wbuf, 4, 6);
Steve Block44f0eee2011-05-26 01:26:41 +01008470 CHECK_EQ(1, len);
8471 CHECK_EQ(0, strcmp("e", buf));
8472 CHECK_EQ(0, StrCmp16(answer5, wbuf));
Steve Blocka7e24c12009-10-30 11:49:00 +00008473
8474 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008475 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008476 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 1);
Steve Block44f0eee2011-05-26 01:26:41 +01008477 CHECK_EQ(1, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008478 len = str->Write(wbuf, 4, 1);
Steve Block44f0eee2011-05-26 01:26:41 +01008479 CHECK_EQ(1, len);
8480 CHECK_EQ(0, strncmp("e\1", buf, 2));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008481 uint16_t answer6[] = {'e', 0x101};
Steve Block44f0eee2011-05-26 01:26:41 +01008482 CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008483
8484 memset(buf, 0x1, sizeof(buf));
8485 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008486 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 3, 1);
Steve Block44f0eee2011-05-26 01:26:41 +01008487 CHECK_EQ(1, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008488 len = str->Write(wbuf, 3, 1);
Steve Block44f0eee2011-05-26 01:26:41 +01008489 CHECK_EQ(1, len);
8490 CHECK_EQ(0, strncmp("d\1", buf, 2));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008491 uint16_t answer7[] = {'d', 0x101};
Steve Block44f0eee2011-05-26 01:26:41 +01008492 CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
Ben Murdoch69a99ed2011-11-30 16:03:39 +00008493
8494 memset(wbuf, 0x1, sizeof(wbuf));
8495 wbuf[5] = 'X';
8496 len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION);
8497 CHECK_EQ(5, len);
8498 CHECK_EQ('X', wbuf[5]);
8499 uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
8500 uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
8501 CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
8502 CHECK_NE(0, StrCmp16(answer8b, wbuf));
8503 wbuf[5] = '\0';
8504 CHECK_EQ(0, StrCmp16(answer8b, wbuf));
8505
8506 memset(buf, 0x1, sizeof(buf));
8507 buf[5] = 'X';
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008508 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf),
8509 0,
8510 6,
8511 String::NO_NULL_TERMINATION);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00008512 CHECK_EQ(5, len);
8513 CHECK_EQ('X', buf[5]);
8514 CHECK_EQ(0, strncmp("abcde", buf, 5));
8515 CHECK_NE(0, strcmp("abcde", buf));
8516 buf[5] = '\0';
8517 CHECK_EQ(0, strcmp("abcde", buf));
8518
8519 memset(utf8buf, 0x1, sizeof(utf8buf));
8520 utf8buf[8] = 'X';
8521 len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
8522 String::NO_NULL_TERMINATION);
8523 CHECK_EQ(8, len);
8524 CHECK_EQ('X', utf8buf[8]);
8525 CHECK_EQ(5, charlen);
8526 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
8527 CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
8528 utf8buf[8] = '\0';
8529 CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008530
8531 memset(utf8buf, 0x1, sizeof(utf8buf));
8532 utf8buf[5] = 'X';
8533 len = str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
8534 String::NO_NULL_TERMINATION);
8535 CHECK_EQ(5, len);
8536 CHECK_EQ('X', utf8buf[5]); // Test that the sixth character is untouched.
8537 CHECK_EQ(5, charlen);
8538 utf8buf[5] = '\0';
8539 CHECK_EQ(0, strcmp(utf8buf, "abcde"));
8540
8541 memset(buf, 0x1, sizeof(buf));
8542 len = str3->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
8543 CHECK_EQ(7, len);
8544 CHECK_EQ(0, strcmp("abc", buf));
8545 CHECK_EQ(0, buf[3]);
8546 CHECK_EQ(0, strcmp("def", buf + 4));
8547
8548 CHECK_EQ(0, str->WriteOneByte(NULL, 0, 0, String::NO_NULL_TERMINATION));
8549 CHECK_EQ(0, str->WriteUtf8(NULL, 0, 0, String::NO_NULL_TERMINATION));
8550 CHECK_EQ(0, str->Write(NULL, 0, 0, String::NO_NULL_TERMINATION));
Steve Blocka7e24c12009-10-30 11:49:00 +00008551}
8552
8553
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008554static void Utf16Helper(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008555 LocalContext& context, // NOLINT
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008556 const char* name,
8557 const char* lengths_name,
8558 int len) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008559 Local<v8::Array> a = Local<v8::Array>::Cast(
8560 context->Global()->Get(context.local(), v8_str(name)).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008561 Local<v8::Array> alens =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008562 Local<v8::Array>::Cast(context->Global()
8563 ->Get(context.local(), v8_str(lengths_name))
8564 .ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008565 for (int i = 0; i < len; i++) {
8566 Local<v8::String> string =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008567 Local<v8::String>::Cast(a->Get(context.local(), i).ToLocalChecked());
8568 Local<v8::Number> expected_len = Local<v8::Number>::Cast(
8569 alens->Get(context.local(), i).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008570 int length = GetUtf8Length(string);
8571 CHECK_EQ(static_cast<int>(expected_len->Value()), length);
8572 }
8573}
8574
8575
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008576THREADED_TEST(Utf16) {
8577 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008578 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008579 CompileRun(
8580 "var pad = '01234567890123456789';"
8581 "var p = [];"
8582 "var plens = [20, 3, 3];"
8583 "p.push('01234567890123456789');"
8584 "var lead = 0xd800;"
8585 "var trail = 0xdc00;"
8586 "p.push(String.fromCharCode(0xd800));"
8587 "p.push(String.fromCharCode(0xdc00));"
8588 "var a = [];"
8589 "var b = [];"
8590 "var c = [];"
8591 "var alens = [];"
8592 "for (var i = 0; i < 3; i++) {"
8593 " p[1] = String.fromCharCode(lead++);"
8594 " for (var j = 0; j < 3; j++) {"
8595 " p[2] = String.fromCharCode(trail++);"
8596 " a.push(p[i] + p[j]);"
8597 " b.push(p[i] + p[j]);"
8598 " c.push(p[i] + p[j]);"
8599 " alens.push(plens[i] + plens[j]);"
8600 " }"
8601 "}"
8602 "alens[5] -= 2;" // Here the surrogate pairs match up.
8603 "var a2 = [];"
8604 "var b2 = [];"
8605 "var c2 = [];"
8606 "var a2lens = [];"
8607 "for (var m = 0; m < 9; m++) {"
8608 " for (var n = 0; n < 9; n++) {"
8609 " a2.push(a[m] + a[n]);"
8610 " b2.push(b[m] + b[n]);"
8611 " var newc = 'x' + c[m] + c[n] + 'y';"
8612 " c2.push(newc.substring(1, newc.length - 1));"
8613 " var utf = alens[m] + alens[n];" // And here.
8614 // The 'n's that start with 0xdc.. are 6-8
8615 // The 'm's that end with 0xd8.. are 1, 4 and 7
8616 " if ((m % 3) == 1 && n >= 6) utf -= 2;"
8617 " a2lens.push(utf);"
8618 " }"
8619 "}");
8620 Utf16Helper(context, "a", "alens", 9);
8621 Utf16Helper(context, "a2", "a2lens", 81);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008622}
8623
8624
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008625static bool SameSymbol(Local<String> s1, Local<String> s2) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008626 i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1));
8627 i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2));
8628 return *is1 == *is2;
8629}
8630
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008631
8632THREADED_TEST(Utf16Symbol) {
8633 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008634 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008635
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008636 Local<String> symbol1 =
8637 v8::String::NewFromUtf8(context->GetIsolate(), "abc",
8638 v8::NewStringType::kInternalized)
8639 .ToLocalChecked();
8640 Local<String> symbol2 =
8641 v8::String::NewFromUtf8(context->GetIsolate(), "abc",
8642 v8::NewStringType::kInternalized)
8643 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008644 CHECK(SameSymbol(symbol1, symbol2));
8645
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008646 CompileRun(
8647 "var sym0 = 'benedictus';"
8648 "var sym0b = 'S\303\270ren';"
8649 "var sym1 = '\355\240\201\355\260\207';"
8650 "var sym2 = '\360\220\220\210';"
8651 "var sym3 = 'x\355\240\201\355\260\207';"
8652 "var sym4 = 'x\360\220\220\210';"
8653 "if (sym1.length != 2) throw sym1;"
8654 "if (sym1.charCodeAt(1) != 0xdc07) throw sym1.charCodeAt(1);"
8655 "if (sym2.length != 2) throw sym2;"
8656 "if (sym2.charCodeAt(1) != 0xdc08) throw sym2.charCodeAt(2);"
8657 "if (sym3.length != 3) throw sym3;"
8658 "if (sym3.charCodeAt(2) != 0xdc07) throw sym1.charCodeAt(2);"
8659 "if (sym4.length != 3) throw sym4;"
8660 "if (sym4.charCodeAt(2) != 0xdc08) throw sym2.charCodeAt(2);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008661 Local<String> sym0 =
8662 v8::String::NewFromUtf8(context->GetIsolate(), "benedictus",
8663 v8::NewStringType::kInternalized)
8664 .ToLocalChecked();
8665 Local<String> sym0b =
8666 v8::String::NewFromUtf8(context->GetIsolate(), "S\303\270ren",
8667 v8::NewStringType::kInternalized)
8668 .ToLocalChecked();
8669 Local<String> sym1 =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008670 v8::String::NewFromUtf8(context->GetIsolate(), "\355\240\201\355\260\207",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008671 v8::NewStringType::kInternalized)
8672 .ToLocalChecked();
8673 Local<String> sym2 =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008674 v8::String::NewFromUtf8(context->GetIsolate(), "\360\220\220\210",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008675 v8::NewStringType::kInternalized)
8676 .ToLocalChecked();
8677 Local<String> sym3 = v8::String::NewFromUtf8(context->GetIsolate(),
8678 "x\355\240\201\355\260\207",
8679 v8::NewStringType::kInternalized)
8680 .ToLocalChecked();
8681 Local<String> sym4 =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008682 v8::String::NewFromUtf8(context->GetIsolate(), "x\360\220\220\210",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008683 v8::NewStringType::kInternalized)
8684 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008685 v8::Local<v8::Object> global = context->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008686 Local<Value> s0 =
8687 global->Get(context.local(), v8_str("sym0")).ToLocalChecked();
8688 Local<Value> s0b =
8689 global->Get(context.local(), v8_str("sym0b")).ToLocalChecked();
8690 Local<Value> s1 =
8691 global->Get(context.local(), v8_str("sym1")).ToLocalChecked();
8692 Local<Value> s2 =
8693 global->Get(context.local(), v8_str("sym2")).ToLocalChecked();
8694 Local<Value> s3 =
8695 global->Get(context.local(), v8_str("sym3")).ToLocalChecked();
8696 Local<Value> s4 =
8697 global->Get(context.local(), v8_str("sym4")).ToLocalChecked();
8698 CHECK(SameSymbol(sym0, Local<String>::Cast(s0)));
8699 CHECK(SameSymbol(sym0b, Local<String>::Cast(s0b)));
8700 CHECK(SameSymbol(sym1, Local<String>::Cast(s1)));
8701 CHECK(SameSymbol(sym2, Local<String>::Cast(s2)));
8702 CHECK(SameSymbol(sym3, Local<String>::Cast(s3)));
8703 CHECK(SameSymbol(sym4, Local<String>::Cast(s4)));
8704}
8705
8706
8707THREADED_TEST(Utf16MissingTrailing) {
8708 LocalContext context;
8709 v8::HandleScope scope(context->GetIsolate());
8710
8711 // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
8712 int size = 1024 * 64;
8713 uint8_t* buffer = new uint8_t[size];
8714 for (int i = 0; i < size; i += 4) {
8715 buffer[i] = 0xf0;
8716 buffer[i + 1] = 0x9d;
8717 buffer[i + 2] = 0x80;
8718 buffer[i + 3] = 0x9e;
8719 }
8720
8721 // Now invoke the decoder without last 3 bytes
8722 v8::Local<v8::String> str =
8723 v8::String::NewFromUtf8(
8724 context->GetIsolate(), reinterpret_cast<char*>(buffer),
8725 v8::NewStringType::kNormal, size - 3).ToLocalChecked();
8726 USE(str);
8727 delete[] buffer;
8728}
8729
8730
8731THREADED_TEST(Utf16Trailing3Byte) {
8732 LocalContext context;
8733 v8::HandleScope scope(context->GetIsolate());
8734
8735 // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
8736 int size = 1024 * 63;
8737 uint8_t* buffer = new uint8_t[size];
8738 for (int i = 0; i < size; i += 3) {
8739 buffer[i] = 0xe2;
8740 buffer[i + 1] = 0x80;
8741 buffer[i + 2] = 0xa6;
8742 }
8743
8744 // Now invoke the decoder without last 3 bytes
8745 v8::Local<v8::String> str =
8746 v8::String::NewFromUtf8(
8747 context->GetIsolate(), reinterpret_cast<char*>(buffer),
8748 v8::NewStringType::kNormal, size).ToLocalChecked();
8749
8750 v8::String::Value value(str);
8751 CHECK_EQ(value.length(), size / 3);
8752 CHECK_EQ((*value)[value.length() - 1], 0x2026);
8753
8754 delete[] buffer;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008755}
8756
8757
Steve Blocka7e24c12009-10-30 11:49:00 +00008758THREADED_TEST(ToArrayIndex) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008759 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008760 v8::Isolate* isolate = context->GetIsolate();
8761 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00008762
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008763 v8::Local<String> str = v8_str("42");
8764 v8::MaybeLocal<v8::Uint32> index = str->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008765 CHECK(!index.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008766 CHECK_EQ(42.0,
8767 index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008768 str = v8_str("42asdf");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008769 index = str->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008770 CHECK(index.IsEmpty());
8771 str = v8_str("-42");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008772 index = str->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008773 CHECK(index.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008774 str = v8_str("4294967294");
8775 index = str->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008776 CHECK(!index.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008777 CHECK_EQ(4294967294.0,
8778 index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
8779 v8::Local<v8::Number> num = v8::Number::New(isolate, 1);
8780 index = num->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008781 CHECK(!index.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008782 CHECK_EQ(1.0,
8783 index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008784 num = v8::Number::New(isolate, -1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008785 index = num->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008786 CHECK(index.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008787 v8::Local<v8::Object> obj = v8::Object::New(isolate);
8788 index = obj->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008789 CHECK(index.IsEmpty());
8790}
8791
8792
8793THREADED_TEST(ErrorConstruction) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008794 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008795 v8::HandleScope scope(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00008796
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008797 v8::Local<String> foo = v8_str("foo");
8798 v8::Local<String> message = v8_str("message");
8799 v8::Local<Value> range_error = v8::Exception::RangeError(foo);
Steve Blocka7e24c12009-10-30 11:49:00 +00008800 CHECK(range_error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008801 CHECK(range_error.As<v8::Object>()
8802 ->Get(context.local(), message)
8803 .ToLocalChecked()
8804 ->Equals(context.local(), foo)
8805 .FromJust());
8806 v8::Local<Value> reference_error = v8::Exception::ReferenceError(foo);
Steve Blocka7e24c12009-10-30 11:49:00 +00008807 CHECK(reference_error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008808 CHECK(reference_error.As<v8::Object>()
8809 ->Get(context.local(), message)
8810 .ToLocalChecked()
8811 ->Equals(context.local(), foo)
8812 .FromJust());
8813 v8::Local<Value> syntax_error = v8::Exception::SyntaxError(foo);
Steve Blocka7e24c12009-10-30 11:49:00 +00008814 CHECK(syntax_error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008815 CHECK(syntax_error.As<v8::Object>()
8816 ->Get(context.local(), message)
8817 .ToLocalChecked()
8818 ->Equals(context.local(), foo)
8819 .FromJust());
8820 v8::Local<Value> type_error = v8::Exception::TypeError(foo);
Steve Blocka7e24c12009-10-30 11:49:00 +00008821 CHECK(type_error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008822 CHECK(type_error.As<v8::Object>()
8823 ->Get(context.local(), message)
8824 .ToLocalChecked()
8825 ->Equals(context.local(), foo)
8826 .FromJust());
8827 v8::Local<Value> error = v8::Exception::Error(foo);
Steve Blocka7e24c12009-10-30 11:49:00 +00008828 CHECK(error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008829 CHECK(error.As<v8::Object>()
8830 ->Get(context.local(), message)
8831 .ToLocalChecked()
8832 ->Equals(context.local(), foo)
8833 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008834}
8835
8836
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008837static void ThrowV8Exception(const v8::FunctionCallbackInfo<v8::Value>& info) {
8838 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008839 v8::Local<String> foo = v8_str("foo");
8840 v8::Local<String> message = v8_str("message");
8841 v8::Local<Value> error = v8::Exception::Error(foo);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008842 CHECK(error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008843 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
8844 CHECK(error.As<v8::Object>()
8845 ->Get(context, message)
8846 .ToLocalChecked()
8847 ->Equals(context, foo)
8848 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008849 info.GetIsolate()->ThrowException(error);
8850 info.GetReturnValue().SetUndefined();
8851}
8852
8853
8854THREADED_TEST(ExceptionCreateMessage) {
8855 LocalContext context;
8856 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008857 v8::Local<String> foo_str = v8_str("foo");
8858 v8::Local<String> message_str = v8_str("message");
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008859
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008860 context->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008861
8862 Local<v8::FunctionTemplate> fun =
8863 v8::FunctionTemplate::New(context->GetIsolate(), ThrowV8Exception);
8864 v8::Local<v8::Object> global = context->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008865 CHECK(global->Set(context.local(), v8_str("throwV8Exception"),
8866 fun->GetFunction(context.local()).ToLocalChecked())
8867 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008868
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008869 TryCatch try_catch(context->GetIsolate());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008870 CompileRun(
8871 "function f1() {\n"
8872 " throwV8Exception();\n"
8873 "};\n"
8874 "f1();");
8875 CHECK(try_catch.HasCaught());
8876
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008877 v8::Local<v8::Value> error = try_catch.Exception();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008878 CHECK(error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008879 CHECK(error.As<v8::Object>()
8880 ->Get(context.local(), message_str)
8881 .ToLocalChecked()
8882 ->Equals(context.local(), foo_str)
8883 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008884
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008885 v8::Local<v8::Message> message =
8886 v8::Exception::CreateMessage(context->GetIsolate(), error);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008887 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008888 CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
8889 CHECK_EQ(2, message->GetStartColumn(context.local()).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008890
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008891 v8::Local<v8::StackTrace> stackTrace = message->GetStackTrace();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008892 CHECK(!stackTrace.IsEmpty());
8893 CHECK_EQ(2, stackTrace->GetFrameCount());
8894
8895 stackTrace = v8::Exception::GetStackTrace(error);
8896 CHECK(!stackTrace.IsEmpty());
8897 CHECK_EQ(2, stackTrace->GetFrameCount());
8898
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008899 context->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(false);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008900
8901 // Now check message location when SetCaptureStackTraceForUncaughtExceptions
8902 // is false.
8903 try_catch.Reset();
8904
8905 CompileRun(
8906 "function f2() {\n"
8907 " return throwV8Exception();\n"
8908 "};\n"
8909 "f2();");
8910 CHECK(try_catch.HasCaught());
8911
8912 error = try_catch.Exception();
8913 CHECK(error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008914 CHECK(error.As<v8::Object>()
8915 ->Get(context.local(), message_str)
8916 .ToLocalChecked()
8917 ->Equals(context.local(), foo_str)
8918 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008919
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008920 message = v8::Exception::CreateMessage(context->GetIsolate(), error);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008921 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008922 CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
8923 CHECK_EQ(9, message->GetStartColumn(context.local()).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008924
8925 // Should be empty stack trace.
8926 stackTrace = message->GetStackTrace();
8927 CHECK(stackTrace.IsEmpty());
8928 CHECK(v8::Exception::GetStackTrace(error).IsEmpty());
8929}
8930
8931
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008932THREADED_TEST(ExceptionCreateMessageLength) {
8933 LocalContext context;
8934 v8::HandleScope scope(context->GetIsolate());
8935
8936 // Test that the message is not truncated.
8937 TryCatch try_catch(context->GetIsolate());
8938 CompileRun(
8939 "var message = 'm';"
8940 "while (message.length < 1000) message += message;"
8941 "throw message;");
8942 CHECK(try_catch.HasCaught());
8943
8944 CHECK_LT(1000, try_catch.Message()->Get()->Length());
8945}
8946
8947
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008948static void YGetter(Local<String> name,
8949 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008950 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008951 info.GetReturnValue().Set(v8_num(10));
Steve Blocka7e24c12009-10-30 11:49:00 +00008952}
8953
8954
8955static void YSetter(Local<String> name,
8956 Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008957 const v8::PropertyCallbackInfo<void>& info) {
8958 Local<Object> this_obj = Local<Object>::Cast(info.This());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008959 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
8960 if (this_obj->Has(context, name).FromJust())
8961 this_obj->Delete(context, name).FromJust();
8962 CHECK(this_obj->Set(context, name, value).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008963}
8964
8965
8966THREADED_TEST(DeleteAccessor) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008967 v8::Isolate* isolate = CcTest::isolate();
8968 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008969 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00008970 obj->SetAccessor(v8_str("y"), YGetter, YSetter);
8971 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008972 v8::Local<v8::Object> holder =
8973 obj->NewInstance(context.local()).ToLocalChecked();
8974 CHECK(context->Global()
8975 ->Set(context.local(), v8_str("holder"), holder)
8976 .FromJust());
8977 v8::Local<Value> result =
8978 CompileRun("holder.y = 11; holder.y = 12; holder.y");
8979 CHECK_EQ(12u, result->Uint32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008980}
8981
8982
Steve Blocka7e24c12009-10-30 11:49:00 +00008983static int trouble_nesting = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008984static void TroubleCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008985 ApiTestFuzzer::Fuzz();
8986 trouble_nesting++;
8987
8988 // Call a JS function that throws an uncaught exception.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008989 Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
8990 Local<v8::Object> arg_this = context->Global();
8991 Local<Value> trouble_callee =
8992 (trouble_nesting == 3)
8993 ? arg_this->Get(context, v8_str("trouble_callee")).ToLocalChecked()
8994 : arg_this->Get(context, v8_str("trouble_caller")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00008995 CHECK(trouble_callee->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008996 args.GetReturnValue().Set(Function::Cast(*trouble_callee)
8997 ->Call(context, arg_this, 0, NULL)
8998 .FromMaybe(v8::Local<v8::Value>()));
Steve Blocka7e24c12009-10-30 11:49:00 +00008999}
9000
9001
9002static int report_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009003static void ApiUncaughtExceptionTestListener(v8::Local<v8::Message>,
9004 v8::Local<Value>) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009005 report_count++;
9006}
9007
9008
9009// Counts uncaught exceptions, but other tests running in parallel
9010// also have uncaught exceptions.
9011TEST(ApiUncaughtException) {
9012 report_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00009013 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009014 v8::Isolate* isolate = env->GetIsolate();
9015 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009016 isolate->AddMessageListener(ApiUncaughtExceptionTestListener);
Steve Blocka7e24c12009-10-30 11:49:00 +00009017
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009018 Local<v8::FunctionTemplate> fun =
9019 v8::FunctionTemplate::New(isolate, TroubleCallback);
Steve Blocka7e24c12009-10-30 11:49:00 +00009020 v8::Local<v8::Object> global = env->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009021 CHECK(global->Set(env.local(), v8_str("trouble"),
9022 fun->GetFunction(env.local()).ToLocalChecked())
9023 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009024
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009025 CompileRun(
9026 "function trouble_callee() {"
9027 " var x = null;"
9028 " return x.foo;"
9029 "};"
9030 "function trouble_caller() {"
9031 " trouble();"
9032 "};");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009033 Local<Value> trouble =
9034 global->Get(env.local(), v8_str("trouble")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009035 CHECK(trouble->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009036 Local<Value> trouble_callee =
9037 global->Get(env.local(), v8_str("trouble_callee")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009038 CHECK(trouble_callee->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009039 Local<Value> trouble_caller =
9040 global->Get(env.local(), v8_str("trouble_caller")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009041 CHECK(trouble_caller->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009042 Function::Cast(*trouble_caller)
9043 ->Call(env.local(), global, 0, NULL)
9044 .FromMaybe(v8::Local<v8::Value>());
Steve Blocka7e24c12009-10-30 11:49:00 +00009045 CHECK_EQ(1, report_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009046 isolate->RemoveMessageListeners(ApiUncaughtExceptionTestListener);
Steve Blocka7e24c12009-10-30 11:49:00 +00009047}
9048
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009049
9050TEST(ApiUncaughtExceptionInObjectObserve) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009051 v8::internal::FLAG_harmony_object_observe = true;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009052 v8::internal::FLAG_stack_size = 150;
9053 report_count = 0;
9054 LocalContext env;
9055 v8::Isolate* isolate = env->GetIsolate();
9056 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009057 isolate->AddMessageListener(ApiUncaughtExceptionTestListener);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009058 CompileRun(
9059 "var obj = {};"
9060 "var observe_count = 0;"
9061 "function observer1() { ++observe_count; };"
9062 "function observer2() { ++observe_count; };"
9063 "function observer_throws() { throw new Error(); };"
9064 "function stack_overflow() { return (function f(x) { f(x+1); })(0); };"
9065 "Object.observe(obj, observer_throws.bind());"
9066 "Object.observe(obj, observer1);"
9067 "Object.observe(obj, stack_overflow);"
9068 "Object.observe(obj, observer2);"
9069 "Object.observe(obj, observer_throws.bind());"
9070 "obj.foo = 'bar';");
9071 CHECK_EQ(3, report_count);
9072 ExpectInt32("observe_count", 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009073 isolate->RemoveMessageListeners(ApiUncaughtExceptionTestListener);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009074}
9075
9076
Leon Clarke4515c472010-02-03 11:58:03 +00009077static const char* script_resource_name = "ExceptionInNativeScript.js";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009078static void ExceptionInNativeScriptTestListener(v8::Local<v8::Message> message,
9079 v8::Local<Value>) {
9080 v8::Local<v8::Value> name_val = message->GetScriptOrigin().ResourceName();
Leon Clarke4515c472010-02-03 11:58:03 +00009081 CHECK(!name_val.IsEmpty() && name_val->IsString());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009082 v8::String::Utf8Value name(message->GetScriptOrigin().ResourceName());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009083 CHECK_EQ(0, strcmp(script_resource_name, *name));
9084 v8::Local<v8::Context> context =
9085 v8::Isolate::GetCurrent()->GetCurrentContext();
9086 CHECK_EQ(3, message->GetLineNumber(context).FromJust());
9087 v8::String::Utf8Value source_line(
9088 message->GetSourceLine(context).ToLocalChecked());
9089 CHECK_EQ(0, strcmp(" new o.foo();", *source_line));
Leon Clarke4515c472010-02-03 11:58:03 +00009090}
9091
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009092
Leon Clarke4515c472010-02-03 11:58:03 +00009093TEST(ExceptionInNativeScript) {
Leon Clarke4515c472010-02-03 11:58:03 +00009094 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009095 v8::Isolate* isolate = env->GetIsolate();
9096 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009097 isolate->AddMessageListener(ExceptionInNativeScriptTestListener);
Leon Clarke4515c472010-02-03 11:58:03 +00009098
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009099 Local<v8::FunctionTemplate> fun =
9100 v8::FunctionTemplate::New(isolate, TroubleCallback);
Leon Clarke4515c472010-02-03 11:58:03 +00009101 v8::Local<v8::Object> global = env->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009102 CHECK(global->Set(env.local(), v8_str("trouble"),
9103 fun->GetFunction(env.local()).ToLocalChecked())
9104 .FromJust());
Leon Clarke4515c472010-02-03 11:58:03 +00009105
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009106 CompileRunWithOrigin(
9107 "function trouble() {\n"
9108 " var o = {};\n"
9109 " new o.foo();\n"
9110 "};",
9111 script_resource_name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009112 Local<Value> trouble =
9113 global->Get(env.local(), v8_str("trouble")).ToLocalChecked();
Leon Clarke4515c472010-02-03 11:58:03 +00009114 CHECK(trouble->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009115 CHECK(Function::Cast(*trouble)->Call(env.local(), global, 0, NULL).IsEmpty());
9116 isolate->RemoveMessageListeners(ExceptionInNativeScriptTestListener);
Leon Clarke4515c472010-02-03 11:58:03 +00009117}
9118
Steve Blocka7e24c12009-10-30 11:49:00 +00009119
9120TEST(CompilationErrorUsingTryCatchHandler) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009121 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009122 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009123 v8::TryCatch try_catch(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009124 v8_compile("This doesn't &*&@#$&*^ compile.");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009125 CHECK(*try_catch.Exception());
Steve Blocka7e24c12009-10-30 11:49:00 +00009126 CHECK(try_catch.HasCaught());
9127}
9128
9129
9130TEST(TryCatchFinallyUsingTryCatchHandler) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009131 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009132 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009133 v8::TryCatch try_catch(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009134 CompileRun("try { throw ''; } catch (e) {}");
Steve Blocka7e24c12009-10-30 11:49:00 +00009135 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009136 CompileRun("try { throw ''; } finally {}");
Steve Blocka7e24c12009-10-30 11:49:00 +00009137 CHECK(try_catch.HasCaught());
9138 try_catch.Reset();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009139 CompileRun(
9140 "(function() {"
9141 "try { throw ''; } finally { return; }"
9142 "})()");
Steve Blocka7e24c12009-10-30 11:49:00 +00009143 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009144 CompileRun(
9145 "(function()"
9146 " { try { throw ''; } finally { throw 0; }"
9147 "})()");
Steve Blocka7e24c12009-10-30 11:49:00 +00009148 CHECK(try_catch.HasCaught());
9149}
9150
9151
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009152void CEvaluate(const v8::FunctionCallbackInfo<v8::Value>& args) {
9153 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009154 CompileRun(args[0]
9155 ->ToString(args.GetIsolate()->GetCurrentContext())
9156 .ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009157}
9158
9159
9160TEST(TryCatchFinallyStoresMessageUsingTryCatchHandler) {
9161 v8::Isolate* isolate = CcTest::isolate();
9162 v8::HandleScope scope(isolate);
9163 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
9164 templ->Set(v8_str("CEvaluate"),
9165 v8::FunctionTemplate::New(isolate, CEvaluate));
9166 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009167 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009168 CompileRun("try {"
9169 " CEvaluate('throw 1;');"
9170 "} finally {"
9171 "}");
9172 CHECK(try_catch.HasCaught());
9173 CHECK(!try_catch.Message().IsEmpty());
9174 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009175 CHECK_EQ(0, strcmp(*exception_value, "1"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009176 try_catch.Reset();
9177 CompileRun("try {"
9178 " CEvaluate('throw 1;');"
9179 "} finally {"
9180 " throw 2;"
9181 "}");
9182 CHECK(try_catch.HasCaught());
9183 CHECK(!try_catch.Message().IsEmpty());
9184 String::Utf8Value finally_exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009185 CHECK_EQ(0, strcmp(*finally_exception_value, "2"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009186}
9187
9188
9189// For use within the TestSecurityHandler() test.
9190static bool g_security_callback_result = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009191static bool SecurityTestCallback(Local<v8::Context> accessing_context,
Ben Murdoch097c5b22016-05-18 11:27:45 +01009192 Local<v8::Object> accessed_object,
9193 Local<v8::Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009194 printf("a\n");
Ben Murdoch097c5b22016-05-18 11:27:45 +01009195 CHECK(!data.IsEmpty() && data->IsInt32());
9196 CHECK_EQ(42, data->Int32Value(accessing_context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009197 return g_security_callback_result;
9198}
9199
9200
Steve Blocka7e24c12009-10-30 11:49:00 +00009201// SecurityHandler can't be run twice
9202TEST(SecurityHandler) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009203 v8::Isolate* isolate = CcTest::isolate();
9204 v8::HandleScope scope0(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009205 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009206 v8::ObjectTemplate::New(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01009207 global_template->SetAccessCheckCallback(SecurityTestCallback, v8_num(42));
Steve Blocka7e24c12009-10-30 11:49:00 +00009208 // Create an environment
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009209 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
Steve Blocka7e24c12009-10-30 11:49:00 +00009210 context0->Enter();
9211
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009212 v8::Local<v8::Object> global0 = context0->Global();
9213 v8::Local<Script> script0 = v8_compile("foo = 111");
9214 script0->Run(context0).ToLocalChecked();
9215 CHECK(global0->Set(context0, v8_str("0"), v8_num(999)).FromJust());
9216 v8::Local<Value> foo0 =
9217 global0->Get(context0, v8_str("foo")).ToLocalChecked();
9218 CHECK_EQ(111, foo0->Int32Value(context0).FromJust());
9219 v8::Local<Value> z0 = global0->Get(context0, v8_str("0")).ToLocalChecked();
9220 CHECK_EQ(999, z0->Int32Value(context0).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009221
9222 // Create another environment, should fail security checks.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009223 v8::HandleScope scope1(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00009224
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009225 v8::Local<Context> context1 = Context::New(isolate, NULL, global_template);
Steve Blocka7e24c12009-10-30 11:49:00 +00009226 context1->Enter();
9227
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009228 v8::Local<v8::Object> global1 = context1->Global();
9229 global1->Set(context1, v8_str("othercontext"), global0).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00009230 // This set will fail the security check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009231 v8::Local<Script> script1 =
9232 v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
9233 CHECK(script1->Run(context1).IsEmpty());
9234 g_security_callback_result = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00009235 // This read will pass the security check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009236 v8::Local<Value> foo1 =
9237 global0->Get(context1, v8_str("foo")).ToLocalChecked();
9238 CHECK_EQ(111, foo1->Int32Value(context0).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009239 // This read will pass the security check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009240 v8::Local<Value> z1 = global0->Get(context1, v8_str("0")).ToLocalChecked();
9241 CHECK_EQ(999, z1->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009242
9243 // Create another environment, should pass security checks.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009244 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009245 v8::HandleScope scope2(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00009246 LocalContext context2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009247 v8::Local<v8::Object> global2 = context2->Global();
9248 CHECK(global2->Set(context2.local(), v8_str("othercontext"), global0)
9249 .FromJust());
9250 v8::Local<Script> script2 =
Steve Blocka7e24c12009-10-30 11:49:00 +00009251 v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009252 script2->Run(context2.local()).ToLocalChecked();
9253 v8::Local<Value> foo2 =
9254 global0->Get(context2.local(), v8_str("foo")).ToLocalChecked();
9255 CHECK_EQ(333, foo2->Int32Value(context2.local()).FromJust());
9256 v8::Local<Value> z2 =
9257 global0->Get(context2.local(), v8_str("0")).ToLocalChecked();
9258 CHECK_EQ(888, z2->Int32Value(context2.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009259 }
9260
9261 context1->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +00009262 context0->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +00009263}
9264
9265
9266THREADED_TEST(SecurityChecks) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009267 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009268 v8::HandleScope handle_scope(env1->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009269 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009270
9271 Local<Value> foo = v8_str("foo");
9272 Local<Value> bar = v8_str("bar");
9273
9274 // Set to the same domain.
9275 env1->SetSecurityToken(foo);
9276
9277 // Create a function in env1.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009278 CompileRun("spy=function(){return spy;}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009279 Local<Value> spy =
9280 env1->Global()->Get(env1.local(), v8_str("spy")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009281 CHECK(spy->IsFunction());
9282
9283 // Create another function accessing global objects.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009284 CompileRun("spy2=function(){return new this.Array();}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009285 Local<Value> spy2 =
9286 env1->Global()->Get(env1.local(), v8_str("spy2")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009287 CHECK(spy2->IsFunction());
9288
9289 // Switch to env2 in the same domain and invoke spy on env2.
9290 {
9291 env2->SetSecurityToken(foo);
9292 // Enter env2
9293 Context::Scope scope_env2(env2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009294 Local<Value> result = Function::Cast(*spy)
9295 ->Call(env2, env2->Global(), 0, NULL)
9296 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009297 CHECK(result->IsFunction());
9298 }
9299
9300 {
9301 env2->SetSecurityToken(bar);
9302 Context::Scope scope_env2(env2);
9303
9304 // Call cross_domain_call, it should throw an exception
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009305 v8::TryCatch try_catch(env1->GetIsolate());
9306 CHECK(Function::Cast(*spy2)->Call(env2, env2->Global(), 0, NULL).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009307 CHECK(try_catch.HasCaught());
9308 }
Steve Blocka7e24c12009-10-30 11:49:00 +00009309}
9310
9311
9312// Regression test case for issue 1183439.
9313THREADED_TEST(SecurityChecksForPrototypeChain) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009314 LocalContext current;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009315 v8::HandleScope scope(current->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009316 v8::Local<Context> other = Context::New(current->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009317
9318 // Change context to be able to get to the Object function in the
9319 // other context without hitting the security checks.
9320 v8::Local<Value> other_object;
9321 { Context::Scope scope(other);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009322 other_object =
9323 other->Global()->Get(other, v8_str("Object")).ToLocalChecked();
9324 CHECK(other->Global()->Set(other, v8_num(42), v8_num(87)).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009325 }
9326
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009327 CHECK(current->Global()
9328 ->Set(current.local(), v8_str("other"), other->Global())
9329 .FromJust());
9330 CHECK(v8_compile("other")
9331 ->Run(current.local())
9332 .ToLocalChecked()
9333 ->Equals(current.local(), other->Global())
9334 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009335
9336 // Make sure the security check fails here and we get an undefined
9337 // result instead of getting the Object function. Repeat in a loop
9338 // to make sure to exercise the IC code.
9339 v8::Local<Script> access_other0 = v8_compile("other.Object");
9340 v8::Local<Script> access_other1 = v8_compile("other[42]");
9341 for (int i = 0; i < 5; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009342 CHECK(access_other0->Run(current.local()).IsEmpty());
9343 CHECK(access_other1->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009344 }
9345
9346 // Create an object that has 'other' in its prototype chain and make
9347 // sure we cannot access the Object function indirectly through
9348 // that. Repeat in a loop to make sure to exercise the IC code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009349 v8_compile(
9350 "function F() { };"
9351 "F.prototype = other;"
9352 "var f = new F();")
9353 ->Run(current.local())
9354 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009355 v8::Local<Script> access_f0 = v8_compile("f.Object");
9356 v8::Local<Script> access_f1 = v8_compile("f[42]");
9357 for (int j = 0; j < 5; j++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009358 CHECK(access_f0->Run(current.local()).IsEmpty());
9359 CHECK(access_f1->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009360 }
9361
9362 // Now it gets hairy: Set the prototype for the other global object
9363 // to be the current global object. The prototype chain for 'f' now
9364 // goes through 'other' but ends up in the current global object.
9365 { Context::Scope scope(other);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009366 CHECK(other->Global()
9367 ->Set(other, v8_str("__proto__"), current->Global())
9368 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009369 }
9370 // Set a named and an index property on the current global
9371 // object. To force the lookup to go through the other global object,
9372 // the properties must not exist in the other global object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009373 CHECK(current->Global()
9374 ->Set(current.local(), v8_str("foo"), v8_num(100))
9375 .FromJust());
9376 CHECK(current->Global()
9377 ->Set(current.local(), v8_num(99), v8_num(101))
9378 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009379 // Try to read the properties from f and make sure that the access
9380 // gets stopped by the security checks on the other global object.
9381 Local<Script> access_f2 = v8_compile("f.foo");
9382 Local<Script> access_f3 = v8_compile("f[99]");
9383 for (int k = 0; k < 5; k++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009384 CHECK(access_f2->Run(current.local()).IsEmpty());
9385 CHECK(access_f3->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009386 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009387}
9388
9389
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009390static bool security_check_with_gc_called;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009391
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009392static bool SecurityTestCallbackWithGC(Local<v8::Context> accessing_context,
Ben Murdoch097c5b22016-05-18 11:27:45 +01009393 Local<v8::Object> accessed_object,
9394 Local<v8::Value> data) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009395 CcTest::heap()->CollectAllGarbage();
9396 security_check_with_gc_called = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009397 return true;
9398}
9399
9400
9401TEST(SecurityTestGCAllowed) {
9402 v8::Isolate* isolate = CcTest::isolate();
9403 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009404 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009405 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009406 object_template->SetAccessCheckCallback(SecurityTestCallbackWithGC);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009407
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009408 v8::Local<Context> context = Context::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009409 v8::Context::Scope context_scope(context);
9410
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009411 CHECK(context->Global()
9412 ->Set(context, v8_str("obj"),
9413 object_template->NewInstance(context).ToLocalChecked())
9414 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009415
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009416 security_check_with_gc_called = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009417 CompileRun("obj[0] = new String(1002);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009418 CHECK(security_check_with_gc_called);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009419
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009420 security_check_with_gc_called = false;
9421 CHECK(CompileRun("obj[0]")
9422 ->ToString(context)
9423 .ToLocalChecked()
9424 ->Equals(context, v8_str("1002"))
9425 .FromJust());
9426 CHECK(security_check_with_gc_called);
Steve Blocka7e24c12009-10-30 11:49:00 +00009427}
9428
9429
9430THREADED_TEST(CrossDomainDelete) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009431 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009432 v8::HandleScope handle_scope(env1->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009433 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009434
9435 Local<Value> foo = v8_str("foo");
9436 Local<Value> bar = v8_str("bar");
9437
9438 // Set to the same domain.
9439 env1->SetSecurityToken(foo);
9440 env2->SetSecurityToken(foo);
9441
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009442 CHECK(
9443 env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
9444 CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009445
9446 // Change env2 to a different domain and delete env1.prop.
9447 env2->SetSecurityToken(bar);
9448 {
9449 Context::Scope scope_env2(env2);
9450 Local<Value> result =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009451 CompileRun("delete env1.prop");
9452 CHECK(result.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009453 }
9454
9455 // Check that env1.prop still exists.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009456 Local<Value> v =
9457 env1->Global()->Get(env1.local(), v8_str("prop")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009458 CHECK(v->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009459 CHECK_EQ(3, v->Int32Value(env1.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009460}
9461
9462
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009463THREADED_TEST(CrossDomainPropertyIsEnumerable) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009464 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009465 v8::HandleScope handle_scope(env1->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009466 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009467
9468 Local<Value> foo = v8_str("foo");
9469 Local<Value> bar = v8_str("bar");
9470
9471 // Set to the same domain.
9472 env1->SetSecurityToken(foo);
9473 env2->SetSecurityToken(foo);
9474
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009475 CHECK(
9476 env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
9477 CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009478
9479 // env1.prop is enumerable in env2.
9480 Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
9481 {
9482 Context::Scope scope_env2(env2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009483 Local<Value> result = CompileRun(test);
Steve Blocka7e24c12009-10-30 11:49:00 +00009484 CHECK(result->IsTrue());
9485 }
9486
9487 // Change env2 to a different domain and test again.
9488 env2->SetSecurityToken(bar);
9489 {
9490 Context::Scope scope_env2(env2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009491 Local<Value> result = CompileRun(test);
9492 CHECK(result.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009493 }
Steve Blocka7e24c12009-10-30 11:49:00 +00009494}
9495
9496
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009497THREADED_TEST(CrossDomainFor) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009498 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009499 v8::HandleScope handle_scope(env1->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009500 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009501
9502 Local<Value> foo = v8_str("foo");
9503 Local<Value> bar = v8_str("bar");
9504
9505 // Set to the same domain.
9506 env1->SetSecurityToken(foo);
9507 env2->SetSecurityToken(foo);
9508
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009509 CHECK(
9510 env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
9511 CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
9512
9513 // Change env2 to a different domain and set env1's global object
9514 // as the __proto__ of an object in env2 and enumerate properties
9515 // in for-in. It shouldn't enumerate properties on env1's global
9516 // object. It shouldn't throw either, just silently ignore them.
9517 env2->SetSecurityToken(bar);
9518 {
9519 Context::Scope scope_env2(env2);
9520 Local<Value> result = CompileRun(
9521 "(function() {"
9522 " try {"
9523 " for (var p in env1) {"
9524 " if (p == 'prop') return false;"
9525 " }"
9526 " return true;"
9527 " } catch (e) {"
9528 " return false;"
9529 " }"
9530 "})()");
9531 CHECK(result->IsTrue());
9532 }
9533}
9534
9535
9536THREADED_TEST(CrossDomainForInOnPrototype) {
9537 LocalContext env1;
9538 v8::HandleScope handle_scope(env1->GetIsolate());
9539 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
9540
9541 Local<Value> foo = v8_str("foo");
9542 Local<Value> bar = v8_str("bar");
9543
9544 // Set to the same domain.
9545 env1->SetSecurityToken(foo);
9546 env2->SetSecurityToken(foo);
9547
9548 CHECK(
9549 env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
9550 CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009551
9552 // Change env2 to a different domain and set env1's global object
9553 // as the __proto__ of an object in env2 and enumerate properties
9554 // in for-in. It shouldn't enumerate properties on env1's global
9555 // object.
9556 env2->SetSecurityToken(bar);
9557 {
9558 Context::Scope scope_env2(env2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009559 Local<Value> result = CompileRun(
9560 "(function() {"
9561 " var obj = { '__proto__': env1 };"
9562 " try {"
9563 " for (var p in obj) {"
9564 " if (p == 'prop') return false;"
9565 " }"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009566 " return true;"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009567 " } catch (e) {"
9568 " return false;"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009569 " }"
9570 "})()");
Steve Blocka7e24c12009-10-30 11:49:00 +00009571 CHECK(result->IsTrue());
9572 }
Steve Blocka7e24c12009-10-30 11:49:00 +00009573}
9574
9575
9576TEST(ContextDetachGlobal) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009577 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009578 v8::HandleScope handle_scope(env1->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009579 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009580
Steve Blocka7e24c12009-10-30 11:49:00 +00009581
9582 Local<Value> foo = v8_str("foo");
9583
9584 // Set to the same domain.
9585 env1->SetSecurityToken(foo);
9586 env2->SetSecurityToken(foo);
9587
9588 // Enter env2
9589 env2->Enter();
9590
Andrei Popescu74b3c142010-03-29 12:03:09 +01009591 // Create a function in env2 and add a reference to it in env1.
Steve Blocka7e24c12009-10-30 11:49:00 +00009592 Local<v8::Object> global2 = env2->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009593 CHECK(global2->Set(env2, v8_str("prop"),
9594 v8::Integer::New(env2->GetIsolate(), 1))
9595 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009596 CompileRun("function getProp() {return prop;}");
9597
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009598 CHECK(env1->Global()
9599 ->Set(env1.local(), v8_str("getProp"),
9600 global2->Get(env2, v8_str("getProp")).ToLocalChecked())
9601 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009602
Andrei Popescu74b3c142010-03-29 12:03:09 +01009603 // Detach env2's global, and reuse the global object of env2
Steve Blocka7e24c12009-10-30 11:49:00 +00009604 env2->Exit();
9605 env2->DetachGlobal();
Steve Blocka7e24c12009-10-30 11:49:00 +00009606
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009607 v8::Local<Context> env3 = Context::New(
9608 env1->GetIsolate(), 0, v8::Local<v8::ObjectTemplate>(), global2);
Steve Blocka7e24c12009-10-30 11:49:00 +00009609 env3->SetSecurityToken(v8_str("bar"));
Steve Blocka7e24c12009-10-30 11:49:00 +00009610
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009611 env3->Enter();
Steve Blocka7e24c12009-10-30 11:49:00 +00009612 Local<v8::Object> global3 = env3->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009613 CHECK(global2->Equals(env3, global3).FromJust());
9614 CHECK(global3->Get(env3, v8_str("prop")).ToLocalChecked()->IsUndefined());
9615 CHECK(global3->Get(env3, v8_str("getProp")).ToLocalChecked()->IsUndefined());
9616 CHECK(global3->Set(env3, v8_str("prop"),
9617 v8::Integer::New(env3->GetIsolate(), -1))
9618 .FromJust());
9619 CHECK(global3->Set(env3, v8_str("prop2"),
9620 v8::Integer::New(env3->GetIsolate(), 2))
9621 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009622 env3->Exit();
9623
9624 // Call getProp in env1, and it should return the value 1
9625 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009626 Local<v8::Object> global1 = env1->Global();
9627 Local<Value> get_prop =
9628 global1->Get(env1.local(), v8_str("getProp")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009629 CHECK(get_prop->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009630 v8::TryCatch try_catch(env1->GetIsolate());
9631 Local<Value> r = Function::Cast(*get_prop)
9632 ->Call(env1.local(), global1, 0, NULL)
9633 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009634 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009635 CHECK_EQ(1, r->Int32Value(env1.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009636 }
9637
9638 // Check that env3 is not accessible from env1
9639 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009640 v8::MaybeLocal<Value> r = global3->Get(env1.local(), v8_str("prop2"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009641 CHECK(r.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009642 }
Steve Blocka7e24c12009-10-30 11:49:00 +00009643}
9644
9645
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009646TEST(DetachGlobal) {
Andrei Popescu74b3c142010-03-29 12:03:09 +01009647 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009648 v8::HandleScope scope(env1->GetIsolate());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009649
9650 // Create second environment.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009651 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009652
9653 Local<Value> foo = v8_str("foo");
9654
9655 // Set same security token for env1 and env2.
9656 env1->SetSecurityToken(foo);
9657 env2->SetSecurityToken(foo);
9658
9659 // Create a property on the global object in env2.
9660 {
9661 v8::Context::Scope scope(env2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009662 CHECK(env2->Global()
9663 ->Set(env2, v8_str("p"), v8::Integer::New(env2->GetIsolate(), 42))
9664 .FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009665 }
9666
9667 // Create a reference to env2 global from env1 global.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009668 CHECK(env1->Global()
9669 ->Set(env1.local(), v8_str("other"), env2->Global())
9670 .FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009671
9672 // Check that we have access to other.p in env2 from env1.
9673 Local<Value> result = CompileRun("other.p");
9674 CHECK(result->IsInt32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009675 CHECK_EQ(42, result->Int32Value(env1.local()).FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009676
9677 // Hold on to global from env2 and detach global from env2.
9678 Local<v8::Object> global2 = env2->Global();
9679 env2->DetachGlobal();
9680
9681 // Check that the global has been detached. No other.p property can
9682 // be found.
9683 result = CompileRun("other.p");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009684 CHECK(result.IsEmpty());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009685
9686 // Reuse global2 for env3.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009687 v8::Local<Context> env3 = Context::New(
9688 env1->GetIsolate(), 0, v8::Local<v8::ObjectTemplate>(), global2);
9689 CHECK(global2->Equals(env1.local(), env3->Global()).FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009690
9691 // Start by using the same security token for env3 as for env1 and env2.
9692 env3->SetSecurityToken(foo);
9693
9694 // Create a property on the global object in env3.
9695 {
9696 v8::Context::Scope scope(env3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009697 CHECK(env3->Global()
9698 ->Set(env3, v8_str("p"), v8::Integer::New(env3->GetIsolate(), 24))
9699 .FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009700 }
9701
9702 // Check that other.p is now the property in env3 and that we have access.
9703 result = CompileRun("other.p");
9704 CHECK(result->IsInt32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009705 CHECK_EQ(24, result->Int32Value(env3).FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009706
9707 // Change security token for env3 to something different from env1 and env2.
9708 env3->SetSecurityToken(v8_str("bar"));
9709
9710 // Check that we do not have access to other.p in env1. |other| is now
9711 // the global object for env3 which has a different security token,
9712 // so access should be blocked.
9713 result = CompileRun("other.p");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009714 CHECK(result.IsEmpty());
9715}
Andrei Popescu74b3c142010-03-29 12:03:09 +01009716
Andrei Popescu74b3c142010-03-29 12:03:09 +01009717
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009718void GetThisX(const v8::FunctionCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009719 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009720 info.GetReturnValue().Set(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009721 context->Global()->Get(context, v8_str("x")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009722}
Andrei Popescu74b3c142010-03-29 12:03:09 +01009723
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009724
9725TEST(DetachedAccesses) {
9726 LocalContext env1;
9727 v8::HandleScope scope(env1->GetIsolate());
9728
9729 // Create second environment.
9730 Local<ObjectTemplate> inner_global_template =
9731 FunctionTemplate::New(env1->GetIsolate())->InstanceTemplate();
9732 inner_global_template ->SetAccessorProperty(
9733 v8_str("this_x"), FunctionTemplate::New(env1->GetIsolate(), GetThisX));
9734 v8::Local<Context> env2 =
9735 Context::New(env1->GetIsolate(), NULL, inner_global_template);
9736
9737 Local<Value> foo = v8_str("foo");
9738
9739 // Set same security token for env1 and env2.
9740 env1->SetSecurityToken(foo);
9741 env2->SetSecurityToken(foo);
9742
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009743 CHECK(env1->Global()
9744 ->Set(env1.local(), v8_str("x"), v8_str("env1_x"))
9745 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009746
9747 {
9748 v8::Context::Scope scope(env2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009749 CHECK(env2->Global()->Set(env2, v8_str("x"), v8_str("env2_x")).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009750 CompileRun(
9751 "function bound_x() { return x; }"
9752 "function get_x() { return this.x; }"
9753 "function get_x_w() { return (function() {return this.x;})(); }");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009754 CHECK(env1->Global()
9755 ->Set(env1.local(), v8_str("bound_x"), CompileRun("bound_x"))
9756 .FromJust());
9757 CHECK(env1->Global()
9758 ->Set(env1.local(), v8_str("get_x"), CompileRun("get_x"))
9759 .FromJust());
9760 CHECK(env1->Global()
9761 ->Set(env1.local(), v8_str("get_x_w"), CompileRun("get_x_w"))
9762 .FromJust());
9763 env1->Global()
9764 ->Set(env1.local(), v8_str("this_x"),
9765 CompileRun("Object.getOwnPropertyDescriptor(this, 'this_x').get"))
9766 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009767 }
9768
9769 Local<Object> env2_global = env2->Global();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009770 env2->DetachGlobal();
9771
9772 Local<Value> result;
9773 result = CompileRun("bound_x()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009774 CHECK(v8_str("env2_x")->Equals(env1.local(), result).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009775 result = CompileRun("get_x()");
9776 CHECK(result.IsEmpty());
9777 result = CompileRun("get_x_w()");
9778 CHECK(result.IsEmpty());
9779 result = CompileRun("this_x()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009780 CHECK(v8_str("env2_x")->Equals(env1.local(), result).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009781
9782 // Reattach env2's proxy
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009783 env2 = Context::New(env1->GetIsolate(), 0, v8::Local<v8::ObjectTemplate>(),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009784 env2_global);
9785 env2->SetSecurityToken(foo);
9786 {
9787 v8::Context::Scope scope(env2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009788 CHECK(env2->Global()->Set(env2, v8_str("x"), v8_str("env3_x")).FromJust());
9789 CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009790 result = CompileRun(
9791 "results = [];"
9792 "for (var i = 0; i < 4; i++ ) {"
9793 " results.push(env1.bound_x());"
9794 " results.push(env1.get_x());"
9795 " results.push(env1.get_x_w());"
9796 " results.push(env1.this_x());"
9797 "}"
9798 "results");
9799 Local<v8::Array> results = Local<v8::Array>::Cast(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009800 CHECK_EQ(16u, results->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009801 for (int i = 0; i < 16; i += 4) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009802 CHECK(v8_str("env2_x")
9803 ->Equals(env2, results->Get(env2, i + 0).ToLocalChecked())
9804 .FromJust());
9805 CHECK(v8_str("env1_x")
9806 ->Equals(env2, results->Get(env2, i + 1).ToLocalChecked())
9807 .FromJust());
9808 CHECK(v8_str("env3_x")
9809 ->Equals(env2, results->Get(env2, i + 2).ToLocalChecked())
9810 .FromJust());
9811 CHECK(v8_str("env2_x")
9812 ->Equals(env2, results->Get(env2, i + 3).ToLocalChecked())
9813 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009814 }
9815 }
9816
9817 result = CompileRun(
9818 "results = [];"
9819 "for (var i = 0; i < 4; i++ ) {"
9820 " results.push(bound_x());"
9821 " results.push(get_x());"
9822 " results.push(get_x_w());"
9823 " results.push(this_x());"
9824 "}"
9825 "results");
9826 Local<v8::Array> results = Local<v8::Array>::Cast(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009827 CHECK_EQ(16u, results->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009828 for (int i = 0; i < 16; i += 4) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009829 CHECK(v8_str("env2_x")
9830 ->Equals(env1.local(),
9831 results->Get(env1.local(), i + 0).ToLocalChecked())
9832 .FromJust());
9833 CHECK(v8_str("env3_x")
9834 ->Equals(env1.local(),
9835 results->Get(env1.local(), i + 1).ToLocalChecked())
9836 .FromJust());
9837 CHECK(v8_str("env3_x")
9838 ->Equals(env1.local(),
9839 results->Get(env1.local(), i + 2).ToLocalChecked())
9840 .FromJust());
9841 CHECK(v8_str("env2_x")
9842 ->Equals(env1.local(),
9843 results->Get(env1.local(), i + 3).ToLocalChecked())
9844 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009845 }
9846
9847 result = CompileRun(
9848 "results = [];"
9849 "for (var i = 0; i < 4; i++ ) {"
9850 " results.push(this.bound_x());"
9851 " results.push(this.get_x());"
9852 " results.push(this.get_x_w());"
9853 " results.push(this.this_x());"
9854 "}"
9855 "results");
9856 results = Local<v8::Array>::Cast(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009857 CHECK_EQ(16u, results->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009858 for (int i = 0; i < 16; i += 4) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009859 CHECK(v8_str("env2_x")
9860 ->Equals(env1.local(),
9861 results->Get(env1.local(), i + 0).ToLocalChecked())
9862 .FromJust());
9863 CHECK(v8_str("env1_x")
9864 ->Equals(env1.local(),
9865 results->Get(env1.local(), i + 1).ToLocalChecked())
9866 .FromJust());
9867 CHECK(v8_str("env3_x")
9868 ->Equals(env1.local(),
9869 results->Get(env1.local(), i + 2).ToLocalChecked())
9870 .FromJust());
9871 CHECK(v8_str("env2_x")
9872 ->Equals(env1.local(),
9873 results->Get(env1.local(), i + 3).ToLocalChecked())
9874 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009875 }
Andrei Popescu74b3c142010-03-29 12:03:09 +01009876}
9877
9878
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009879static bool allowed_access = false;
9880static bool AccessBlocker(Local<v8::Context> accessing_context,
Ben Murdoch097c5b22016-05-18 11:27:45 +01009881 Local<v8::Object> accessed_object,
9882 Local<v8::Value> data) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009883 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
9884 return context->Global()->Equals(context, accessed_object).FromJust() ||
9885 allowed_access;
Steve Blocka7e24c12009-10-30 11:49:00 +00009886}
9887
9888
9889static int g_echo_value = -1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009890
9891
9892static void EchoGetter(
9893 Local<String> name,
9894 const v8::PropertyCallbackInfo<v8::Value>& info) {
9895 info.GetReturnValue().Set(v8_num(g_echo_value));
Steve Blocka7e24c12009-10-30 11:49:00 +00009896}
9897
9898
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009899static void EchoSetter(Local<String> name, Local<Value> value,
9900 const v8::PropertyCallbackInfo<void>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009901 if (value->IsNumber())
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009902 g_echo_value =
9903 value->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00009904}
9905
9906
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009907static void UnreachableGetter(
9908 Local<String> name,
9909 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009910 CHECK(false); // This function should not be called..
Steve Blocka7e24c12009-10-30 11:49:00 +00009911}
9912
9913
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009914static void UnreachableSetter(Local<String>,
9915 Local<Value>,
9916 const v8::PropertyCallbackInfo<void>&) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009917 CHECK(false); // This function should nto be called.
9918}
9919
9920
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009921static void UnreachableFunction(
9922 const v8::FunctionCallbackInfo<v8::Value>& info) {
9923 CHECK(false); // This function should not be called..
9924}
9925
9926
Steve Block1e0659c2011-05-24 12:43:12 +01009927TEST(AccessControl) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009928 v8::Isolate* isolate = CcTest::isolate();
9929 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009930 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009931 v8::ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00009932
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009933 global_template->SetAccessCheckCallback(AccessBlocker);
Steve Blocka7e24c12009-10-30 11:49:00 +00009934
9935 // Add an accessor accessible by cross-domain JS code.
9936 global_template->SetAccessor(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009937 v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
Steve Blocka7e24c12009-10-30 11:49:00 +00009938 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
9939
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009940
Steve Blocka7e24c12009-10-30 11:49:00 +00009941 // Add an accessor that is not accessible by cross-domain JS code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009942 global_template->SetAccessor(v8_str("blocked_prop"), UnreachableGetter,
9943 UnreachableSetter, v8::Local<Value>(),
Steve Blocka7e24c12009-10-30 11:49:00 +00009944 v8::DEFAULT);
9945
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009946 global_template->SetAccessorProperty(
9947 v8_str("blocked_js_prop"),
9948 v8::FunctionTemplate::New(isolate, UnreachableFunction),
9949 v8::FunctionTemplate::New(isolate, UnreachableFunction),
9950 v8::None,
9951 v8::DEFAULT);
9952
Steve Blocka7e24c12009-10-30 11:49:00 +00009953 // Create an environment
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009954 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
Steve Blocka7e24c12009-10-30 11:49:00 +00009955 context0->Enter();
9956
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009957 v8::Local<v8::Object> global0 = context0->Global();
Steve Blocka7e24c12009-10-30 11:49:00 +00009958
Steve Block1e0659c2011-05-24 12:43:12 +01009959 // Define a property with JS getter and setter.
9960 CompileRun(
9961 "function getter() { return 'getter'; };\n"
9962 "function setter() { return 'setter'; }\n"
9963 "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
9964
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009965 Local<Value> getter =
9966 global0->Get(context0, v8_str("getter")).ToLocalChecked();
9967 Local<Value> setter =
9968 global0->Get(context0, v8_str("setter")).ToLocalChecked();
Steve Block1e0659c2011-05-24 12:43:12 +01009969
9970 // And define normal element.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009971 CHECK(global0->Set(context0, 239, v8_str("239")).FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +01009972
9973 // Define an element with JS getter and setter.
9974 CompileRun(
9975 "function el_getter() { return 'el_getter'; };\n"
9976 "function el_setter() { return 'el_setter'; };\n"
9977 "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
9978
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009979 Local<Value> el_getter =
9980 global0->Get(context0, v8_str("el_getter")).ToLocalChecked();
9981 Local<Value> el_setter =
9982 global0->Get(context0, v8_str("el_setter")).ToLocalChecked();
Steve Block1e0659c2011-05-24 12:43:12 +01009983
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009984 v8::HandleScope scope1(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00009985
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009986 v8::Local<Context> context1 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00009987 context1->Enter();
9988
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009989 v8::Local<v8::Object> global1 = context1->Global();
9990 CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009991
Steve Block1e0659c2011-05-24 12:43:12 +01009992 // Access blocked property.
9993 CompileRun("other.blocked_prop = 1");
9994
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009995 CHECK(CompileRun("other.blocked_prop").IsEmpty());
9996 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
9997 .IsEmpty());
9998 CHECK(
9999 CompileRun("propertyIsEnumerable.call(other, 'blocked_prop')").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +010010000
10001 // Access blocked element.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010002 CHECK(CompileRun("other[239] = 1").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +010010003
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010004 CHECK(CompileRun("other[239]").IsEmpty());
10005 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '239')").IsEmpty());
10006 CHECK(CompileRun("propertyIsEnumerable.call(other, '239')").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +010010007
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010008 allowed_access = true;
10009 // Now we can enumerate the property.
Steve Block1e0659c2011-05-24 12:43:12 +010010010 ExpectTrue("propertyIsEnumerable.call(other, '239')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010011 allowed_access = false;
Steve Block1e0659c2011-05-24 12:43:12 +010010012
10013 // Access a property with JS accessor.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010014 CHECK(CompileRun("other.js_accessor_p = 2").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +010010015
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010016 CHECK(CompileRun("other.js_accessor_p").IsEmpty());
10017 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'js_accessor_p')")
10018 .IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +010010019
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010020 allowed_access = true;
Steve Block1e0659c2011-05-24 12:43:12 +010010021
10022 ExpectString("other.js_accessor_p", "getter");
10023 ExpectObject(
10024 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
Steve Block1e0659c2011-05-24 12:43:12 +010010025 ExpectObject(
10026 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
10027 ExpectUndefined(
10028 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
10029
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010030 allowed_access = false;
Steve Block1e0659c2011-05-24 12:43:12 +010010031
10032 // Access an element with JS accessor.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010033 CHECK(CompileRun("other[42] = 2").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +010010034
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010035 CHECK(CompileRun("other[42]").IsEmpty());
10036 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '42')").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +010010037
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010038 allowed_access = true;
Steve Block1e0659c2011-05-24 12:43:12 +010010039
10040 ExpectString("other[42]", "el_getter");
10041 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
Steve Block1e0659c2011-05-24 12:43:12 +010010042 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
10043 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
10044
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010045 allowed_access = false;
Steve Block1e0659c2011-05-24 12:43:12 +010010046
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010047 v8::Local<Value> value;
Steve Blocka7e24c12009-10-30 11:49:00 +000010048
Steve Blocka7e24c12009-10-30 11:49:00 +000010049 // Access accessible property
Steve Block1e0659c2011-05-24 12:43:12 +010010050 value = CompileRun("other.accessible_prop = 3");
Steve Blocka7e24c12009-10-30 11:49:00 +000010051 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010052 CHECK_EQ(3, value->Int32Value(context1).FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +000010053 CHECK_EQ(3, g_echo_value);
Steve Blocka7e24c12009-10-30 11:49:00 +000010054
Steve Block1e0659c2011-05-24 12:43:12 +010010055 value = CompileRun("other.accessible_prop");
Steve Blocka7e24c12009-10-30 11:49:00 +000010056 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010057 CHECK_EQ(3, value->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010058
Steve Block1e0659c2011-05-24 12:43:12 +010010059 value = CompileRun(
10060 "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
10061 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010062 CHECK_EQ(3, value->Int32Value(context1).FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +010010063
10064 value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
Steve Blocka7e24c12009-10-30 11:49:00 +000010065 CHECK(value->IsTrue());
10066
10067 // Enumeration doesn't enumerate accessors from inaccessible objects in
10068 // the prototype chain even if the accessors are in themselves accessible.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010069 // Enumeration doesn't throw, it silently ignores what it can't access.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010070 value = CompileRun(
10071 "(function() {"
10072 " var obj = { '__proto__': other };"
10073 " try {"
10074 " for (var p in obj) {"
10075 " if (p == 'accessible_prop' ||"
10076 " p == 'blocked_js_prop' ||"
10077 " p == 'blocked_js_prop') {"
10078 " return false;"
10079 " }"
10080 " }"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010081 " return true;"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010082 " } catch (e) {"
10083 " return false;"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010084 " }"
10085 "})()");
Steve Block1e0659c2011-05-24 12:43:12 +010010086 CHECK(value->IsTrue());
Steve Blocka7e24c12009-10-30 11:49:00 +000010087
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010088 // Test that preventExtensions fails on a non-accessible object even if that
10089 // object is already non-extensible.
10090 CHECK(global1->Set(context1, v8_str("checked_object"),
10091 global_template->NewInstance(context1).ToLocalChecked())
10092 .FromJust());
10093 allowed_access = true;
10094 CompileRun("Object.preventExtensions(checked_object)");
10095 ExpectFalse("Object.isExtensible(checked_object)");
10096 allowed_access = false;
10097 CHECK(CompileRun("Object.preventExtensions(checked_object)").IsEmpty());
10098
Steve Blocka7e24c12009-10-30 11:49:00 +000010099 context1->Exit();
10100 context0->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +000010101}
10102
10103
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010104TEST(AccessControlES5) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010105 v8::Isolate* isolate = CcTest::isolate();
10106 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010107 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010108 v8::ObjectTemplate::New(isolate);
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010109
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010110 global_template->SetAccessCheckCallback(AccessBlocker);
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010111
Steve Block44f0eee2011-05-26 01:26:41 +010010112 // Add accessible accessor.
10113 global_template->SetAccessor(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010114 v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
Steve Block44f0eee2011-05-26 01:26:41 +010010115 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
10116
10117
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010118 // Add an accessor that is not accessible by cross-domain JS code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010119 global_template->SetAccessor(v8_str("blocked_prop"), UnreachableGetter,
10120 UnreachableSetter, v8::Local<Value>(),
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010121 v8::DEFAULT);
10122
10123 // Create an environment
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010124 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010125 context0->Enter();
10126
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010127 v8::Local<v8::Object> global0 = context0->Global();
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010128
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010129 v8::Local<Context> context1 = Context::New(isolate);
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010130 context1->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010131 v8::Local<v8::Object> global1 = context1->Global();
10132 CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010133
10134 // Regression test for issue 1154.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010135 CHECK(CompileRun("Object.keys(other).length == 1")
10136 ->BooleanValue(context1)
10137 .FromJust());
10138 CHECK(CompileRun("Object.keys(other)[0] == 'accessible_prop'")
10139 ->BooleanValue(context1)
10140 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010141 CHECK(CompileRun("other.blocked_prop").IsEmpty());
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010142
10143 // Regression test for issue 1027.
10144 CompileRun("Object.defineProperty(\n"
10145 " other, 'blocked_prop', {configurable: false})");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010146 CHECK(CompileRun("other.blocked_prop").IsEmpty());
10147 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
10148 .IsEmpty());
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010149
10150 // Regression test for issue 1171.
10151 ExpectTrue("Object.isExtensible(other)");
10152 CompileRun("Object.preventExtensions(other)");
10153 ExpectTrue("Object.isExtensible(other)");
10154
10155 // Object.seal and Object.freeze.
10156 CompileRun("Object.freeze(other)");
10157 ExpectTrue("Object.isExtensible(other)");
10158
10159 CompileRun("Object.seal(other)");
10160 ExpectTrue("Object.isExtensible(other)");
Steve Block44f0eee2011-05-26 01:26:41 +010010161
10162 // Regression test for issue 1250.
10163 // Make sure that we can set the accessible accessors value using normal
10164 // assignment.
10165 CompileRun("other.accessible_prop = 42");
10166 CHECK_EQ(42, g_echo_value);
10167
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010168 // [[DefineOwnProperty]] always throws for access-checked objects.
10169 CHECK(
10170 CompileRun("Object.defineProperty(other, 'accessible_prop', {value: 43})")
10171 .IsEmpty());
10172 CHECK(CompileRun("other.accessible_prop == 42")->IsTrue());
10173 CHECK_EQ(42, g_echo_value); // Make sure we didn't call the setter.
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010174}
10175
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010176static bool AccessAlwaysBlocked(Local<v8::Context> accessing_context,
Ben Murdoch097c5b22016-05-18 11:27:45 +010010177 Local<v8::Object> global,
10178 Local<v8::Value> data) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010179 i::PrintF("Access blocked.\n");
Leon Clarke4515c472010-02-03 11:58:03 +000010180 return false;
10181}
10182
10183
10184THREADED_TEST(AccessControlGetOwnPropertyNames) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010185 v8::Isolate* isolate = CcTest::isolate();
10186 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010187 v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
Leon Clarke4515c472010-02-03 11:58:03 +000010188
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010189 obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010190 obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
10191
10192 // Add an accessor accessible by cross-domain JS code.
10193 obj_template->SetAccessor(
10194 v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
10195 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
Leon Clarke4515c472010-02-03 11:58:03 +000010196
10197 // Create an environment
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010198 v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
Leon Clarke4515c472010-02-03 11:58:03 +000010199 context0->Enter();
10200
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010201 v8::Local<v8::Object> global0 = context0->Global();
Leon Clarke4515c472010-02-03 11:58:03 +000010202
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010203 v8::HandleScope scope1(CcTest::isolate());
Leon Clarke4515c472010-02-03 11:58:03 +000010204
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010205 v8::Local<Context> context1 = Context::New(isolate);
Leon Clarke4515c472010-02-03 11:58:03 +000010206 context1->Enter();
10207
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010208 v8::Local<v8::Object> global1 = context1->Global();
10209 CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
10210 CHECK(global1->Set(context1, v8_str("object"),
10211 obj_template->NewInstance(context1).ToLocalChecked())
10212 .FromJust());
Leon Clarke4515c472010-02-03 11:58:03 +000010213
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010214 v8::Local<Value> value;
Leon Clarke4515c472010-02-03 11:58:03 +000010215
10216 // Attempt to get the property names of the other global object and
10217 // of an object that requires access checks. Accessing the other
10218 // global object should be blocked by access checks on the global
10219 // proxy object. Accessing the object that requires access checks
10220 // is blocked by the access checks on the object itself.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010221 value = CompileRun(
10222 "var names = Object.getOwnPropertyNames(other);"
10223 "names.length == 1 && names[0] == 'accessible_prop';");
10224 CHECK(value->BooleanValue(context1).FromJust());
Leon Clarke4515c472010-02-03 11:58:03 +000010225
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010226 value = CompileRun(
10227 "var names = Object.getOwnPropertyNames(object);"
10228 "names.length == 1 && names[0] == 'accessible_prop';");
10229 CHECK(value->BooleanValue(context1).FromJust());
Leon Clarke4515c472010-02-03 11:58:03 +000010230
10231 context1->Exit();
10232 context0->Exit();
Leon Clarke4515c472010-02-03 11:58:03 +000010233}
10234
10235
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010236TEST(Regress470113) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010237 v8::Isolate* isolate = CcTest::isolate();
10238 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010239 v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
10240 obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010241 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010242 CHECK(env->Global()
10243 ->Set(env.local(), v8_str("prohibited"),
10244 obj_template->NewInstance(env.local()).ToLocalChecked())
10245 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010246
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010247 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010248 v8::TryCatch try_catch(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010249 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010250 "'use strict';\n"
10251 "class C extends Object {\n"
10252 " m() { super.powned = 'Powned!'; }\n"
10253 "}\n"
10254 "let c = new C();\n"
10255 "c.m.call(prohibited)");
10256
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010257 CHECK(try_catch.HasCaught());
10258 }
Steve Block8defd9f2010-07-08 12:39:36 +010010259}
10260
10261
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010262static void ConstTenGetter(Local<String> name,
10263 const v8::PropertyCallbackInfo<v8::Value>& info) {
10264 info.GetReturnValue().Set(v8_num(10));
Steve Blocka7e24c12009-10-30 11:49:00 +000010265}
10266
10267
10268THREADED_TEST(CrossDomainAccessors) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010269 v8::Isolate* isolate = CcTest::isolate();
10270 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010271
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010272 v8::Local<v8::FunctionTemplate> func_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010273 v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010274
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010275 v8::Local<v8::ObjectTemplate> global_template =
Steve Blocka7e24c12009-10-30 11:49:00 +000010276 func_template->InstanceTemplate();
10277
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010278 v8::Local<v8::ObjectTemplate> proto_template =
Steve Blocka7e24c12009-10-30 11:49:00 +000010279 func_template->PrototypeTemplate();
10280
10281 // Add an accessor to proto that's accessible by cross-domain JS code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010282 proto_template->SetAccessor(v8_str("accessible"), ConstTenGetter, 0,
10283 v8::Local<Value>(), v8::ALL_CAN_READ);
Steve Blocka7e24c12009-10-30 11:49:00 +000010284
10285 // Add an accessor that is not accessible by cross-domain JS code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010286 global_template->SetAccessor(v8_str("unreachable"), UnreachableGetter, 0,
10287 v8::Local<Value>(), v8::DEFAULT);
Steve Blocka7e24c12009-10-30 11:49:00 +000010288
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010289 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
Steve Blocka7e24c12009-10-30 11:49:00 +000010290 context0->Enter();
10291
10292 Local<v8::Object> global = context0->Global();
10293 // Add a normal property that shadows 'accessible'
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010294 CHECK(global->Set(context0, v8_str("accessible"), v8_num(11)).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010295
10296 // Enter a new context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010297 v8::HandleScope scope1(CcTest::isolate());
10298 v8::Local<Context> context1 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010299 context1->Enter();
10300
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010301 v8::Local<v8::Object> global1 = context1->Global();
10302 CHECK(global1->Set(context1, v8_str("other"), global).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010303
10304 // Should return 10, instead of 11
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010305 v8::Local<Value> value =
10306 v8_compile("other.accessible")->Run(context1).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000010307 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010308 CHECK_EQ(10, value->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010309
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010310 v8::MaybeLocal<v8::Value> maybe_value =
10311 v8_compile("other.unreachable")->Run(context1);
10312 CHECK(maybe_value.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000010313
10314 context1->Exit();
10315 context0->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +000010316}
10317
10318
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010319static int access_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +000010320
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010321static bool AccessCounter(Local<v8::Context> accessing_context,
Ben Murdoch097c5b22016-05-18 11:27:45 +010010322 Local<v8::Object> accessed_object,
10323 Local<v8::Value> data) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010324 access_count++;
Steve Blocka7e24c12009-10-30 11:49:00 +000010325 return true;
10326}
10327
10328
10329// This one is too easily disturbed by other tests.
10330TEST(AccessControlIC) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010331 access_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +000010332
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010333 v8::Isolate* isolate = CcTest::isolate();
10334 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010335
10336 // Create an environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010337 v8::Local<Context> context0 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010338 context0->Enter();
10339
10340 // Create an object that requires access-check functions to be
10341 // called for cross-domain access.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010342 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010343 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010344 object_template->SetAccessCheckCallback(AccessCounter);
10345 Local<v8::Object> object =
10346 object_template->NewInstance(context0).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000010347
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010348 v8::HandleScope scope1(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010349
10350 // Create another environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010351 v8::Local<Context> context1 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010352 context1->Enter();
10353
10354 // Make easy access to the object from the other environment.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010355 v8::Local<v8::Object> global1 = context1->Global();
10356 CHECK(global1->Set(context1, v8_str("obj"), object).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010357
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010358 v8::Local<Value> value;
Steve Blocka7e24c12009-10-30 11:49:00 +000010359
10360 // Check that the named access-control function is called every time.
10361 CompileRun("function testProp(obj) {"
10362 " for (var i = 0; i < 10; i++) obj.prop = 1;"
10363 " for (var j = 0; j < 10; j++) obj.prop;"
10364 " return obj.prop"
10365 "}");
10366 value = CompileRun("testProp(obj)");
10367 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010368 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10369 CHECK_EQ(21, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010370
10371 // Check that the named access-control function is called every time.
10372 CompileRun("var p = 'prop';"
10373 "function testKeyed(obj) {"
10374 " for (var i = 0; i < 10; i++) obj[p] = 1;"
10375 " for (var j = 0; j < 10; j++) obj[p];"
10376 " return obj[p];"
10377 "}");
10378 // Use obj which requires access checks. No inline caching is used
10379 // in that case.
10380 value = CompileRun("testKeyed(obj)");
10381 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010382 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10383 CHECK_EQ(42, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010384 // Force the inline caches into generic state and try again.
10385 CompileRun("testKeyed({ a: 0 })");
10386 CompileRun("testKeyed({ b: 0 })");
10387 value = CompileRun("testKeyed(obj)");
10388 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010389 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10390 CHECK_EQ(63, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010391
10392 // Check that the indexed access-control function is called every time.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010393 access_count = 0;
10394
Steve Blocka7e24c12009-10-30 11:49:00 +000010395 CompileRun("function testIndexed(obj) {"
10396 " for (var i = 0; i < 10; i++) obj[0] = 1;"
10397 " for (var j = 0; j < 10; j++) obj[0];"
10398 " return obj[0]"
10399 "}");
10400 value = CompileRun("testIndexed(obj)");
10401 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010402 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10403 CHECK_EQ(21, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010404 // Force the inline caches into generic state.
10405 CompileRun("testIndexed(new Array(1))");
10406 // Test that the indexed access check is called.
10407 value = CompileRun("testIndexed(obj)");
10408 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010409 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10410 CHECK_EQ(42, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010411
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010412 access_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +000010413 // Check that the named access check is called when invoking
10414 // functions on an object that requires access checks.
10415 CompileRun("obj.f = function() {}");
10416 CompileRun("function testCallNormal(obj) {"
10417 " for (var i = 0; i < 10; i++) obj.f();"
10418 "}");
10419 CompileRun("testCallNormal(obj)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010420 printf("%i\n", access_count);
10421 CHECK_EQ(11, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010422
10423 // Force obj into slow case.
10424 value = CompileRun("delete obj.prop");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010425 CHECK(value->BooleanValue(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010426 // Force inline caches into dictionary probing mode.
10427 CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
10428 // Test that the named access check is called.
10429 value = CompileRun("testProp(obj);");
10430 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010431 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10432 CHECK_EQ(33, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010433
10434 // Force the call inline cache into dictionary probing mode.
10435 CompileRun("o.f = function() {}; testCallNormal(o)");
10436 // Test that the named access check is still called for each
10437 // invocation of the function.
10438 value = CompileRun("testCallNormal(obj)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010439 CHECK_EQ(43, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010440
10441 context1->Exit();
10442 context0->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +000010443}
10444
10445
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010446THREADED_TEST(Version) { v8::V8::GetVersion(); }
Steve Blocka7e24c12009-10-30 11:49:00 +000010447
10448
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010449static void InstanceFunctionCallback(
10450 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010451 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010452 args.GetReturnValue().Set(v8_num(12));
Steve Blocka7e24c12009-10-30 11:49:00 +000010453}
10454
10455
10456THREADED_TEST(InstanceProperties) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010457 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010458 v8::Isolate* isolate = context->GetIsolate();
10459 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010460
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010461 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010462 Local<ObjectTemplate> instance = t->InstanceTemplate();
10463
10464 instance->Set(v8_str("x"), v8_num(42));
10465 instance->Set(v8_str("f"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010466 v8::FunctionTemplate::New(isolate, InstanceFunctionCallback));
Steve Blocka7e24c12009-10-30 11:49:00 +000010467
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010468 Local<Value> o = t->GetFunction(context.local())
10469 .ToLocalChecked()
10470 ->NewInstance(context.local())
10471 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000010472
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010473 CHECK(context->Global()->Set(context.local(), v8_str("i"), o).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010474 Local<Value> value = CompileRun("i.x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010475 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010476
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010477 value = CompileRun("i.f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010478 CHECK_EQ(12, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010479}
10480
10481
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010482static void GlobalObjectInstancePropertiesGet(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010483 Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>&) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010484 ApiTestFuzzer::Fuzz();
Steve Blocka7e24c12009-10-30 11:49:00 +000010485}
10486
10487
10488THREADED_TEST(GlobalObjectInstanceProperties) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010489 v8::Isolate* isolate = CcTest::isolate();
10490 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010491
10492 Local<Value> global_object;
10493
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010494 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010495 t->InstanceTemplate()->SetHandler(
10496 v8::NamedPropertyHandlerConfiguration(GlobalObjectInstancePropertiesGet));
Steve Blocka7e24c12009-10-30 11:49:00 +000010497 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10498 instance_template->Set(v8_str("x"), v8_num(42));
10499 instance_template->Set(v8_str("f"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010500 v8::FunctionTemplate::New(isolate,
10501 InstanceFunctionCallback));
Steve Blocka7e24c12009-10-30 11:49:00 +000010502
Ben Murdochb0fe1622011-05-05 13:52:32 +010010503 // The script to check how Crankshaft compiles missing global function
10504 // invocations. function g is not defined and should throw on call.
10505 const char* script =
10506 "function wrapper(call) {"
10507 " var x = 0, y = 1;"
10508 " for (var i = 0; i < 1000; i++) {"
10509 " x += i * 100;"
10510 " y += i * 100;"
10511 " }"
10512 " if (call) g();"
10513 "}"
10514 "for (var i = 0; i < 17; i++) wrapper(false);"
10515 "var thrown = 0;"
10516 "try { wrapper(true); } catch (e) { thrown = 1; };"
10517 "thrown";
10518
Steve Blocka7e24c12009-10-30 11:49:00 +000010519 {
10520 LocalContext env(NULL, instance_template);
10521 // Hold on to the global object so it can be used again in another
10522 // environment initialization.
10523 global_object = env->Global();
10524
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010525 Local<Value> value = CompileRun("x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010526 CHECK_EQ(42, value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010527 value = CompileRun("f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010528 CHECK_EQ(12, value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010529 value = CompileRun(script);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010530 CHECK_EQ(1, value->Int32Value(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010531 }
10532
10533 {
10534 // Create new environment reusing the global object.
10535 LocalContext env(NULL, instance_template, global_object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010536 Local<Value> value = CompileRun("x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010537 CHECK_EQ(42, value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010538 value = CompileRun("f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010539 CHECK_EQ(12, value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010540 value = CompileRun(script);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010541 CHECK_EQ(1, value->Int32Value(env.local()).FromJust());
Ben Murdochb0fe1622011-05-05 13:52:32 +010010542 }
10543}
10544
10545
10546THREADED_TEST(CallKnownGlobalReceiver) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010547 v8::Isolate* isolate = CcTest::isolate();
10548 v8::HandleScope handle_scope(isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +010010549
10550 Local<Value> global_object;
10551
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010552 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +010010553 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10554
10555 // The script to check that we leave global object not
10556 // global object proxy on stack when we deoptimize from inside
10557 // arguments evaluation.
10558 // To provoke error we need to both force deoptimization
10559 // from arguments evaluation and to force CallIC to take
10560 // CallIC_Miss code path that can't cope with global proxy.
10561 const char* script =
10562 "function bar(x, y) { try { } finally { } }"
10563 "function baz(x) { try { } finally { } }"
10564 "function bom(x) { try { } finally { } }"
10565 "function foo(x) { bar([x], bom(2)); }"
10566 "for (var i = 0; i < 10000; i++) foo(1);"
10567 "foo";
10568
10569 Local<Value> foo;
10570 {
10571 LocalContext env(NULL, instance_template);
10572 // Hold on to the global object so it can be used again in another
10573 // environment initialization.
10574 global_object = env->Global();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010575 foo = CompileRun(script);
Ben Murdochb0fe1622011-05-05 13:52:32 +010010576 }
10577
10578 {
10579 // Create new environment reusing the global object.
10580 LocalContext env(NULL, instance_template, global_object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010581 CHECK(env->Global()->Set(env.local(), v8_str("foo"), foo).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010582 CompileRun("foo()");
Steve Blocka7e24c12009-10-30 11:49:00 +000010583 }
10584}
10585
10586
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010587static void ShadowFunctionCallback(
10588 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010589 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010590 args.GetReturnValue().Set(v8_num(42));
Steve Blocka7e24c12009-10-30 11:49:00 +000010591}
10592
10593
10594static int shadow_y;
10595static int shadow_y_setter_call_count;
10596static int shadow_y_getter_call_count;
10597
10598
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010599static void ShadowYSetter(Local<String>,
10600 Local<Value>,
10601 const v8::PropertyCallbackInfo<void>&) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010602 shadow_y_setter_call_count++;
10603 shadow_y = 42;
10604}
10605
10606
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010607static void ShadowYGetter(Local<String> name,
10608 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010609 ApiTestFuzzer::Fuzz();
10610 shadow_y_getter_call_count++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010611 info.GetReturnValue().Set(v8_num(shadow_y));
Steve Blocka7e24c12009-10-30 11:49:00 +000010612}
10613
10614
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010615static void ShadowIndexedGet(uint32_t index,
10616 const v8::PropertyCallbackInfo<v8::Value>&) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010617}
10618
10619
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010620static void ShadowNamedGet(Local<Name> key,
10621 const v8::PropertyCallbackInfo<v8::Value>&) {}
Steve Blocka7e24c12009-10-30 11:49:00 +000010622
10623
10624THREADED_TEST(ShadowObject) {
10625 shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010626 v8::Isolate* isolate = CcTest::isolate();
10627 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010628
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010629 Local<ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010630 LocalContext context(NULL, global_template);
10631
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010632 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010633 t->InstanceTemplate()->SetHandler(
10634 v8::NamedPropertyHandlerConfiguration(ShadowNamedGet));
10635 t->InstanceTemplate()->SetHandler(
10636 v8::IndexedPropertyHandlerConfiguration(ShadowIndexedGet));
Steve Blocka7e24c12009-10-30 11:49:00 +000010637 Local<ObjectTemplate> proto = t->PrototypeTemplate();
10638 Local<ObjectTemplate> instance = t->InstanceTemplate();
10639
Steve Blocka7e24c12009-10-30 11:49:00 +000010640 proto->Set(v8_str("f"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010641 v8::FunctionTemplate::New(isolate,
10642 ShadowFunctionCallback,
10643 Local<Value>()));
Steve Blocka7e24c12009-10-30 11:49:00 +000010644 proto->Set(v8_str("x"), v8_num(12));
10645
10646 instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
10647
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010648 Local<Value> o = t->GetFunction(context.local())
10649 .ToLocalChecked()
10650 ->NewInstance(context.local())
10651 .ToLocalChecked();
10652 CHECK(context->Global()
10653 ->Set(context.local(), v8_str("__proto__"), o)
10654 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010655
10656 Local<Value> value =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010657 CompileRun("this.propertyIsEnumerable(0)");
Steve Blocka7e24c12009-10-30 11:49:00 +000010658 CHECK(value->IsBoolean());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010659 CHECK(!value->BooleanValue(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010660
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010661 value = CompileRun("x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010662 CHECK_EQ(12, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010663
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010664 value = CompileRun("f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010665 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010666
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010667 CompileRun("y = 43");
Steve Blocka7e24c12009-10-30 11:49:00 +000010668 CHECK_EQ(1, shadow_y_setter_call_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010669 value = CompileRun("y");
Steve Blocka7e24c12009-10-30 11:49:00 +000010670 CHECK_EQ(1, shadow_y_getter_call_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010671 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010672}
10673
10674
10675THREADED_TEST(HiddenPrototype) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010676 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010677 v8::Isolate* isolate = context->GetIsolate();
10678 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010679
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010680 Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010681 t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010682 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010683 t1->SetHiddenPrototype(true);
10684 t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010685 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010686 t2->SetHiddenPrototype(true);
10687 t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010688 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010689 t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
10690
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010691 Local<v8::Object> o0 = t0->GetFunction(context.local())
10692 .ToLocalChecked()
10693 ->NewInstance(context.local())
10694 .ToLocalChecked();
10695 Local<v8::Object> o1 = t1->GetFunction(context.local())
10696 .ToLocalChecked()
10697 ->NewInstance(context.local())
10698 .ToLocalChecked();
10699 Local<v8::Object> o2 = t2->GetFunction(context.local())
10700 .ToLocalChecked()
10701 ->NewInstance(context.local())
10702 .ToLocalChecked();
10703 Local<v8::Object> o3 = t3->GetFunction(context.local())
10704 .ToLocalChecked()
10705 ->NewInstance(context.local())
10706 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000010707
10708 // Setting the prototype on an object skips hidden prototypes.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010709 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10710 .ToLocalChecked()
10711 ->Int32Value(context.local())
10712 .FromJust());
10713 CHECK(o0->Set(context.local(), v8_str("__proto__"), o1).FromJust());
10714 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10715 .ToLocalChecked()
10716 ->Int32Value(context.local())
10717 .FromJust());
10718 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10719 .ToLocalChecked()
10720 ->Int32Value(context.local())
10721 .FromJust());
10722 CHECK(o0->Set(context.local(), v8_str("__proto__"), o2).FromJust());
10723 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10724 .ToLocalChecked()
10725 ->Int32Value(context.local())
10726 .FromJust());
10727 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10728 .ToLocalChecked()
10729 ->Int32Value(context.local())
10730 .FromJust());
10731 CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
10732 .ToLocalChecked()
10733 ->Int32Value(context.local())
10734 .FromJust());
10735 CHECK(o0->Set(context.local(), v8_str("__proto__"), o3).FromJust());
10736 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10737 .ToLocalChecked()
10738 ->Int32Value(context.local())
10739 .FromJust());
10740 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10741 .ToLocalChecked()
10742 ->Int32Value(context.local())
10743 .FromJust());
10744 CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
10745 .ToLocalChecked()
10746 ->Int32Value(context.local())
10747 .FromJust());
10748 CHECK_EQ(3, o0->Get(context.local(), v8_str("u"))
10749 .ToLocalChecked()
10750 ->Int32Value(context.local())
10751 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010752
10753 // Getting the prototype of o0 should get the first visible one
10754 // which is o3. Therefore, z should not be defined on the prototype
10755 // object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010756 Local<Value> proto =
10757 o0->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000010758 CHECK(proto->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010759 CHECK(proto.As<v8::Object>()
10760 ->Get(context.local(), v8_str("z"))
10761 .ToLocalChecked()
10762 ->IsUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +000010763}
10764
10765
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010766THREADED_TEST(HiddenPrototypeSet) {
Andrei Popescu402d9372010-02-26 13:31:12 +000010767 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010768 v8::Isolate* isolate = context->GetIsolate();
10769 v8::HandleScope handle_scope(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000010770
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010771 Local<v8::FunctionTemplate> ot = v8::FunctionTemplate::New(isolate);
10772 Local<v8::FunctionTemplate> ht = v8::FunctionTemplate::New(isolate);
10773 ht->SetHiddenPrototype(true);
10774 Local<v8::FunctionTemplate> pt = v8::FunctionTemplate::New(isolate);
10775 ht->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
10776
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010777 Local<v8::Object> o = ot->GetFunction(context.local())
10778 .ToLocalChecked()
10779 ->NewInstance(context.local())
10780 .ToLocalChecked();
10781 Local<v8::Object> h = ht->GetFunction(context.local())
10782 .ToLocalChecked()
10783 ->NewInstance(context.local())
10784 .ToLocalChecked();
10785 Local<v8::Object> p = pt->GetFunction(context.local())
10786 .ToLocalChecked()
10787 ->NewInstance(context.local())
10788 .ToLocalChecked();
10789 CHECK(o->Set(context.local(), v8_str("__proto__"), h).FromJust());
10790 CHECK(h->Set(context.local(), v8_str("__proto__"), p).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010791
10792 // Setting a property that exists on the hidden prototype goes there.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010793 CHECK(o->Set(context.local(), v8_str("x"), v8_num(7)).FromJust());
10794 CHECK_EQ(7, o->Get(context.local(), v8_str("x"))
10795 .ToLocalChecked()
10796 ->Int32Value(context.local())
10797 .FromJust());
10798 CHECK_EQ(7, h->Get(context.local(), v8_str("x"))
10799 .ToLocalChecked()
10800 ->Int32Value(context.local())
10801 .FromJust());
10802 CHECK(p->Get(context.local(), v8_str("x")).ToLocalChecked()->IsUndefined());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010803
10804 // Setting a new property should not be forwarded to the hidden prototype.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010805 CHECK(o->Set(context.local(), v8_str("y"), v8_num(6)).FromJust());
10806 CHECK_EQ(6, o->Get(context.local(), v8_str("y"))
10807 .ToLocalChecked()
10808 ->Int32Value(context.local())
10809 .FromJust());
10810 CHECK(h->Get(context.local(), v8_str("y")).ToLocalChecked()->IsUndefined());
10811 CHECK(p->Get(context.local(), v8_str("y")).ToLocalChecked()->IsUndefined());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010812
10813 // Setting a property that only exists on a prototype of the hidden prototype
10814 // is treated normally again.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010815 CHECK(p->Set(context.local(), v8_str("z"), v8_num(8)).FromJust());
10816 CHECK_EQ(8, o->Get(context.local(), v8_str("z"))
10817 .ToLocalChecked()
10818 ->Int32Value(context.local())
10819 .FromJust());
10820 CHECK_EQ(8, h->Get(context.local(), v8_str("z"))
10821 .ToLocalChecked()
10822 ->Int32Value(context.local())
10823 .FromJust());
10824 CHECK_EQ(8, p->Get(context.local(), v8_str("z"))
10825 .ToLocalChecked()
10826 ->Int32Value(context.local())
10827 .FromJust());
10828 CHECK(o->Set(context.local(), v8_str("z"), v8_num(9)).FromJust());
10829 CHECK_EQ(9, o->Get(context.local(), v8_str("z"))
10830 .ToLocalChecked()
10831 ->Int32Value(context.local())
10832 .FromJust());
10833 CHECK_EQ(8, h->Get(context.local(), v8_str("z"))
10834 .ToLocalChecked()
10835 ->Int32Value(context.local())
10836 .FromJust());
10837 CHECK_EQ(8, p->Get(context.local(), v8_str("z"))
10838 .ToLocalChecked()
10839 ->Int32Value(context.local())
10840 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010841}
10842
10843
10844// Regression test for issue 2457.
10845THREADED_TEST(HiddenPrototypeIdentityHash) {
10846 LocalContext context;
10847 v8::HandleScope handle_scope(context->GetIsolate());
10848
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010849 Local<FunctionTemplate> t = FunctionTemplate::New(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010850 t->SetHiddenPrototype(true);
10851 t->InstanceTemplate()->Set(v8_str("foo"), v8_num(75));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010852 Local<Object> p = t->GetFunction(context.local())
10853 .ToLocalChecked()
10854 ->NewInstance(context.local())
10855 .ToLocalChecked();
10856 Local<Object> o = Object::New(context->GetIsolate());
10857 CHECK(o->SetPrototype(context.local(), p).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010858
10859 int hash = o->GetIdentityHash();
10860 USE(hash);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010861 CHECK(o->Set(context.local(), v8_str("foo"), v8_num(42)).FromJust());
10862 CHECK_EQ(hash, o->GetIdentityHash());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010863}
10864
10865
10866THREADED_TEST(SetPrototype) {
10867 LocalContext context;
10868 v8::Isolate* isolate = context->GetIsolate();
10869 v8::HandleScope handle_scope(isolate);
10870
10871 Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000010872 t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010873 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000010874 t1->SetHiddenPrototype(true);
10875 t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010876 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000010877 t2->SetHiddenPrototype(true);
10878 t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010879 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000010880 t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
10881
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010882 Local<v8::Object> o0 = t0->GetFunction(context.local())
10883 .ToLocalChecked()
10884 ->NewInstance(context.local())
10885 .ToLocalChecked();
10886 Local<v8::Object> o1 = t1->GetFunction(context.local())
10887 .ToLocalChecked()
10888 ->NewInstance(context.local())
10889 .ToLocalChecked();
10890 Local<v8::Object> o2 = t2->GetFunction(context.local())
10891 .ToLocalChecked()
10892 ->NewInstance(context.local())
10893 .ToLocalChecked();
10894 Local<v8::Object> o3 = t3->GetFunction(context.local())
10895 .ToLocalChecked()
10896 ->NewInstance(context.local())
10897 .ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000010898
10899 // Setting the prototype on an object does not skip hidden prototypes.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010900 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10901 .ToLocalChecked()
10902 ->Int32Value(context.local())
10903 .FromJust());
10904 CHECK(o0->SetPrototype(context.local(), o1).FromJust());
10905 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10906 .ToLocalChecked()
10907 ->Int32Value(context.local())
10908 .FromJust());
10909 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10910 .ToLocalChecked()
10911 ->Int32Value(context.local())
10912 .FromJust());
10913 CHECK(o1->SetPrototype(context.local(), o2).FromJust());
10914 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10915 .ToLocalChecked()
10916 ->Int32Value(context.local())
10917 .FromJust());
10918 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10919 .ToLocalChecked()
10920 ->Int32Value(context.local())
10921 .FromJust());
10922 CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
10923 .ToLocalChecked()
10924 ->Int32Value(context.local())
10925 .FromJust());
10926 CHECK(o2->SetPrototype(context.local(), o3).FromJust());
10927 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10928 .ToLocalChecked()
10929 ->Int32Value(context.local())
10930 .FromJust());
10931 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10932 .ToLocalChecked()
10933 ->Int32Value(context.local())
10934 .FromJust());
10935 CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
10936 .ToLocalChecked()
10937 ->Int32Value(context.local())
10938 .FromJust());
10939 CHECK_EQ(3, o0->Get(context.local(), v8_str("u"))
10940 .ToLocalChecked()
10941 ->Int32Value(context.local())
10942 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000010943
10944 // Getting the prototype of o0 should get the first visible one
10945 // which is o3. Therefore, z should not be defined on the prototype
10946 // object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010947 Local<Value> proto =
10948 o0->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000010949 CHECK(proto->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010950 CHECK(proto.As<v8::Object>()->Equals(context.local(), o3).FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000010951
10952 // However, Object::GetPrototype ignores hidden prototype.
10953 Local<Value> proto0 = o0->GetPrototype();
10954 CHECK(proto0->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010955 CHECK(proto0.As<v8::Object>()->Equals(context.local(), o1).FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000010956
10957 Local<Value> proto1 = o1->GetPrototype();
10958 CHECK(proto1->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010959 CHECK(proto1.As<v8::Object>()->Equals(context.local(), o2).FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000010960
10961 Local<Value> proto2 = o2->GetPrototype();
10962 CHECK(proto2->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010963 CHECK(proto2.As<v8::Object>()->Equals(context.local(), o3).FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000010964}
10965
10966
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010967// Getting property names of an object with a prototype chain that
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010968// triggers dictionary elements in GetOwnPropertyNames() shouldn't
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010969// crash the runtime.
10970THREADED_TEST(Regress91517) {
10971 i::FLAG_allow_natives_syntax = true;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010972 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010973 v8::Isolate* isolate = context->GetIsolate();
10974 v8::HandleScope handle_scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010975
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010976 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010977 t1->SetHiddenPrototype(true);
10978 t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010979 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010980 t2->SetHiddenPrototype(true);
10981 t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
Ben Murdoch097c5b22016-05-18 11:27:45 +010010982 t2->InstanceTemplate()->Set(v8_str("objects"),
10983 v8::ObjectTemplate::New(isolate));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010984 t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010985 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010986 t3->SetHiddenPrototype(true);
10987 t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010988 Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010989 t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
10990
10991 // Force dictionary-based properties.
10992 i::ScopedVector<char> name_buf(1024);
10993 for (int i = 1; i <= 1000; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010994 i::SNPrintF(name_buf, "sdf%d", i);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010995 t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
10996 }
10997
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010998 Local<v8::Object> o1 = t1->GetFunction(context.local())
10999 .ToLocalChecked()
11000 ->NewInstance(context.local())
11001 .ToLocalChecked();
11002 Local<v8::Object> o2 = t2->GetFunction(context.local())
11003 .ToLocalChecked()
11004 ->NewInstance(context.local())
11005 .ToLocalChecked();
11006 Local<v8::Object> o3 = t3->GetFunction(context.local())
11007 .ToLocalChecked()
11008 ->NewInstance(context.local())
11009 .ToLocalChecked();
11010 Local<v8::Object> o4 = t4->GetFunction(context.local())
11011 .ToLocalChecked()
11012 ->NewInstance(context.local())
11013 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011014
11015 // Create prototype chain of hidden prototypes.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011016 CHECK(o4->SetPrototype(context.local(), o3).FromJust());
11017 CHECK(o3->SetPrototype(context.local(), o2).FromJust());
11018 CHECK(o2->SetPrototype(context.local(), o1).FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011019
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011020 // Call the runtime version of GetOwnPropertyNames() on the natively
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011021 // created object through JavaScript.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011022 CHECK(context->Global()->Set(context.local(), v8_str("obj"), o4).FromJust());
11023 // PROPERTY_FILTER_NONE = 0
11024 CompileRun("var names = %GetOwnPropertyKeys(obj, 0);");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011025
11026 ExpectInt32("names.length", 1006);
11027 ExpectTrue("names.indexOf(\"baz\") >= 0");
11028 ExpectTrue("names.indexOf(\"boo\") >= 0");
11029 ExpectTrue("names.indexOf(\"foo\") >= 0");
11030 ExpectTrue("names.indexOf(\"fuz1\") >= 0");
Ben Murdoch097c5b22016-05-18 11:27:45 +010011031 ExpectTrue("names.indexOf(\"objects\") >= 0");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011032 ExpectTrue("names.indexOf(\"fuz2\") >= 0");
11033 ExpectFalse("names[1005] == undefined");
11034}
11035
11036
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011037// Getting property names of an object with a hidden and inherited
11038// prototype should not duplicate the accessor properties inherited.
11039THREADED_TEST(Regress269562) {
11040 i::FLAG_allow_natives_syntax = true;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000011041 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011042 v8::HandleScope handle_scope(context->GetIsolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000011043
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011044 Local<v8::FunctionTemplate> t1 =
11045 v8::FunctionTemplate::New(context->GetIsolate());
11046 t1->SetHiddenPrototype(true);
11047
11048 Local<v8::ObjectTemplate> i1 = t1->InstanceTemplate();
11049 i1->SetAccessor(v8_str("foo"),
11050 SimpleAccessorGetter, SimpleAccessorSetter);
11051 i1->SetAccessor(v8_str("bar"),
11052 SimpleAccessorGetter, SimpleAccessorSetter);
11053 i1->SetAccessor(v8_str("baz"),
11054 SimpleAccessorGetter, SimpleAccessorSetter);
11055 i1->Set(v8_str("n1"), v8_num(1));
11056 i1->Set(v8_str("n2"), v8_num(2));
11057
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011058 Local<v8::Object> o1 = t1->GetFunction(context.local())
11059 .ToLocalChecked()
11060 ->NewInstance(context.local())
11061 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011062 Local<v8::FunctionTemplate> t2 =
11063 v8::FunctionTemplate::New(context->GetIsolate());
11064 t2->SetHiddenPrototype(true);
11065
11066 // Inherit from t1 and mark prototype as hidden.
11067 t2->Inherit(t1);
11068 t2->InstanceTemplate()->Set(v8_str("mine"), v8_num(4));
11069
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011070 Local<v8::Object> o2 = t2->GetFunction(context.local())
11071 .ToLocalChecked()
11072 ->NewInstance(context.local())
11073 .ToLocalChecked();
11074 CHECK(o2->SetPrototype(context.local(), o1).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011075
11076 v8::Local<v8::Symbol> sym =
11077 v8::Symbol::New(context->GetIsolate(), v8_str("s1"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011078 CHECK(o1->Set(context.local(), sym, v8_num(3)).FromJust());
11079 o1->SetPrivate(context.local(),
11080 v8::Private::New(context->GetIsolate(), v8_str("h1")),
11081 v8::Integer::New(context->GetIsolate(), 2013))
11082 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011083
11084 // Call the runtime version of GetOwnPropertyNames() on
11085 // the natively created object through JavaScript.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011086 CHECK(context->Global()->Set(context.local(), v8_str("obj"), o2).FromJust());
11087 CHECK(context->Global()->Set(context.local(), v8_str("sym"), sym).FromJust());
11088 // PROPERTY_FILTER_NONE = 0
11089 CompileRun("var names = %GetOwnPropertyKeys(obj, 0);");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011090
11091 ExpectInt32("names.length", 7);
11092 ExpectTrue("names.indexOf(\"foo\") >= 0");
11093 ExpectTrue("names.indexOf(\"bar\") >= 0");
11094 ExpectTrue("names.indexOf(\"baz\") >= 0");
11095 ExpectTrue("names.indexOf(\"n1\") >= 0");
11096 ExpectTrue("names.indexOf(\"n2\") >= 0");
11097 ExpectTrue("names.indexOf(sym) >= 0");
11098 ExpectTrue("names.indexOf(\"mine\") >= 0");
11099}
11100
11101
11102THREADED_TEST(FunctionReadOnlyPrototype) {
11103 LocalContext context;
11104 v8::Isolate* isolate = context->GetIsolate();
11105 v8::HandleScope handle_scope(isolate);
11106
11107 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
11108 t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
Ben Murdoch69a99ed2011-11-30 16:03:39 +000011109 t1->ReadOnlyPrototype();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011110 CHECK(context->Global()
11111 ->Set(context.local(), v8_str("func1"),
11112 t1->GetFunction(context.local()).ToLocalChecked())
11113 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000011114 // Configured value of ReadOnly flag.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011115 CHECK(
11116 CompileRun(
11117 "(function() {"
11118 " descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
11119 " return (descriptor['writable'] == false);"
11120 "})()")
11121 ->BooleanValue(context.local())
11122 .FromJust());
11123 CHECK_EQ(
11124 42,
11125 CompileRun("func1.prototype.x")->Int32Value(context.local()).FromJust());
11126 CHECK_EQ(42, CompileRun("func1.prototype = {}; func1.prototype.x")
11127 ->Int32Value(context.local())
11128 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000011129
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011130 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
11131 t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011132 CHECK(context->Global()
11133 ->Set(context.local(), v8_str("func2"),
11134 t2->GetFunction(context.local()).ToLocalChecked())
11135 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000011136 // Default value of ReadOnly flag.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011137 CHECK(
11138 CompileRun(
11139 "(function() {"
11140 " descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
11141 " return (descriptor['writable'] == true);"
11142 "})()")
11143 ->BooleanValue(context.local())
11144 .FromJust());
11145 CHECK_EQ(
11146 42,
11147 CompileRun("func2.prototype.x")->Int32Value(context.local()).FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000011148}
11149
11150
Andrei Popescu402d9372010-02-26 13:31:12 +000011151THREADED_TEST(SetPrototypeThrows) {
Andrei Popescu402d9372010-02-26 13:31:12 +000011152 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011153 v8::Isolate* isolate = context->GetIsolate();
11154 v8::HandleScope handle_scope(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000011155
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011156 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000011157
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011158 Local<v8::Object> o0 = t->GetFunction(context.local())
11159 .ToLocalChecked()
11160 ->NewInstance(context.local())
11161 .ToLocalChecked();
11162 Local<v8::Object> o1 = t->GetFunction(context.local())
11163 .ToLocalChecked()
11164 ->NewInstance(context.local())
11165 .ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000011166
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011167 CHECK(o0->SetPrototype(context.local(), o1).FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000011168 // If setting the prototype leads to the cycle, SetPrototype should
11169 // return false and keep VM in sane state.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011170 v8::TryCatch try_catch(isolate);
11171 CHECK(o1->SetPrototype(context.local(), o0).IsNothing());
Andrei Popescu402d9372010-02-26 13:31:12 +000011172 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011173 CHECK(!CcTest::i_isolate()->has_pending_exception());
Andrei Popescu402d9372010-02-26 13:31:12 +000011174
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011175 CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")
11176 ->Int32Value(context.local())
11177 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000011178}
11179
11180
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011181THREADED_TEST(FunctionRemovePrototype) {
Steve Blocka7e24c12009-10-30 11:49:00 +000011182 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011183 v8::Isolate* isolate = context->GetIsolate();
11184 v8::HandleScope handle_scope(isolate);
11185
11186 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
11187 t1->RemovePrototype();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011188 Local<v8::Function> fun = t1->GetFunction(context.local()).ToLocalChecked();
11189 CHECK(context->Global()->Set(context.local(), v8_str("fun"), fun).FromJust());
11190 CHECK(!CompileRun("'prototype' in fun")
11191 ->BooleanValue(context.local())
11192 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011193
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011194 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011195 CompileRun("new fun()");
11196 CHECK(try_catch.HasCaught());
11197
11198 try_catch.Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011199 CHECK(fun->NewInstance(context.local()).IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011200 CHECK(try_catch.HasCaught());
11201}
11202
11203
11204THREADED_TEST(GetterSetterExceptions) {
11205 LocalContext context;
11206 v8::Isolate* isolate = context->GetIsolate();
11207 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011208 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011209 "function Foo() { };"
11210 "function Throw() { throw 5; };"
11211 "var x = { };"
11212 "x.__defineSetter__('set', Throw);"
11213 "x.__defineGetter__('get', Throw);");
11214 Local<v8::Object> x = Local<v8::Object>::Cast(
11215 context->Global()->Get(context.local(), v8_str("x")).ToLocalChecked());
11216 v8::TryCatch try_catch(isolate);
11217 CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
11218 .IsNothing());
11219 CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
11220 CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
11221 .IsNothing());
11222 CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
11223 CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
11224 .IsNothing());
11225 CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
11226 CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
11227 .IsNothing());
11228 CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000011229}
11230
11231
11232THREADED_TEST(Constructor) {
Steve Blocka7e24c12009-10-30 11:49:00 +000011233 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011234 v8::Isolate* isolate = context->GetIsolate();
11235 v8::HandleScope handle_scope(isolate);
11236 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011237 templ->SetClassName(v8_str("Fun"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011238 Local<Function> cons = templ->GetFunction(context.local()).ToLocalChecked();
11239 CHECK(
11240 context->Global()->Set(context.local(), v8_str("Fun"), cons).FromJust());
11241 Local<v8::Object> inst = cons->NewInstance(context.local()).ToLocalChecked();
11242 i::Handle<i::JSReceiver> obj(v8::Utils::OpenHandle(*inst));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011243 CHECK(obj->IsJSObject());
Steve Blocka7e24c12009-10-30 11:49:00 +000011244 Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011245 CHECK(value->BooleanValue(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011246}
11247
Ben Murdoch257744e2011-11-30 15:57:28 +000011248
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011249static void ConstructorCallback(
11250 const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch257744e2011-11-30 15:57:28 +000011251 ApiTestFuzzer::Fuzz();
11252 Local<Object> This;
11253
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011254 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
Ben Murdoch257744e2011-11-30 15:57:28 +000011255 if (args.IsConstructCall()) {
11256 Local<Object> Holder = args.Holder();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011257 This = Object::New(args.GetIsolate());
Ben Murdoch257744e2011-11-30 15:57:28 +000011258 Local<Value> proto = Holder->GetPrototype();
11259 if (proto->IsObject()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011260 This->SetPrototype(context, proto).FromJust();
Ben Murdoch257744e2011-11-30 15:57:28 +000011261 }
11262 } else {
11263 This = args.This();
11264 }
11265
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011266 This->Set(context, v8_str("a"), args[0]).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011267 args.GetReturnValue().Set(This);
Ben Murdoch257744e2011-11-30 15:57:28 +000011268}
11269
11270
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011271static void FakeConstructorCallback(
11272 const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch257744e2011-11-30 15:57:28 +000011273 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011274 args.GetReturnValue().Set(args[0]);
Ben Murdoch257744e2011-11-30 15:57:28 +000011275}
11276
11277
11278THREADED_TEST(ConstructorForObject) {
Ben Murdoch257744e2011-11-30 15:57:28 +000011279 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011280 v8::Isolate* isolate = context->GetIsolate();
11281 v8::HandleScope handle_scope(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011282
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011283 {
11284 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011285 instance_template->SetCallAsFunctionHandler(ConstructorCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011286 Local<Object> instance =
11287 instance_template->NewInstance(context.local()).ToLocalChecked();
11288 CHECK(context->Global()
11289 ->Set(context.local(), v8_str("obj"), instance)
11290 .FromJust());
11291 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011292 Local<Value> value;
11293 CHECK(!try_catch.HasCaught());
11294
11295 // Call the Object's constructor with a 32-bit signed integer.
11296 value = CompileRun("(function() { var o = new obj(28); return o.a; })()");
11297 CHECK(!try_catch.HasCaught());
11298 CHECK(value->IsInt32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011299 CHECK_EQ(28, value->Int32Value(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011300
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011301 Local<Value> args1[] = {v8_num(28)};
11302 Local<Value> value_obj1 =
11303 instance->CallAsConstructor(context.local(), 1, args1).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011304 CHECK(value_obj1->IsObject());
11305 Local<Object> object1 = Local<Object>::Cast(value_obj1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011306 value = object1->Get(context.local(), v8_str("a")).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011307 CHECK(value->IsInt32());
11308 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011309 CHECK_EQ(28, value->Int32Value(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011310
11311 // Call the Object's constructor with a String.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011312 value =
11313 CompileRun("(function() { var o = new obj('tipli'); return o.a; })()");
Ben Murdoch257744e2011-11-30 15:57:28 +000011314 CHECK(!try_catch.HasCaught());
11315 CHECK(value->IsString());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011316 String::Utf8Value string_value1(
11317 value->ToString(context.local()).ToLocalChecked());
11318 CHECK_EQ(0, strcmp("tipli", *string_value1));
Ben Murdoch257744e2011-11-30 15:57:28 +000011319
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011320 Local<Value> args2[] = {v8_str("tipli")};
11321 Local<Value> value_obj2 =
11322 instance->CallAsConstructor(context.local(), 1, args2).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011323 CHECK(value_obj2->IsObject());
11324 Local<Object> object2 = Local<Object>::Cast(value_obj2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011325 value = object2->Get(context.local(), v8_str("a")).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011326 CHECK(!try_catch.HasCaught());
11327 CHECK(value->IsString());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011328 String::Utf8Value string_value2(
11329 value->ToString(context.local()).ToLocalChecked());
11330 CHECK_EQ(0, strcmp("tipli", *string_value2));
Ben Murdoch257744e2011-11-30 15:57:28 +000011331
11332 // Call the Object's constructor with a Boolean.
11333 value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
11334 CHECK(!try_catch.HasCaught());
11335 CHECK(value->IsBoolean());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011336 CHECK_EQ(true, value->BooleanValue(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011337
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011338 Local<Value> args3[] = {v8::True(isolate)};
11339 Local<Value> value_obj3 =
11340 instance->CallAsConstructor(context.local(), 1, args3).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011341 CHECK(value_obj3->IsObject());
11342 Local<Object> object3 = Local<Object>::Cast(value_obj3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011343 value = object3->Get(context.local(), v8_str("a")).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011344 CHECK(!try_catch.HasCaught());
11345 CHECK(value->IsBoolean());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011346 CHECK_EQ(true, value->BooleanValue(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011347
11348 // Call the Object's constructor with undefined.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011349 Local<Value> args4[] = {v8::Undefined(isolate)};
11350 Local<Value> value_obj4 =
11351 instance->CallAsConstructor(context.local(), 1, args4).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011352 CHECK(value_obj4->IsObject());
11353 Local<Object> object4 = Local<Object>::Cast(value_obj4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011354 value = object4->Get(context.local(), v8_str("a")).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011355 CHECK(!try_catch.HasCaught());
11356 CHECK(value->IsUndefined());
11357
11358 // Call the Object's constructor with null.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011359 Local<Value> args5[] = {v8::Null(isolate)};
11360 Local<Value> value_obj5 =
11361 instance->CallAsConstructor(context.local(), 1, args5).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011362 CHECK(value_obj5->IsObject());
11363 Local<Object> object5 = Local<Object>::Cast(value_obj5);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011364 value = object5->Get(context.local(), v8_str("a")).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011365 CHECK(!try_catch.HasCaught());
11366 CHECK(value->IsNull());
11367 }
11368
11369 // Check exception handling when there is no constructor set for the Object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011370 {
11371 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
11372 Local<Object> instance =
11373 instance_template->NewInstance(context.local()).ToLocalChecked();
11374 CHECK(context->Global()
11375 ->Set(context.local(), v8_str("obj2"), instance)
11376 .FromJust());
11377 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011378 Local<Value> value;
11379 CHECK(!try_catch.HasCaught());
11380
11381 value = CompileRun("new obj2(28)");
11382 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011383 String::Utf8Value exception_value1(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011384 CHECK_EQ(0,
11385 strcmp("TypeError: obj2 is not a constructor", *exception_value1));
Ben Murdoch257744e2011-11-30 15:57:28 +000011386 try_catch.Reset();
11387
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011388 Local<Value> args[] = {v8_num(29)};
11389 CHECK(instance->CallAsConstructor(context.local(), 1, args).IsEmpty());
Ben Murdoch257744e2011-11-30 15:57:28 +000011390 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011391 String::Utf8Value exception_value2(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011392 CHECK_EQ(
11393 0, strcmp("TypeError: object is not a constructor", *exception_value2));
Ben Murdoch257744e2011-11-30 15:57:28 +000011394 try_catch.Reset();
11395 }
11396
11397 // Check the case when constructor throws exception.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011398 {
11399 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011400 instance_template->SetCallAsFunctionHandler(ThrowValue);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011401 Local<Object> instance =
11402 instance_template->NewInstance(context.local()).ToLocalChecked();
11403 CHECK(context->Global()
11404 ->Set(context.local(), v8_str("obj3"), instance)
11405 .FromJust());
11406 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011407 Local<Value> value;
11408 CHECK(!try_catch.HasCaught());
11409
11410 value = CompileRun("new obj3(22)");
11411 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011412 String::Utf8Value exception_value1(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011413 CHECK_EQ(0, strcmp("22", *exception_value1));
Ben Murdoch257744e2011-11-30 15:57:28 +000011414 try_catch.Reset();
11415
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011416 Local<Value> args[] = {v8_num(23)};
11417 CHECK(instance->CallAsConstructor(context.local(), 1, args).IsEmpty());
Ben Murdoch257744e2011-11-30 15:57:28 +000011418 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011419 String::Utf8Value exception_value2(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011420 CHECK_EQ(0, strcmp("23", *exception_value2));
Ben Murdoch257744e2011-11-30 15:57:28 +000011421 try_catch.Reset();
11422 }
11423
11424 // Check whether constructor returns with an object or non-object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011425 {
11426 Local<FunctionTemplate> function_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011427 FunctionTemplate::New(isolate, FakeConstructorCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011428 Local<Function> function =
11429 function_template->GetFunction(context.local()).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011430 Local<Object> instance1 = function;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011431 CHECK(context->Global()
11432 ->Set(context.local(), v8_str("obj4"), instance1)
11433 .FromJust());
11434 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011435 Local<Value> value;
11436 CHECK(!try_catch.HasCaught());
11437
11438 CHECK(instance1->IsObject());
11439 CHECK(instance1->IsFunction());
11440
11441 value = CompileRun("new obj4(28)");
11442 CHECK(!try_catch.HasCaught());
11443 CHECK(value->IsObject());
11444
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011445 Local<Value> args1[] = {v8_num(28)};
11446 value = instance1->CallAsConstructor(context.local(), 1, args1)
11447 .ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011448 CHECK(!try_catch.HasCaught());
11449 CHECK(value->IsObject());
11450
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011451 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011452 instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011453 Local<Object> instance2 =
11454 instance_template->NewInstance(context.local()).ToLocalChecked();
11455 CHECK(context->Global()
11456 ->Set(context.local(), v8_str("obj5"), instance2)
11457 .FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011458 CHECK(!try_catch.HasCaught());
11459
11460 CHECK(instance2->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011461 CHECK(instance2->IsFunction());
Ben Murdoch257744e2011-11-30 15:57:28 +000011462
11463 value = CompileRun("new obj5(28)");
11464 CHECK(!try_catch.HasCaught());
11465 CHECK(!value->IsObject());
11466
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011467 Local<Value> args2[] = {v8_num(28)};
11468 value = instance2->CallAsConstructor(context.local(), 1, args2)
11469 .ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011470 CHECK(!try_catch.HasCaught());
11471 CHECK(!value->IsObject());
11472 }
11473}
11474
11475
Steve Blocka7e24c12009-10-30 11:49:00 +000011476THREADED_TEST(FunctionDescriptorException) {
Steve Blocka7e24c12009-10-30 11:49:00 +000011477 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011478 v8::Isolate* isolate = context->GetIsolate();
11479 v8::HandleScope handle_scope(isolate);
11480 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011481 templ->SetClassName(v8_str("Fun"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011482 Local<Function> cons = templ->GetFunction(context.local()).ToLocalChecked();
11483 CHECK(
11484 context->Global()->Set(context.local(), v8_str("Fun"), cons).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011485 Local<Value> value = CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011486 "function test() {"
11487 " try {"
11488 " (new Fun()).blah()"
11489 " } catch (e) {"
11490 " var str = String(e);"
11491 // " if (str.indexOf('TypeError') == -1) return 1;"
11492 // " if (str.indexOf('[object Fun]') != -1) return 2;"
11493 // " if (str.indexOf('#<Fun>') == -1) return 3;"
11494 " return 0;"
11495 " }"
11496 " return 4;"
11497 "}"
11498 "test();");
11499 CHECK_EQ(0, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011500}
11501
11502
11503THREADED_TEST(EvalAliasedDynamic) {
Steve Blocka7e24c12009-10-30 11:49:00 +000011504 LocalContext current;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011505 v8::HandleScope scope(current->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000011506
11507 // Tests where aliased eval can only be resolved dynamically.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011508 Local<Script> script = v8_compile(
11509 "function f(x) { "
11510 " var foo = 2;"
11511 " with (x) { return eval('foo'); }"
11512 "}"
11513 "foo = 0;"
11514 "result1 = f(new Object());"
11515 "result2 = f(this);"
11516 "var x = new Object();"
11517 "x.eval = function(x) { return 1; };"
11518 "result3 = f(x);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011519 script->Run(current.local()).ToLocalChecked();
11520 CHECK_EQ(2, current->Global()
11521 ->Get(current.local(), v8_str("result1"))
11522 .ToLocalChecked()
11523 ->Int32Value(current.local())
11524 .FromJust());
11525 CHECK_EQ(0, current->Global()
11526 ->Get(current.local(), v8_str("result2"))
11527 .ToLocalChecked()
11528 ->Int32Value(current.local())
11529 .FromJust());
11530 CHECK_EQ(1, current->Global()
11531 ->Get(current.local(), v8_str("result3"))
11532 .ToLocalChecked()
11533 ->Int32Value(current.local())
11534 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011535
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011536 v8::TryCatch try_catch(current->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011537 script = v8_compile(
11538 "function f(x) { "
11539 " var bar = 2;"
11540 " with (x) { return eval('bar'); }"
11541 "}"
11542 "result4 = f(this)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011543 script->Run(current.local()).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011544 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011545 CHECK_EQ(2, current->Global()
11546 ->Get(current.local(), v8_str("result4"))
11547 .ToLocalChecked()
11548 ->Int32Value(current.local())
11549 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011550
Steve Blocka7e24c12009-10-30 11:49:00 +000011551 try_catch.Reset();
11552}
11553
11554
11555THREADED_TEST(CrossEval) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011556 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000011557 LocalContext other;
11558 LocalContext current;
11559
11560 Local<String> token = v8_str("<security token>");
11561 other->SetSecurityToken(token);
11562 current->SetSecurityToken(token);
11563
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011564 // Set up reference from current to other.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011565 CHECK(current->Global()
11566 ->Set(current.local(), v8_str("other"), other->Global())
11567 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011568
11569 // Check that new variables are introduced in other context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011570 Local<Script> script = v8_compile("other.eval('var foo = 1234')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011571 script->Run(current.local()).ToLocalChecked();
11572 Local<Value> foo =
11573 other->Global()->Get(current.local(), v8_str("foo")).ToLocalChecked();
11574 CHECK_EQ(1234, foo->Int32Value(other.local()).FromJust());
11575 CHECK(!current->Global()->Has(current.local(), v8_str("foo")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011576
11577 // Check that writing to non-existing properties introduces them in
11578 // the other context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011579 script = v8_compile("other.eval('na = 1234')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011580 script->Run(current.local()).ToLocalChecked();
11581 CHECK_EQ(1234, other->Global()
11582 ->Get(current.local(), v8_str("na"))
11583 .ToLocalChecked()
11584 ->Int32Value(other.local())
11585 .FromJust());
11586 CHECK(!current->Global()->Has(current.local(), v8_str("na")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011587
11588 // Check that global variables in current context are not visible in other
11589 // context.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011590 v8::TryCatch try_catch(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011591 script = v8_compile("var bar = 42; other.eval('bar');");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011592 CHECK(script->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000011593 CHECK(try_catch.HasCaught());
11594 try_catch.Reset();
11595
11596 // Check that local variables in current context are not visible in other
11597 // context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011598 script = v8_compile(
11599 "(function() { "
11600 " var baz = 87;"
11601 " return other.eval('baz');"
11602 "})();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011603 CHECK(script->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000011604 CHECK(try_catch.HasCaught());
11605 try_catch.Reset();
11606
11607 // Check that global variables in the other environment are visible
11608 // when evaluting code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011609 CHECK(other->Global()
11610 ->Set(other.local(), v8_str("bis"), v8_num(1234))
11611 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011612 script = v8_compile("other.eval('bis')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011613 CHECK_EQ(1234, script->Run(current.local())
11614 .ToLocalChecked()
11615 ->Int32Value(current.local())
11616 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011617 CHECK(!try_catch.HasCaught());
11618
11619 // Check that the 'this' pointer points to the global object evaluating
11620 // code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011621 CHECK(other->Global()
11622 ->Set(current.local(), v8_str("t"), other->Global())
11623 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011624 script = v8_compile("other.eval('this == t')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011625 Local<Value> result = script->Run(current.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000011626 CHECK(result->IsTrue());
11627 CHECK(!try_catch.HasCaught());
11628
11629 // Check that variables introduced in with-statement are not visible in
11630 // other context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011631 script = v8_compile("with({x:2}){other.eval('x')}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011632 CHECK(script->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000011633 CHECK(try_catch.HasCaught());
11634 try_catch.Reset();
11635
11636 // Check that you cannot use 'eval.call' with another object than the
11637 // current global object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011638 script = v8_compile("other.y = 1; eval.call(other, 'y')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011639 CHECK(script->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000011640 CHECK(try_catch.HasCaught());
11641}
11642
11643
11644// Test that calling eval in a context which has been detached from
Emily Bernierd0a1eb72015-03-24 16:35:39 -040011645// its global proxy works.
Steve Blocka7e24c12009-10-30 11:49:00 +000011646THREADED_TEST(EvalInDetachedGlobal) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011647 v8::Isolate* isolate = CcTest::isolate();
11648 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011649
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011650 v8::Local<Context> context0 = Context::New(isolate);
11651 v8::Local<Context> context1 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011652
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011653 // Set up function in context0 that uses eval from context0.
Steve Blocka7e24c12009-10-30 11:49:00 +000011654 context0->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011655 v8::Local<v8::Value> fun = CompileRun(
11656 "var x = 42;"
11657 "(function() {"
11658 " var e = eval;"
11659 " return function(s) { return e(s); }"
11660 "})()");
Steve Blocka7e24c12009-10-30 11:49:00 +000011661 context0->Exit();
11662
11663 // Put the function into context1 and call it before and after
11664 // detaching the global. Before detaching, the call succeeds and
11665 // after detaching and exception is thrown.
11666 context1->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011667 CHECK(context1->Global()->Set(context1, v8_str("fun"), fun).FromJust());
11668 v8::Local<v8::Value> x_value = CompileRun("fun('x')");
11669 CHECK_EQ(42, x_value->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011670 context0->DetachGlobal();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011671 v8::TryCatch catcher(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011672 x_value = CompileRun("fun('x')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011673 CHECK_EQ(42, x_value->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011674 context1->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +000011675}
11676
11677
11678THREADED_TEST(CrossLazyLoad) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011679 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000011680 LocalContext other;
11681 LocalContext current;
11682
11683 Local<String> token = v8_str("<security token>");
11684 other->SetSecurityToken(token);
11685 current->SetSecurityToken(token);
11686
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011687 // Set up reference from current to other.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011688 CHECK(current->Global()
11689 ->Set(current.local(), v8_str("other"), other->Global())
11690 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011691
11692 // Trigger lazy loading in other context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011693 Local<Script> script = v8_compile("other.eval('new Date(42)')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011694 Local<Value> value = script->Run(current.local()).ToLocalChecked();
11695 CHECK_EQ(42.0, value->NumberValue(current.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011696}
11697
11698
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011699static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
Andrei Popescu402d9372010-02-26 13:31:12 +000011700 ApiTestFuzzer::Fuzz();
Steve Blocka7e24c12009-10-30 11:49:00 +000011701 if (args.IsConstructCall()) {
11702 if (args[0]->IsInt32()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011703 args.GetReturnValue().Set(
11704 v8_num(-args[0]
11705 ->Int32Value(args.GetIsolate()->GetCurrentContext())
11706 .FromJust()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011707 return;
Steve Blocka7e24c12009-10-30 11:49:00 +000011708 }
11709 }
11710
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011711 args.GetReturnValue().Set(args[0]);
11712}
11713
11714
11715static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
11716 args.GetReturnValue().Set(args.This());
Steve Blocka7e24c12009-10-30 11:49:00 +000011717}
11718
11719
11720// Test that a call handler can be set for objects which will allow
11721// non-function objects created through the API to be called as
11722// functions.
11723THREADED_TEST(CallAsFunction) {
Steve Blocka7e24c12009-10-30 11:49:00 +000011724 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011725 v8::Isolate* isolate = context->GetIsolate();
11726 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011727
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011728 {
11729 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011730 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
11731 instance_template->SetCallAsFunctionHandler(call_as_function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011732 Local<v8::Object> instance = t->GetFunction(context.local())
11733 .ToLocalChecked()
11734 ->NewInstance(context.local())
11735 .ToLocalChecked();
11736 CHECK(context->Global()
11737 ->Set(context.local(), v8_str("obj"), instance)
11738 .FromJust());
11739 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011740 Local<Value> value;
11741 CHECK(!try_catch.HasCaught());
Steve Blocka7e24c12009-10-30 11:49:00 +000011742
Ben Murdoch257744e2011-11-30 15:57:28 +000011743 value = CompileRun("obj(42)");
11744 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011745 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011746
Ben Murdoch257744e2011-11-30 15:57:28 +000011747 value = CompileRun("(function(o){return o(49)})(obj)");
11748 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011749 CHECK_EQ(49, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011750
Ben Murdoch257744e2011-11-30 15:57:28 +000011751 // test special case of call as function
11752 value = CompileRun("[obj]['0'](45)");
11753 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011754 CHECK_EQ(45, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011755
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011756 value = CompileRun(
11757 "obj.call = Function.prototype.call;"
11758 "obj.call(null, 87)");
Ben Murdoch257744e2011-11-30 15:57:28 +000011759 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011760 CHECK_EQ(87, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011761
Ben Murdoch257744e2011-11-30 15:57:28 +000011762 // Regression tests for bug #1116356: Calling call through call/apply
11763 // must work for non-function receivers.
11764 const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
11765 value = CompileRun(apply_99);
11766 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011767 CHECK_EQ(99, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011768
Ben Murdoch257744e2011-11-30 15:57:28 +000011769 const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
11770 value = CompileRun(call_17);
11771 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011772 CHECK_EQ(17, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011773
Ben Murdoch257744e2011-11-30 15:57:28 +000011774 // Check that the call-as-function handler can be called through
11775 // new.
11776 value = CompileRun("new obj(43)");
11777 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011778 CHECK_EQ(-43, value->Int32Value(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011779
11780 // Check that the call-as-function handler can be called through
11781 // the API.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011782 v8::Local<Value> args[] = {v8_num(28)};
11783 value = instance->CallAsFunction(context.local(), instance, 1, args)
11784 .ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011785 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011786 CHECK_EQ(28, value->Int32Value(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011787 }
11788
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011789 {
11790 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011791 Local<ObjectTemplate> instance_template(t->InstanceTemplate());
11792 USE(instance_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011793 Local<v8::Object> instance = t->GetFunction(context.local())
11794 .ToLocalChecked()
11795 ->NewInstance(context.local())
11796 .ToLocalChecked();
11797 CHECK(context->Global()
11798 ->Set(context.local(), v8_str("obj2"), instance)
11799 .FromJust());
11800 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011801 Local<Value> value;
11802 CHECK(!try_catch.HasCaught());
11803
11804 // Call an object without call-as-function handler through the JS
11805 value = CompileRun("obj2(28)");
11806 CHECK(value.IsEmpty());
11807 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011808 String::Utf8Value exception_value1(try_catch.Exception());
11809 // TODO(verwaest): Better message
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011810 CHECK_EQ(0, strcmp("TypeError: obj2 is not a function", *exception_value1));
Ben Murdoch257744e2011-11-30 15:57:28 +000011811 try_catch.Reset();
11812
11813 // Call an object without call-as-function handler through the API
11814 value = CompileRun("obj2(28)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011815 v8::Local<Value> args[] = {v8_num(28)};
11816 CHECK(
11817 instance->CallAsFunction(context.local(), instance, 1, args).IsEmpty());
Ben Murdoch257744e2011-11-30 15:57:28 +000011818 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011819 String::Utf8Value exception_value2(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011820 CHECK_EQ(0,
11821 strcmp("TypeError: object is not a function", *exception_value2));
Ben Murdoch257744e2011-11-30 15:57:28 +000011822 try_catch.Reset();
11823 }
11824
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011825 {
11826 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011827 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
11828 instance_template->SetCallAsFunctionHandler(ThrowValue);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011829 Local<v8::Object> instance = t->GetFunction(context.local())
11830 .ToLocalChecked()
11831 ->NewInstance(context.local())
11832 .ToLocalChecked();
11833 CHECK(context->Global()
11834 ->Set(context.local(), v8_str("obj3"), instance)
11835 .FromJust());
11836 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011837 Local<Value> value;
11838 CHECK(!try_catch.HasCaught());
11839
11840 // Catch the exception which is thrown by call-as-function handler
11841 value = CompileRun("obj3(22)");
11842 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011843 String::Utf8Value exception_value1(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011844 CHECK_EQ(0, strcmp("22", *exception_value1));
Ben Murdoch257744e2011-11-30 15:57:28 +000011845 try_catch.Reset();
11846
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011847 v8::Local<Value> args[] = {v8_num(23)};
11848 CHECK(
11849 instance->CallAsFunction(context.local(), instance, 1, args).IsEmpty());
Ben Murdoch257744e2011-11-30 15:57:28 +000011850 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011851 String::Utf8Value exception_value2(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011852 CHECK_EQ(0, strcmp("23", *exception_value2));
Ben Murdoch257744e2011-11-30 15:57:28 +000011853 try_catch.Reset();
11854 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011855
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011856 {
11857 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011858 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
11859 instance_template->SetCallAsFunctionHandler(ReturnThis);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011860 Local<v8::Object> instance = t->GetFunction(context.local())
11861 .ToLocalChecked()
11862 ->NewInstance(context.local())
11863 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011864
11865 Local<v8::Value> a1 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011866 instance->CallAsFunction(context.local(), v8::Undefined(isolate), 0,
11867 NULL)
11868 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011869 CHECK(a1->StrictEquals(instance));
11870 Local<v8::Value> a2 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011871 instance->CallAsFunction(context.local(), v8::Null(isolate), 0, NULL)
11872 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011873 CHECK(a2->StrictEquals(instance));
11874 Local<v8::Value> a3 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011875 instance->CallAsFunction(context.local(), v8_num(42), 0, NULL)
11876 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011877 CHECK(a3->StrictEquals(instance));
11878 Local<v8::Value> a4 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011879 instance->CallAsFunction(context.local(), v8_str("hello"), 0, NULL)
11880 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011881 CHECK(a4->StrictEquals(instance));
11882 Local<v8::Value> a5 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011883 instance->CallAsFunction(context.local(), v8::True(isolate), 0, NULL)
11884 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011885 CHECK(a5->StrictEquals(instance));
11886 }
11887
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011888 {
11889 CompileRun(
11890 "function ReturnThisSloppy() {"
11891 " return this;"
11892 "}"
11893 "function ReturnThisStrict() {"
11894 " 'use strict';"
11895 " return this;"
11896 "}");
11897 Local<Function> ReturnThisSloppy = Local<Function>::Cast(
11898 context->Global()
11899 ->Get(context.local(), v8_str("ReturnThisSloppy"))
11900 .ToLocalChecked());
11901 Local<Function> ReturnThisStrict = Local<Function>::Cast(
11902 context->Global()
11903 ->Get(context.local(), v8_str("ReturnThisStrict"))
11904 .ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011905
11906 Local<v8::Value> a1 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011907 ReturnThisSloppy->CallAsFunction(context.local(),
11908 v8::Undefined(isolate), 0, NULL)
11909 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011910 CHECK(a1->StrictEquals(context->Global()));
11911 Local<v8::Value> a2 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011912 ReturnThisSloppy->CallAsFunction(context.local(), v8::Null(isolate), 0,
11913 NULL)
11914 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011915 CHECK(a2->StrictEquals(context->Global()));
11916 Local<v8::Value> a3 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011917 ReturnThisSloppy->CallAsFunction(context.local(), v8_num(42), 0, NULL)
11918 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011919 CHECK(a3->IsNumberObject());
11920 CHECK_EQ(42.0, a3.As<v8::NumberObject>()->ValueOf());
11921 Local<v8::Value> a4 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011922 ReturnThisSloppy->CallAsFunction(context.local(), v8_str("hello"), 0,
11923 NULL)
11924 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011925 CHECK(a4->IsStringObject());
11926 CHECK(a4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
11927 Local<v8::Value> a5 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011928 ReturnThisSloppy->CallAsFunction(context.local(), v8::True(isolate), 0,
11929 NULL)
11930 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011931 CHECK(a5->IsBooleanObject());
11932 CHECK(a5.As<v8::BooleanObject>()->ValueOf());
11933
11934 Local<v8::Value> a6 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011935 ReturnThisStrict->CallAsFunction(context.local(),
11936 v8::Undefined(isolate), 0, NULL)
11937 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011938 CHECK(a6->IsUndefined());
11939 Local<v8::Value> a7 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011940 ReturnThisStrict->CallAsFunction(context.local(), v8::Null(isolate), 0,
11941 NULL)
11942 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011943 CHECK(a7->IsNull());
11944 Local<v8::Value> a8 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011945 ReturnThisStrict->CallAsFunction(context.local(), v8_num(42), 0, NULL)
11946 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011947 CHECK(a8->StrictEquals(v8_num(42)));
11948 Local<v8::Value> a9 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011949 ReturnThisStrict->CallAsFunction(context.local(), v8_str("hello"), 0,
11950 NULL)
11951 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011952 CHECK(a9->StrictEquals(v8_str("hello")));
11953 Local<v8::Value> a10 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011954 ReturnThisStrict->CallAsFunction(context.local(), v8::True(isolate), 0,
11955 NULL)
11956 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011957 CHECK(a10->StrictEquals(v8::True(isolate)));
11958 }
Ben Murdoch257744e2011-11-30 15:57:28 +000011959}
11960
11961
11962// Check whether a non-function object is callable.
11963THREADED_TEST(CallableObject) {
Ben Murdoch257744e2011-11-30 15:57:28 +000011964 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011965 v8::Isolate* isolate = context->GetIsolate();
11966 v8::HandleScope scope(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011967
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011968 {
11969 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011970 instance_template->SetCallAsFunctionHandler(call_as_function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011971 Local<Object> instance =
11972 instance_template->NewInstance(context.local()).ToLocalChecked();
11973 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011974
11975 CHECK(instance->IsCallable());
11976 CHECK(!try_catch.HasCaught());
11977 }
11978
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011979 {
11980 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
11981 Local<Object> instance =
11982 instance_template->NewInstance(context.local()).ToLocalChecked();
11983 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011984
11985 CHECK(!instance->IsCallable());
11986 CHECK(!try_catch.HasCaught());
11987 }
11988
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011989 {
11990 Local<FunctionTemplate> function_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011991 FunctionTemplate::New(isolate, call_as_function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011992 Local<Function> function =
11993 function_template->GetFunction(context.local()).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011994 Local<Object> instance = function;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011995 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011996
11997 CHECK(instance->IsCallable());
11998 CHECK(!try_catch.HasCaught());
11999 }
12000
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012001 {
12002 Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate);
12003 Local<Function> function =
12004 function_template->GetFunction(context.local()).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000012005 Local<Object> instance = function;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012006 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000012007
12008 CHECK(instance->IsCallable());
12009 CHECK(!try_catch.HasCaught());
12010 }
Steve Blocka7e24c12009-10-30 11:49:00 +000012011}
12012
12013
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012014THREADED_TEST(Regress567998) {
12015 LocalContext env;
12016 v8::HandleScope scope(env->GetIsolate());
12017
12018 Local<v8::FunctionTemplate> desc =
12019 v8::FunctionTemplate::New(env->GetIsolate());
12020 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
12021 desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis); // callable
12022
12023 Local<v8::Object> obj = desc->GetFunction(env.local())
12024 .ToLocalChecked()
12025 ->NewInstance(env.local())
12026 .ToLocalChecked();
12027 CHECK(
12028 env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
12029
12030 ExpectString("undetectable.toString()", "[object Object]");
12031 ExpectString("typeof undetectable", "undefined");
12032 ExpectString("typeof(undetectable)", "undefined");
12033 ExpectBoolean("typeof undetectable == 'undefined'", true);
12034 ExpectBoolean("typeof undetectable == 'object'", false);
12035 ExpectBoolean("if (undetectable) { true; } else { false; }", false);
12036 ExpectBoolean("!undetectable", true);
12037
12038 ExpectObject("true&&undetectable", obj);
12039 ExpectBoolean("false&&undetectable", false);
12040 ExpectBoolean("true||undetectable", true);
12041 ExpectObject("false||undetectable", obj);
12042
12043 ExpectObject("undetectable&&true", obj);
12044 ExpectObject("undetectable&&false", obj);
12045 ExpectBoolean("undetectable||true", true);
12046 ExpectBoolean("undetectable||false", false);
12047
12048 ExpectBoolean("undetectable==null", true);
12049 ExpectBoolean("null==undetectable", true);
12050 ExpectBoolean("undetectable==undefined", true);
12051 ExpectBoolean("undefined==undetectable", true);
12052 ExpectBoolean("undetectable==undetectable", true);
12053
12054 ExpectBoolean("undetectable===null", false);
12055 ExpectBoolean("null===undetectable", false);
12056 ExpectBoolean("undetectable===undefined", false);
12057 ExpectBoolean("undefined===undetectable", false);
12058 ExpectBoolean("undetectable===undetectable", true);
12059}
12060
12061
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012062static int Recurse(v8::Isolate* isolate, int depth, int iterations) {
12063 v8::HandleScope scope(isolate);
12064 if (depth == 0) return v8::HandleScope::NumberOfHandles(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000012065 for (int i = 0; i < iterations; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012066 Local<v8::Number> n(v8::Integer::New(isolate, 42));
Steve Blocka7e24c12009-10-30 11:49:00 +000012067 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012068 return Recurse(isolate, depth - 1, iterations);
Steve Blocka7e24c12009-10-30 11:49:00 +000012069}
12070
12071
12072THREADED_TEST(HandleIteration) {
12073 static const int kIterations = 500;
12074 static const int kNesting = 200;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012075 LocalContext context;
12076 v8::Isolate* isolate = context->GetIsolate();
12077 v8::HandleScope scope0(isolate);
12078 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000012079 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012080 v8::HandleScope scope1(isolate);
12081 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000012082 for (int i = 0; i < kIterations; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012083 Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
12084 CHECK_EQ(i + 1, v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000012085 }
12086
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012087 CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000012088 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012089 v8::HandleScope scope2(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000012090 for (int j = 0; j < kIterations; j++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012091 Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
12092 CHECK_EQ(j + 1 + kIterations,
12093 v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000012094 }
12095 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012096 CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000012097 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012098 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
12099 CHECK_EQ(kNesting * kIterations, Recurse(isolate, kNesting, kIterations));
Steve Blocka7e24c12009-10-30 11:49:00 +000012100}
12101
12102
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012103static void InterceptorCallICFastApi(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012104 Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012105 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012106 CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
12107 int* call_count =
12108 reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
Andrei Popescu402d9372010-02-26 13:31:12 +000012109 ++(*call_count);
12110 if ((*call_count) % 20 == 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012111 CcTest::heap()->CollectAllGarbage();
Andrei Popescu402d9372010-02-26 13:31:12 +000012112 }
Andrei Popescu402d9372010-02-26 13:31:12 +000012113}
12114
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012115static void FastApiCallback_TrivialSignature(
12116 const v8::FunctionCallbackInfo<v8::Value>& args) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012117 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012118 CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
12119 v8::Isolate* isolate = CcTest::isolate();
12120 CHECK_EQ(isolate, args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012121 CHECK(args.This()
12122 ->Equals(isolate->GetCurrentContext(), args.Holder())
12123 .FromJust());
12124 CHECK(args.Data()
12125 ->Equals(isolate->GetCurrentContext(), v8_str("method_data"))
12126 .FromJust());
12127 args.GetReturnValue().Set(
12128 args[0]->Int32Value(isolate->GetCurrentContext()).FromJust() + 1);
Andrei Popescu402d9372010-02-26 13:31:12 +000012129}
12130
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012131static void FastApiCallback_SimpleSignature(
12132 const v8::FunctionCallbackInfo<v8::Value>& args) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012133 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012134 CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
12135 v8::Isolate* isolate = CcTest::isolate();
12136 CHECK_EQ(isolate, args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012137 CHECK(args.This()
12138 ->GetPrototype()
12139 ->Equals(isolate->GetCurrentContext(), args.Holder())
12140 .FromJust());
12141 CHECK(args.Data()
12142 ->Equals(isolate->GetCurrentContext(), v8_str("method_data"))
12143 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012144 // Note, we're using HasRealNamedProperty instead of Has to avoid
12145 // invoking the interceptor again.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012146 CHECK(args.Holder()
12147 ->HasRealNamedProperty(isolate->GetCurrentContext(), v8_str("foo"))
12148 .FromJust());
12149 args.GetReturnValue().Set(
12150 args[0]->Int32Value(isolate->GetCurrentContext()).FromJust() + 1);
Andrei Popescu402d9372010-02-26 13:31:12 +000012151}
12152
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012153
Andrei Popescu402d9372010-02-26 13:31:12 +000012154// Helper to maximize the odds of object moving.
12155static void GenerateSomeGarbage() {
12156 CompileRun(
12157 "var garbage;"
12158 "for (var i = 0; i < 1000; i++) {"
12159 " garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
12160 "}"
12161 "garbage = undefined;");
12162}
12163
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012164
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012165void DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Block1e0659c2011-05-24 12:43:12 +010012166 static int count = 0;
12167 if (count++ % 3 == 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012168 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012169 // This should move the stub
Steve Block1e0659c2011-05-24 12:43:12 +010012170 GenerateSomeGarbage(); // This should ensure the old stub memory is flushed
12171 }
Steve Block1e0659c2011-05-24 12:43:12 +010012172}
12173
12174
12175THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
Steve Block1e0659c2011-05-24 12:43:12 +010012176 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012177 v8::Isolate* isolate = context->GetIsolate();
12178 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012179 v8::Local<v8::ObjectTemplate> nativeobject_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012180 v8::ObjectTemplate::New(isolate);
12181 nativeobject_templ->Set(isolate, "callback",
12182 v8::FunctionTemplate::New(isolate,
12183 DirectApiCallback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012184 v8::Local<v8::Object> nativeobject_obj =
12185 nativeobject_templ->NewInstance(context.local()).ToLocalChecked();
12186 CHECK(context->Global()
12187 ->Set(context.local(), v8_str("nativeobject"), nativeobject_obj)
12188 .FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +010012189 // call the api function multiple times to ensure direct call stub creation.
12190 CompileRun(
12191 "function f() {"
12192 " for (var i = 1; i <= 30; i++) {"
12193 " nativeobject.callback();"
12194 " }"
12195 "}"
12196 "f();");
12197}
12198
12199
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012200void ThrowingDirectApiCallback(
12201 const v8::FunctionCallbackInfo<v8::Value>& args) {
12202 args.GetIsolate()->ThrowException(v8_str("g"));
Steve Block1e0659c2011-05-24 12:43:12 +010012203}
12204
12205
12206THREADED_TEST(CallICFastApi_DirectCall_Throw) {
Steve Block1e0659c2011-05-24 12:43:12 +010012207 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012208 v8::Isolate* isolate = context->GetIsolate();
12209 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012210 v8::Local<v8::ObjectTemplate> nativeobject_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012211 v8::ObjectTemplate::New(isolate);
12212 nativeobject_templ->Set(isolate, "callback",
12213 v8::FunctionTemplate::New(isolate,
12214 ThrowingDirectApiCallback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012215 v8::Local<v8::Object> nativeobject_obj =
12216 nativeobject_templ->NewInstance(context.local()).ToLocalChecked();
12217 CHECK(context->Global()
12218 ->Set(context.local(), v8_str("nativeobject"), nativeobject_obj)
12219 .FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +010012220 // call the api function multiple times to ensure direct call stub creation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012221 v8::Local<Value> result = CompileRun(
Steve Block1e0659c2011-05-24 12:43:12 +010012222 "var result = '';"
12223 "function f() {"
12224 " for (var i = 1; i <= 5; i++) {"
12225 " try { nativeobject.callback(); } catch (e) { result += e; }"
12226 " }"
12227 "}"
12228 "f(); result;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012229 CHECK(v8_str("ggggg")->Equals(context.local(), result).FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +010012230}
12231
12232
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012233static int p_getter_count_3;
12234
12235
12236static Local<Value> DoDirectGetter() {
12237 if (++p_getter_count_3 % 3 == 0) {
12238 CcTest::heap()->CollectAllGarbage();
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012239 GenerateSomeGarbage();
12240 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012241 return v8_str("Direct Getter Result");
12242}
12243
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012244
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012245static void DirectGetterCallback(
12246 Local<String> name,
12247 const v8::PropertyCallbackInfo<v8::Value>& info) {
12248 CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
12249 info.GetReturnValue().Set(DoDirectGetter());
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012250}
12251
12252
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012253template<typename Accessor>
12254static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012255 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012256 v8::Isolate* isolate = context->GetIsolate();
12257 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012258 v8::Local<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012259 obj->SetAccessor(v8_str("p1"), accessor);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012260 CHECK(context->Global()
12261 ->Set(context.local(), v8_str("o1"),
12262 obj->NewInstance(context.local()).ToLocalChecked())
12263 .FromJust());
12264 p_getter_count_3 = 0;
12265 v8::Local<v8::Value> result = CompileRun(
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012266 "function f() {"
12267 " for (var i = 0; i < 30; i++) o1.p1;"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012268 " return o1.p1"
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012269 "}"
12270 "f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012271 CHECK(v8_str("Direct Getter Result")
12272 ->Equals(context.local(), result)
12273 .FromJust());
12274 CHECK_EQ(31, p_getter_count_3);
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012275}
12276
12277
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012278THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
12279 LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
12280}
12281
12282
12283void ThrowingDirectGetterCallback(
12284 Local<String> name,
12285 const v8::PropertyCallbackInfo<v8::Value>& info) {
12286 info.GetIsolate()->ThrowException(v8_str("g"));
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012287}
12288
12289
12290THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012291 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012292 v8::Isolate* isolate = context->GetIsolate();
12293 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012294 v8::Local<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012295 obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012296 CHECK(context->Global()
12297 ->Set(context.local(), v8_str("o1"),
12298 obj->NewInstance(context.local()).ToLocalChecked())
12299 .FromJust());
12300 v8::Local<Value> result = CompileRun(
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012301 "var result = '';"
12302 "for (var i = 0; i < 5; i++) {"
12303 " try { o1.p1; } catch (e) { result += e; }"
12304 "}"
12305 "result;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012306 CHECK(v8_str("ggggg")->Equals(context.local(), result).FromJust());
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012307}
12308
12309
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012310THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012311 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012312 v8::Isolate* isolate = CcTest::isolate();
12313 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012314 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012315 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012316 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
12317 isolate, FastApiCallback_TrivialSignature, v8_str("method_data"),
12318 v8::Local<v8::Signature>());
12319 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012320 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012321 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012322 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012323 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012324 v8::External::New(isolate, &interceptor_call_count)));
Andrei Popescu402d9372010-02-26 13:31:12 +000012325 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012326 v8::Local<v8::Function> fun =
12327 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012328 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012329 CHECK(context->Global()
12330 ->Set(context.local(), v8_str("o"),
12331 fun->NewInstance(context.local()).ToLocalChecked())
12332 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012333 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012334 "var result = 0;"
12335 "for (var i = 0; i < 100; i++) {"
12336 " result = o.method(41);"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012337 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012338 CHECK_EQ(42, context->Global()
12339 ->Get(context.local(), v8_str("result"))
12340 .ToLocalChecked()
12341 ->Int32Value(context.local())
12342 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012343 CHECK_EQ(100, interceptor_call_count);
12344}
12345
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012346
12347THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012348 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012349 v8::Isolate* isolate = CcTest::isolate();
12350 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012351 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012352 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012353 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012354 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12355 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012356 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012357 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012358 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012359 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012360 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012361 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012362 v8::External::New(isolate, &interceptor_call_count)));
Andrei Popescu402d9372010-02-26 13:31:12 +000012363 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012364 v8::Local<v8::Function> fun =
12365 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012366 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012367 CHECK(context->Global()
12368 ->Set(context.local(), v8_str("o"),
12369 fun->NewInstance(context.local()).ToLocalChecked())
12370 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012371 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012372 "o.foo = 17;"
12373 "var receiver = {};"
12374 "receiver.__proto__ = o;"
12375 "var result = 0;"
12376 "for (var i = 0; i < 100; i++) {"
12377 " result = receiver.method(41);"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012378 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012379 CHECK_EQ(42, context->Global()
12380 ->Get(context.local(), v8_str("result"))
12381 .ToLocalChecked()
12382 ->Int32Value(context.local())
12383 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012384 CHECK_EQ(100, interceptor_call_count);
12385}
12386
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012387
12388THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012389 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012390 v8::Isolate* isolate = CcTest::isolate();
12391 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012392 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012393 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012394 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012395 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12396 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012397 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012398 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012399 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012400 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012401 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012402 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012403 v8::External::New(isolate, &interceptor_call_count)));
Andrei Popescu402d9372010-02-26 13:31:12 +000012404 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012405 v8::Local<v8::Function> fun =
12406 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012407 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012408 CHECK(context->Global()
12409 ->Set(context.local(), v8_str("o"),
12410 fun->NewInstance(context.local()).ToLocalChecked())
12411 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012412 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012413 "o.foo = 17;"
12414 "var receiver = {};"
12415 "receiver.__proto__ = o;"
12416 "var result = 0;"
12417 "var saved_result = 0;"
12418 "for (var i = 0; i < 100; i++) {"
12419 " result = receiver.method(41);"
12420 " if (i == 50) {"
12421 " saved_result = result;"
12422 " receiver = {method: function(x) { return x - 1 }};"
12423 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012424 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012425 CHECK_EQ(40, context->Global()
12426 ->Get(context.local(), v8_str("result"))
12427 .ToLocalChecked()
12428 ->Int32Value(context.local())
12429 .FromJust());
12430 CHECK_EQ(42, context->Global()
12431 ->Get(context.local(), v8_str("saved_result"))
12432 .ToLocalChecked()
12433 ->Int32Value(context.local())
12434 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012435 CHECK_GE(interceptor_call_count, 50);
12436}
12437
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012438
12439THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012440 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012441 v8::Isolate* isolate = CcTest::isolate();
12442 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012443 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012444 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012445 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012446 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12447 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012448 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012449 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012450 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012451 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012452 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012453 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012454 v8::External::New(isolate, &interceptor_call_count)));
Andrei Popescu402d9372010-02-26 13:31:12 +000012455 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012456 v8::Local<v8::Function> fun =
12457 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012458 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012459 CHECK(context->Global()
12460 ->Set(context.local(), v8_str("o"),
12461 fun->NewInstance(context.local()).ToLocalChecked())
12462 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012463 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012464 "o.foo = 17;"
12465 "var receiver = {};"
12466 "receiver.__proto__ = o;"
12467 "var result = 0;"
12468 "var saved_result = 0;"
12469 "for (var i = 0; i < 100; i++) {"
12470 " result = receiver.method(41);"
12471 " if (i == 50) {"
12472 " saved_result = result;"
12473 " o.method = function(x) { return x - 1 };"
12474 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012475 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012476 CHECK_EQ(40, context->Global()
12477 ->Get(context.local(), v8_str("result"))
12478 .ToLocalChecked()
12479 ->Int32Value(context.local())
12480 .FromJust());
12481 CHECK_EQ(42, context->Global()
12482 ->Get(context.local(), v8_str("saved_result"))
12483 .ToLocalChecked()
12484 ->Int32Value(context.local())
12485 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012486 CHECK_GE(interceptor_call_count, 50);
12487}
12488
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012489
12490THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
Steve Block6ded16b2010-05-10 14:33:55 +010012491 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012492 v8::Isolate* isolate = CcTest::isolate();
12493 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012494 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012495 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012496 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012497 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12498 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012499 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Steve Block6ded16b2010-05-10 14:33:55 +010012500 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012501 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012502 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012503 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012504 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012505 v8::External::New(isolate, &interceptor_call_count)));
Steve Block6ded16b2010-05-10 14:33:55 +010012506 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012507 v8::Local<v8::Function> fun =
12508 fun_templ->GetFunction(context.local()).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +010012509 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012510 CHECK(context->Global()
12511 ->Set(context.local(), v8_str("o"),
12512 fun->NewInstance(context.local()).ToLocalChecked())
12513 .FromJust());
12514 v8::TryCatch try_catch(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012515 CompileRun(
Steve Block6ded16b2010-05-10 14:33:55 +010012516 "o.foo = 17;"
12517 "var receiver = {};"
12518 "receiver.__proto__ = o;"
12519 "var result = 0;"
12520 "var saved_result = 0;"
12521 "for (var i = 0; i < 100; i++) {"
12522 " result = receiver.method(41);"
12523 " if (i == 50) {"
12524 " saved_result = result;"
12525 " receiver = 333;"
12526 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012527 "}");
Steve Block6ded16b2010-05-10 14:33:55 +010012528 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012529 // TODO(verwaest): Adjust message.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012530 CHECK(
12531 v8_str("TypeError: receiver.method is not a function")
12532 ->Equals(
12533 context.local(),
12534 try_catch.Exception()->ToString(context.local()).ToLocalChecked())
12535 .FromJust());
12536 CHECK_EQ(42, context->Global()
12537 ->Get(context.local(), v8_str("saved_result"))
12538 .ToLocalChecked()
12539 ->Int32Value(context.local())
12540 .FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +010012541 CHECK_GE(interceptor_call_count, 50);
12542}
12543
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012544
12545THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012546 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012547 v8::Isolate* isolate = CcTest::isolate();
12548 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012549 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012550 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012551 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012552 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12553 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012554 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012555 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012556 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012557 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012558 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012559 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012560 v8::External::New(isolate, &interceptor_call_count)));
Andrei Popescu402d9372010-02-26 13:31:12 +000012561 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012562 v8::Local<v8::Function> fun =
12563 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012564 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012565 CHECK(context->Global()
12566 ->Set(context.local(), v8_str("o"),
12567 fun->NewInstance(context.local()).ToLocalChecked())
12568 .FromJust());
12569 v8::TryCatch try_catch(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012570 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012571 "o.foo = 17;"
12572 "var receiver = {};"
12573 "receiver.__proto__ = o;"
12574 "var result = 0;"
12575 "var saved_result = 0;"
12576 "for (var i = 0; i < 100; i++) {"
12577 " result = receiver.method(41);"
12578 " if (i == 50) {"
12579 " saved_result = result;"
12580 " receiver = {method: receiver.method};"
12581 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012582 "}");
Andrei Popescu402d9372010-02-26 13:31:12 +000012583 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012584 CHECK(
12585 v8_str("TypeError: Illegal invocation")
12586 ->Equals(
12587 context.local(),
12588 try_catch.Exception()->ToString(context.local()).ToLocalChecked())
12589 .FromJust());
12590 CHECK_EQ(42, context->Global()
12591 ->Get(context.local(), v8_str("saved_result"))
12592 .ToLocalChecked()
12593 ->Int32Value(context.local())
12594 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012595 CHECK_GE(interceptor_call_count, 50);
12596}
12597
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012598
12599THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
12600 v8::Isolate* isolate = CcTest::isolate();
12601 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012602 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012603 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012604 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
12605 isolate, FastApiCallback_TrivialSignature, v8_str("method_data"),
12606 v8::Local<v8::Signature>());
12607 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012608 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012609 v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012610 USE(templ);
Andrei Popescu402d9372010-02-26 13:31:12 +000012611 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012612 v8::Local<v8::Function> fun =
12613 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012614 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012615 CHECK(context->Global()
12616 ->Set(context.local(), v8_str("o"),
12617 fun->NewInstance(context.local()).ToLocalChecked())
12618 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012619 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012620 "var result = 0;"
12621 "for (var i = 0; i < 100; i++) {"
12622 " result = o.method(41);"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012623 "}");
Andrei Popescu402d9372010-02-26 13:31:12 +000012624
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012625 CHECK_EQ(42, context->Global()
12626 ->Get(context.local(), v8_str("result"))
12627 .ToLocalChecked()
12628 ->Int32Value(context.local())
12629 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012630}
12631
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012632
12633THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
12634 v8::Isolate* isolate = CcTest::isolate();
12635 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012636 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012637 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012638 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012639 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12640 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012641 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012642 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012643 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012644 v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012645 CHECK(!templ.IsEmpty());
Andrei Popescu402d9372010-02-26 13:31:12 +000012646 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012647 v8::Local<v8::Function> fun =
12648 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012649 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012650 CHECK(context->Global()
12651 ->Set(context.local(), v8_str("o"),
12652 fun->NewInstance(context.local()).ToLocalChecked())
12653 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012654 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012655 "o.foo = 17;"
12656 "var receiver = {};"
12657 "receiver.__proto__ = o;"
12658 "var result = 0;"
12659 "for (var i = 0; i < 100; i++) {"
12660 " result = receiver.method(41);"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012661 "}");
Andrei Popescu402d9372010-02-26 13:31:12 +000012662
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012663 CHECK_EQ(42, context->Global()
12664 ->Get(context.local(), v8_str("result"))
12665 .ToLocalChecked()
12666 ->Int32Value(context.local())
12667 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012668}
12669
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012670
12671THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
12672 v8::Isolate* isolate = CcTest::isolate();
12673 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012674 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012675 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012676 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012677 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12678 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012679 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012680 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012681 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012682 v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012683 CHECK(!templ.IsEmpty());
Andrei Popescu402d9372010-02-26 13:31:12 +000012684 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012685 v8::Local<v8::Function> fun =
12686 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012687 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012688 CHECK(context->Global()
12689 ->Set(context.local(), v8_str("o"),
12690 fun->NewInstance(context.local()).ToLocalChecked())
12691 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012692 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012693 "o.foo = 17;"
12694 "var receiver = {};"
12695 "receiver.__proto__ = o;"
12696 "var result = 0;"
12697 "var saved_result = 0;"
12698 "for (var i = 0; i < 100; i++) {"
12699 " result = receiver.method(41);"
12700 " if (i == 50) {"
12701 " saved_result = result;"
12702 " receiver = {method: function(x) { return x - 1 }};"
12703 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012704 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012705 CHECK_EQ(40, context->Global()
12706 ->Get(context.local(), v8_str("result"))
12707 .ToLocalChecked()
12708 ->Int32Value(context.local())
12709 .FromJust());
12710 CHECK_EQ(42, context->Global()
12711 ->Get(context.local(), v8_str("saved_result"))
12712 .ToLocalChecked()
12713 ->Int32Value(context.local())
12714 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012715}
12716
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012717
12718THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
12719 v8::Isolate* isolate = CcTest::isolate();
12720 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012721 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012722 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012723 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012724 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12725 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012726 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Steve Block6ded16b2010-05-10 14:33:55 +010012727 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012728 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012729 v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012730 CHECK(!templ.IsEmpty());
Steve Block6ded16b2010-05-10 14:33:55 +010012731 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012732 v8::Local<v8::Function> fun =
12733 fun_templ->GetFunction(context.local()).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +010012734 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012735 CHECK(context->Global()
12736 ->Set(context.local(), v8_str("o"),
12737 fun->NewInstance(context.local()).ToLocalChecked())
12738 .FromJust());
12739 v8::TryCatch try_catch(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012740 CompileRun(
Steve Block6ded16b2010-05-10 14:33:55 +010012741 "o.foo = 17;"
12742 "var receiver = {};"
12743 "receiver.__proto__ = o;"
12744 "var result = 0;"
12745 "var saved_result = 0;"
12746 "for (var i = 0; i < 100; i++) {"
12747 " result = receiver.method(41);"
12748 " if (i == 50) {"
12749 " saved_result = result;"
12750 " receiver = 333;"
12751 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012752 "}");
Steve Block6ded16b2010-05-10 14:33:55 +010012753 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012754 // TODO(verwaest): Adjust message.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012755 CHECK(
12756 v8_str("TypeError: receiver.method is not a function")
12757 ->Equals(
12758 context.local(),
12759 try_catch.Exception()->ToString(context.local()).ToLocalChecked())
12760 .FromJust());
12761 CHECK_EQ(42, context->Global()
12762 ->Get(context.local(), v8_str("saved_result"))
12763 .ToLocalChecked()
12764 ->Int32Value(context.local())
12765 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012766}
12767
12768
12769THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) {
12770 v8::Isolate* isolate = CcTest::isolate();
12771 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012772 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012773 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012774 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012775 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12776 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012777 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012778 proto_templ->Set(v8_str("method"), method_templ);
12779 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012780 v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012781 CHECK(!templ.IsEmpty());
12782 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012783 v8::Local<v8::Function> fun =
12784 fun_templ->GetFunction(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012785 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012786 CHECK(context->Global()
12787 ->Set(context.local(), v8_str("o"),
12788 fun->NewInstance(context.local()).ToLocalChecked())
12789 .FromJust());
12790 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012791 CompileRun(
12792 "o.foo = 17;"
12793 "var receiver = {};"
12794 "receiver.__proto__ = o;"
12795 "var result = 0;"
12796 "var saved_result = 0;"
12797 "for (var i = 0; i < 100; i++) {"
12798 " result = receiver.method(41);"
12799 " if (i == 50) {"
12800 " saved_result = result;"
12801 " receiver = Object.create(receiver);"
12802 " }"
12803 "}");
12804 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012805 CHECK(
12806 v8_str("TypeError: Illegal invocation")
12807 ->Equals(
12808 context.local(),
12809 try_catch.Exception()->ToString(context.local()).ToLocalChecked())
12810 .FromJust());
12811 CHECK_EQ(42, context->Global()
12812 ->Get(context.local(), v8_str("saved_result"))
12813 .ToLocalChecked()
12814 ->Int32Value(context.local())
12815 .FromJust());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010012816}
12817
12818
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012819static void ThrowingGetter(Local<String> name,
12820 const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010012821 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012822 info.GetIsolate()->ThrowException(Local<Value>());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012823 info.GetReturnValue().SetUndefined();
Ben Murdoch8b112d22011-06-08 16:22:53 +010012824}
12825
12826
12827THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010012828 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012829 HandleScope scope(context->GetIsolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012830
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012831 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012832 Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
12833 instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
12834
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012835 Local<Object> instance = templ->GetFunction(context.local())
12836 .ToLocalChecked()
12837 ->NewInstance(context.local())
12838 .ToLocalChecked();
Ben Murdoch8b112d22011-06-08 16:22:53 +010012839
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012840 Local<Object> another = Object::New(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012841 CHECK(another->SetPrototype(context.local(), instance).FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012842
12843 Local<Object> with_js_getter = CompileRun(
12844 "o = {};\n"
12845 "o.__defineGetter__('f', function() { throw undefined; });\n"
12846 "o\n").As<Object>();
12847 CHECK(!with_js_getter.IsEmpty());
12848
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012849 TryCatch try_catch(context->GetIsolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012850
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012851 v8::MaybeLocal<Value> result =
12852 instance->GetRealNamedProperty(context.local(), v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012853 CHECK(try_catch.HasCaught());
12854 try_catch.Reset();
12855 CHECK(result.IsEmpty());
12856
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012857 Maybe<PropertyAttribute> attr =
12858 instance->GetRealNamedPropertyAttributes(context.local(), v8_str("f"));
12859 CHECK(!try_catch.HasCaught());
12860 CHECK(Just(None) == attr);
12861
12862 result = another->GetRealNamedProperty(context.local(), v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012863 CHECK(try_catch.HasCaught());
12864 try_catch.Reset();
12865 CHECK(result.IsEmpty());
12866
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012867 attr = another->GetRealNamedPropertyAttributes(context.local(), v8_str("f"));
12868 CHECK(!try_catch.HasCaught());
12869 CHECK(Just(None) == attr);
12870
12871 result = another->GetRealNamedPropertyInPrototypeChain(context.local(),
12872 v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012873 CHECK(try_catch.HasCaught());
12874 try_catch.Reset();
12875 CHECK(result.IsEmpty());
12876
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012877 attr = another->GetRealNamedPropertyAttributesInPrototypeChain(
12878 context.local(), v8_str("f"));
12879 CHECK(!try_catch.HasCaught());
12880 CHECK(Just(None) == attr);
12881
12882 result = another->Get(context.local(), v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012883 CHECK(try_catch.HasCaught());
12884 try_catch.Reset();
12885 CHECK(result.IsEmpty());
12886
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012887 result = with_js_getter->GetRealNamedProperty(context.local(), v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012888 CHECK(try_catch.HasCaught());
12889 try_catch.Reset();
12890 CHECK(result.IsEmpty());
12891
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012892 attr = with_js_getter->GetRealNamedPropertyAttributes(context.local(),
12893 v8_str("f"));
12894 CHECK(!try_catch.HasCaught());
12895 CHECK(Just(None) == attr);
12896
12897 result = with_js_getter->Get(context.local(), v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012898 CHECK(try_catch.HasCaught());
12899 try_catch.Reset();
12900 CHECK(result.IsEmpty());
12901}
12902
12903
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012904static void ThrowingCallbackWithTryCatch(
12905 const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012906 TryCatch try_catch(args.GetIsolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012907 // Verboseness is important: it triggers message delivery which can call into
12908 // external code.
12909 try_catch.SetVerbose(true);
12910 CompileRun("throw 'from JS';");
12911 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012912 CHECK(!CcTest::i_isolate()->has_pending_exception());
12913 CHECK(!CcTest::i_isolate()->has_scheduled_exception());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012914}
12915
12916
12917static int call_depth;
12918
12919
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012920static void WithTryCatch(Local<Message> message, Local<Value> data) {
12921 TryCatch try_catch(CcTest::isolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012922}
12923
12924
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012925static void ThrowFromJS(Local<Message> message, Local<Value> data) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010012926 if (--call_depth) CompileRun("throw 'ThrowInJS';");
12927}
12928
12929
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012930static void ThrowViaApi(Local<Message> message, Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012931 if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012932}
12933
12934
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012935static void WebKitLike(Local<Message> message, Local<Value> data) {
12936 Local<String> errorMessageString = message->Get();
Ben Murdoch8b112d22011-06-08 16:22:53 +010012937 CHECK(!errorMessageString.IsEmpty());
12938 message->GetStackTrace();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012939 message->GetScriptOrigin().ResourceName();
Ben Murdoch8b112d22011-06-08 16:22:53 +010012940}
12941
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012942
Ben Murdoch8b112d22011-06-08 16:22:53 +010012943THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010012944 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012945 v8::Isolate* isolate = context->GetIsolate();
12946 HandleScope scope(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +010012947
12948 Local<Function> func =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012949 FunctionTemplate::New(isolate, ThrowingCallbackWithTryCatch)
12950 ->GetFunction(context.local())
12951 .ToLocalChecked();
12952 CHECK(
12953 context->Global()->Set(context.local(), v8_str("func"), func).FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012954
12955 MessageCallback callbacks[] =
12956 { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
12957 for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
12958 MessageCallback callback = callbacks[i];
12959 if (callback != NULL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012960 isolate->AddMessageListener(callback);
Ben Murdoch8b112d22011-06-08 16:22:53 +010012961 }
Ben Murdoch257744e2011-11-30 15:57:28 +000012962 // Some small number to control number of times message handler should
12963 // throw an exception.
Ben Murdoch8b112d22011-06-08 16:22:53 +010012964 call_depth = 5;
12965 ExpectFalse(
12966 "var thrown = false;\n"
12967 "try { func(); } catch(e) { thrown = true; }\n"
12968 "thrown\n");
12969 if (callback != NULL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012970 isolate->RemoveMessageListeners(callback);
Ben Murdoch8b112d22011-06-08 16:22:53 +010012971 }
12972 }
12973}
12974
12975
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012976static void ParentGetter(Local<String> name,
12977 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +000012978 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012979 info.GetReturnValue().Set(v8_num(1));
Steve Blocka7e24c12009-10-30 11:49:00 +000012980}
12981
12982
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012983static void ChildGetter(Local<String> name,
12984 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +000012985 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012986 info.GetReturnValue().Set(v8_num(42));
Steve Blocka7e24c12009-10-30 11:49:00 +000012987}
12988
12989
12990THREADED_TEST(Overriding) {
Steve Blocka7e24c12009-10-30 11:49:00 +000012991 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012992 v8::Isolate* isolate = context->GetIsolate();
12993 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000012994
12995 // Parent template.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012996 Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000012997 Local<ObjectTemplate> parent_instance_templ =
12998 parent_templ->InstanceTemplate();
12999 parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
13000
13001 // Template that inherits from the parent template.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013002 Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000013003 Local<ObjectTemplate> child_instance_templ =
13004 child_templ->InstanceTemplate();
13005 child_templ->Inherit(parent_templ);
13006 // Override 'f'. The child version of 'f' should get called for child
13007 // instances.
13008 child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
13009 // Add 'g' twice. The 'g' added last should get called for instances.
13010 child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
13011 child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
13012
13013 // Add 'h' as an accessor to the proto template with ReadOnly attributes
13014 // so 'h' can be shadowed on the instance object.
13015 Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
13016 child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013017 v8::Local<Value>(), v8::DEFAULT, v8::ReadOnly);
Steve Blocka7e24c12009-10-30 11:49:00 +000013018
13019 // Add 'i' as an accessor to the instance template with ReadOnly attributes
13020 // but the attribute does not have effect because it is duplicated with
13021 // NULL setter.
13022 child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013023 v8::Local<Value>(), v8::DEFAULT,
13024 v8::ReadOnly);
Steve Blocka7e24c12009-10-30 11:49:00 +000013025
13026
13027 // Instantiate the child template.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013028 Local<v8::Object> instance = child_templ->GetFunction(context.local())
13029 .ToLocalChecked()
13030 ->NewInstance(context.local())
13031 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000013032
13033 // Check that the child function overrides the parent one.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013034 CHECK(context->Global()
13035 ->Set(context.local(), v8_str("o"), instance)
13036 .FromJust());
13037 Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000013038 // Check that the 'g' that was added last is hit.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013039 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
13040 value = v8_compile("o.g")->Run(context.local()).ToLocalChecked();
13041 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013042
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013043 // Check that 'h' cannot be shadowed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013044 value = v8_compile("o.h = 3; o.h")->Run(context.local()).ToLocalChecked();
13045 CHECK_EQ(1, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013046
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013047 // Check that 'i' cannot be shadowed or changed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013048 value = v8_compile("o.i = 3; o.i")->Run(context.local()).ToLocalChecked();
13049 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013050}
13051
13052
Ben Murdoch097c5b22016-05-18 11:27:45 +010013053static void ShouldThrowOnErrorGetter(
13054 Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
13055 ApiTestFuzzer::Fuzz();
13056 v8::Isolate* isolate = info.GetIsolate();
13057 Local<Boolean> should_throw_on_error =
13058 Boolean::New(isolate, info.ShouldThrowOnError());
13059 info.GetReturnValue().Set(should_throw_on_error);
13060}
13061
13062
13063template <typename T>
13064static void ShouldThrowOnErrorSetter(Local<Name> name, Local<v8::Value> value,
13065 const v8::PropertyCallbackInfo<T>& info) {
13066 ApiTestFuzzer::Fuzz();
13067 v8::Isolate* isolate = info.GetIsolate();
13068 auto context = isolate->GetCurrentContext();
13069 Local<Boolean> should_throw_on_error_value =
13070 Boolean::New(isolate, info.ShouldThrowOnError());
13071 CHECK(context->Global()
13072 ->Set(isolate->GetCurrentContext(), v8_str("should_throw_setter"),
13073 should_throw_on_error_value)
13074 .FromJust());
13075}
13076
13077
13078THREADED_TEST(AccessorShouldThrowOnError) {
13079 i::FLAG_strong_mode = true;
13080 LocalContext context;
13081 v8::Isolate* isolate = context->GetIsolate();
13082 v8::HandleScope scope(isolate);
13083 Local<Object> global = context->Global();
13084
13085 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
13086 Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
13087 instance_templ->SetAccessor(v8_str("f"), ShouldThrowOnErrorGetter,
13088 ShouldThrowOnErrorSetter<void>);
13089
13090 Local<v8::Object> instance = templ->GetFunction(context.local())
13091 .ToLocalChecked()
13092 ->NewInstance(context.local())
13093 .ToLocalChecked();
13094
13095 CHECK(global->Set(context.local(), v8_str("o"), instance).FromJust());
13096
13097 // SLOPPY mode
13098 Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
13099 CHECK(value->IsFalse());
13100 v8_compile("o.f = 153")->Run(context.local()).ToLocalChecked();
13101 value = global->Get(context.local(), v8_str("should_throw_setter"))
13102 .ToLocalChecked();
13103 CHECK(value->IsFalse());
13104
13105 // STRICT mode
13106 value = v8_compile("'use strict';o.f")->Run(context.local()).ToLocalChecked();
13107 CHECK(value->IsFalse());
13108 v8_compile("'use strict'; o.f = 153")->Run(context.local()).ToLocalChecked();
13109 value = global->Get(context.local(), v8_str("should_throw_setter"))
13110 .ToLocalChecked();
13111 CHECK(value->IsTrue());
13112
13113 // STRONG mode
13114 value = v8_compile("'use strong';o.f")->Run(context.local()).ToLocalChecked();
13115 CHECK(value->IsFalse());
13116 v8_compile("'use strong'; o.f = 153")->Run(context.local()).ToLocalChecked();
13117 value = global->Get(context.local(), v8_str("should_throw_setter"))
13118 .ToLocalChecked();
13119 CHECK(value->IsTrue());
13120}
13121
13122
13123static void ShouldThrowOnErrorQuery(
13124 Local<Name> name, const v8::PropertyCallbackInfo<v8::Integer>& info) {
13125 ApiTestFuzzer::Fuzz();
13126 v8::Isolate* isolate = info.GetIsolate();
13127 info.GetReturnValue().Set(v8::None);
13128
13129 auto context = isolate->GetCurrentContext();
13130 Local<Boolean> should_throw_on_error_value =
13131 Boolean::New(isolate, info.ShouldThrowOnError());
13132 CHECK(context->Global()
13133 ->Set(isolate->GetCurrentContext(), v8_str("should_throw_query"),
13134 should_throw_on_error_value)
13135 .FromJust());
13136}
13137
13138
13139static void ShouldThrowOnErrorDeleter(
13140 Local<Name> name, const v8::PropertyCallbackInfo<v8::Boolean>& info) {
13141 ApiTestFuzzer::Fuzz();
13142 v8::Isolate* isolate = info.GetIsolate();
13143 info.GetReturnValue().Set(v8::True(isolate));
13144
13145 auto context = isolate->GetCurrentContext();
13146 Local<Boolean> should_throw_on_error_value =
13147 Boolean::New(isolate, info.ShouldThrowOnError());
13148 CHECK(context->Global()
13149 ->Set(isolate->GetCurrentContext(), v8_str("should_throw_deleter"),
13150 should_throw_on_error_value)
13151 .FromJust());
13152}
13153
13154
13155static void ShouldThrowOnErrorPropertyEnumerator(
13156 const v8::PropertyCallbackInfo<v8::Array>& info) {
13157 ApiTestFuzzer::Fuzz();
13158 v8::Isolate* isolate = info.GetIsolate();
13159 Local<v8::Array> names = v8::Array::New(isolate, 1);
13160 CHECK(names->Set(isolate->GetCurrentContext(), names, v8_num(1)).FromJust());
13161 info.GetReturnValue().Set(names);
13162
13163 auto context = isolate->GetCurrentContext();
13164 Local<Boolean> should_throw_on_error_value =
13165 Boolean::New(isolate, info.ShouldThrowOnError());
13166 CHECK(context->Global()
13167 ->Set(isolate->GetCurrentContext(),
13168 v8_str("should_throw_enumerator"),
13169 should_throw_on_error_value)
13170 .FromJust());
13171}
13172
13173
13174THREADED_TEST(InterceptorShouldThrowOnError) {
13175 i::FLAG_strong_mode = true;
13176 LocalContext context;
13177 v8::Isolate* isolate = context->GetIsolate();
13178 v8::HandleScope scope(isolate);
13179 Local<Object> global = context->Global();
13180
13181 auto interceptor_templ = v8::ObjectTemplate::New(isolate);
13182 v8::NamedPropertyHandlerConfiguration handler(
13183 ShouldThrowOnErrorGetter, ShouldThrowOnErrorSetter<Value>,
13184 ShouldThrowOnErrorQuery, ShouldThrowOnErrorDeleter,
13185 ShouldThrowOnErrorPropertyEnumerator);
13186 interceptor_templ->SetHandler(handler);
13187
13188 Local<v8::Object> instance =
13189 interceptor_templ->NewInstance(context.local()).ToLocalChecked();
13190
13191 CHECK(global->Set(context.local(), v8_str("o"), instance).FromJust());
13192
13193 // SLOPPY mode
13194 Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
13195 CHECK(value->IsFalse());
13196 v8_compile("o.f = 153")->Run(context.local()).ToLocalChecked();
13197 value = global->Get(context.local(), v8_str("should_throw_setter"))
13198 .ToLocalChecked();
13199 CHECK(value->IsFalse());
13200
13201 v8_compile("delete o.f")->Run(context.local()).ToLocalChecked();
13202 value = global->Get(context.local(), v8_str("should_throw_deleter"))
13203 .ToLocalChecked();
13204 CHECK(value->IsFalse());
13205
13206 v8_compile("Object.getOwnPropertyNames(o)")
13207 ->Run(context.local())
13208 .ToLocalChecked();
13209 value = global->Get(context.local(), v8_str("should_throw_enumerator"))
13210 .ToLocalChecked();
13211 CHECK(value->IsFalse());
13212
13213 // STRICT mode
13214 value = v8_compile("'use strict';o.f")->Run(context.local()).ToLocalChecked();
13215 CHECK(value->IsFalse());
13216 v8_compile("'use strict'; o.f = 153")->Run(context.local()).ToLocalChecked();
13217 value = global->Get(context.local(), v8_str("should_throw_setter"))
13218 .ToLocalChecked();
13219 CHECK(value->IsTrue());
13220
13221 v8_compile("'use strict'; delete o.f")->Run(context.local()).ToLocalChecked();
13222 value = global->Get(context.local(), v8_str("should_throw_deleter"))
13223 .ToLocalChecked();
13224 CHECK(value->IsTrue());
13225
13226 v8_compile("'use strict'; Object.getOwnPropertyNames(o)")
13227 ->Run(context.local())
13228 .ToLocalChecked();
13229 value = global->Get(context.local(), v8_str("should_throw_enumerator"))
13230 .ToLocalChecked();
13231 CHECK(value->IsFalse());
13232
13233 // STRONG mode
13234 value = v8_compile("'use strong';o.f")->Run(context.local()).ToLocalChecked();
13235 CHECK(value->IsFalse());
13236 v8_compile("'use strong'; o.f = 153")->Run(context.local()).ToLocalChecked();
13237 value = global->Get(context.local(), v8_str("should_throw_setter"))
13238 .ToLocalChecked();
13239 CHECK(value->IsTrue());
13240
13241 v8_compile("'use strong'; Object.getOwnPropertyNames(o)")
13242 ->Run(context.local())
13243 .ToLocalChecked();
13244 value = global->Get(context.local(), v8_str("should_throw_enumerator"))
13245 .ToLocalChecked();
13246 CHECK(value->IsFalse());
13247}
13248
13249
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013250static void IsConstructHandler(
13251 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +000013252 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013253 args.GetReturnValue().Set(args.IsConstructCall());
Steve Blocka7e24c12009-10-30 11:49:00 +000013254}
13255
13256
13257THREADED_TEST(IsConstructCall) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013258 v8::Isolate* isolate = CcTest::isolate();
13259 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000013260
13261 // Function template with call handler.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013262 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000013263 templ->SetCallHandler(IsConstructHandler);
13264
13265 LocalContext context;
13266
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013267 CHECK(context->Global()
13268 ->Set(context.local(), v8_str("f"),
13269 templ->GetFunction(context.local()).ToLocalChecked())
13270 .FromJust());
13271 Local<Value> value = v8_compile("f()")->Run(context.local()).ToLocalChecked();
13272 CHECK(!value->BooleanValue(context.local()).FromJust());
13273 value = v8_compile("new f()")->Run(context.local()).ToLocalChecked();
13274 CHECK(value->BooleanValue(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013275}
13276
13277
13278THREADED_TEST(ObjectProtoToString) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013279 v8::Isolate* isolate = CcTest::isolate();
13280 v8::HandleScope scope(isolate);
13281 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000013282 templ->SetClassName(v8_str("MyClass"));
13283
13284 LocalContext context;
13285
13286 Local<String> customized_tostring = v8_str("customized toString");
13287
13288 // Replace Object.prototype.toString
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013289 v8_compile(
13290 "Object.prototype.toString = function() {"
13291 " return 'customized toString';"
13292 "}")
13293 ->Run(context.local())
13294 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000013295
13296 // Normal ToString call should call replaced Object.prototype.toString
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013297 Local<v8::Object> instance = templ->GetFunction(context.local())
13298 .ToLocalChecked()
13299 ->NewInstance(context.local())
13300 .ToLocalChecked();
13301 Local<String> value = instance->ToString(context.local()).ToLocalChecked();
13302 CHECK(value->IsString() &&
13303 value->Equals(context.local(), customized_tostring).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013304
13305 // ObjectProtoToString should not call replace toString function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013306 value = instance->ObjectProtoToString(context.local()).ToLocalChecked();
13307 CHECK(value->IsString() &&
13308 value->Equals(context.local(), v8_str("[object MyClass]")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013309
13310 // Check global
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013311 value =
13312 context->Global()->ObjectProtoToString(context.local()).ToLocalChecked();
13313 CHECK(value->IsString() &&
13314 value->Equals(context.local(), v8_str("[object global]")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013315
13316 // Check ordinary object
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013317 Local<Value> object =
13318 v8_compile("new Object()")->Run(context.local()).ToLocalChecked();
13319 value = object.As<v8::Object>()
13320 ->ObjectProtoToString(context.local())
13321 .ToLocalChecked();
13322 CHECK(value->IsString() &&
13323 value->Equals(context.local(), v8_str("[object Object]")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013324}
13325
13326
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013327TEST(ObjectProtoToStringES6) {
13328 // TODO(dslomov, caitp): merge into ObjectProtoToString test once shipped.
13329 i::FLAG_harmony_tostring = true;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080013330 LocalContext context;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013331 v8::Isolate* isolate = CcTest::isolate();
13332 v8::HandleScope scope(isolate);
13333 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
13334 templ->SetClassName(v8_str("MyClass"));
13335
13336 Local<String> customized_tostring = v8_str("customized toString");
13337
13338 // Replace Object.prototype.toString
13339 CompileRun(
13340 "Object.prototype.toString = function() {"
13341 " return 'customized toString';"
13342 "}");
13343
13344 // Normal ToString call should call replaced Object.prototype.toString
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013345 Local<v8::Object> instance = templ->GetFunction(context.local())
13346 .ToLocalChecked()
13347 ->NewInstance(context.local())
13348 .ToLocalChecked();
13349 Local<String> value = instance->ToString(context.local()).ToLocalChecked();
13350 CHECK(value->IsString() &&
13351 value->Equals(context.local(), customized_tostring).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013352
13353 // ObjectProtoToString should not call replace toString function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013354 value = instance->ObjectProtoToString(context.local()).ToLocalChecked();
13355 CHECK(value->IsString() &&
13356 value->Equals(context.local(), v8_str("[object MyClass]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013357
13358 // Check global
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013359 value =
13360 context->Global()->ObjectProtoToString(context.local()).ToLocalChecked();
13361 CHECK(value->IsString() &&
13362 value->Equals(context.local(), v8_str("[object global]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013363
13364 // Check ordinary object
13365 Local<Value> object = CompileRun("new Object()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013366 value = object.As<v8::Object>()
13367 ->ObjectProtoToString(context.local())
13368 .ToLocalChecked();
13369 CHECK(value->IsString() &&
13370 value->Equals(context.local(), v8_str("[object Object]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013371
13372 // Check that ES6 semantics using @@toStringTag work
13373 Local<v8::Symbol> toStringTag = v8::Symbol::GetToStringTag(isolate);
13374
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013375#define TEST_TOSTRINGTAG(type, tag, expected) \
13376 do { \
13377 object = CompileRun("new " #type "()"); \
13378 CHECK(object.As<v8::Object>() \
13379 ->Set(context.local(), toStringTag, v8_str(#tag)) \
13380 .FromJust()); \
13381 value = object.As<v8::Object>() \
13382 ->ObjectProtoToString(context.local()) \
13383 .ToLocalChecked(); \
13384 CHECK(value->IsString() && \
13385 value->Equals(context.local(), v8_str("[object " #expected "]")) \
13386 .FromJust()); \
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013387 } while (0)
13388
13389 TEST_TOSTRINGTAG(Array, Object, Object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013390 TEST_TOSTRINGTAG(Object, Arguments, Arguments);
13391 TEST_TOSTRINGTAG(Object, Array, Array);
13392 TEST_TOSTRINGTAG(Object, Boolean, Boolean);
13393 TEST_TOSTRINGTAG(Object, Date, Date);
13394 TEST_TOSTRINGTAG(Object, Error, Error);
13395 TEST_TOSTRINGTAG(Object, Function, Function);
13396 TEST_TOSTRINGTAG(Object, Number, Number);
13397 TEST_TOSTRINGTAG(Object, RegExp, RegExp);
13398 TEST_TOSTRINGTAG(Object, String, String);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013399 TEST_TOSTRINGTAG(Object, Foo, Foo);
13400
13401#undef TEST_TOSTRINGTAG
13402
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013403 Local<v8::RegExp> valueRegExp =
13404 v8::RegExp::New(context.local(), v8_str("^$"), v8::RegExp::kNone)
13405 .ToLocalChecked();
13406 Local<Value> valueNumber = v8_num(123);
13407 Local<v8::Symbol> valueSymbol = v8_symbol("TestSymbol");
13408 Local<v8::Function> valueFunction =
13409 CompileRun("(function fn() {})").As<v8::Function>();
13410 Local<v8::Object> valueObject = v8::Object::New(v8::Isolate::GetCurrent());
13411 Local<v8::Primitive> valueNull = v8::Null(v8::Isolate::GetCurrent());
13412 Local<v8::Primitive> valueUndef = v8::Undefined(v8::Isolate::GetCurrent());
13413
13414#define TEST_TOSTRINGTAG(type, tagValue, expected) \
13415 do { \
13416 object = CompileRun("new " #type "()"); \
13417 CHECK(object.As<v8::Object>() \
13418 ->Set(context.local(), toStringTag, tagValue) \
13419 .FromJust()); \
13420 value = object.As<v8::Object>() \
13421 ->ObjectProtoToString(context.local()) \
13422 .ToLocalChecked(); \
13423 CHECK(value->IsString() && \
13424 value->Equals(context.local(), v8_str("[object " #expected "]")) \
13425 .FromJust()); \
13426 } while (0)
13427
13428#define TEST_TOSTRINGTAG_TYPES(tagValue) \
13429 TEST_TOSTRINGTAG(Array, tagValue, Array); \
13430 TEST_TOSTRINGTAG(Object, tagValue, Object); \
13431 TEST_TOSTRINGTAG(Function, tagValue, Function); \
13432 TEST_TOSTRINGTAG(Date, tagValue, Date); \
13433 TEST_TOSTRINGTAG(RegExp, tagValue, RegExp); \
13434 TEST_TOSTRINGTAG(Error, tagValue, Error); \
13435
13436 // Test non-String-valued @@toStringTag
13437 TEST_TOSTRINGTAG_TYPES(valueRegExp);
13438 TEST_TOSTRINGTAG_TYPES(valueNumber);
13439 TEST_TOSTRINGTAG_TYPES(valueSymbol);
13440 TEST_TOSTRINGTAG_TYPES(valueFunction);
13441 TEST_TOSTRINGTAG_TYPES(valueObject);
13442 TEST_TOSTRINGTAG_TYPES(valueNull);
13443 TEST_TOSTRINGTAG_TYPES(valueUndef);
13444
13445#undef TEST_TOSTRINGTAG
13446#undef TEST_TOSTRINGTAG_TYPES
13447
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013448 // @@toStringTag getter throws
13449 Local<Value> obj = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013450 obj.As<v8::Object>()
13451 ->SetAccessor(context.local(), toStringTag, ThrowingSymbolAccessorGetter)
13452 .FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013453 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013454 TryCatch try_catch(isolate);
13455 CHECK(obj.As<v8::Object>()->ObjectProtoToString(context.local()).IsEmpty());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013456 CHECK(try_catch.HasCaught());
13457 }
13458
13459 // @@toStringTag getter does not throw
13460 obj = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013461 obj.As<v8::Object>()
13462 ->SetAccessor(context.local(), toStringTag,
13463 SymbolAccessorGetterReturnsDefault, 0, v8_str("Test"))
13464 .FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013465 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013466 TryCatch try_catch(isolate);
13467 value = obj.As<v8::Object>()
13468 ->ObjectProtoToString(context.local())
13469 .ToLocalChecked();
13470 CHECK(value->IsString() &&
13471 value->Equals(context.local(), v8_str("[object Test]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013472 CHECK(!try_catch.HasCaught());
13473 }
13474
13475 // JS @@toStringTag value
13476 obj = CompileRun("obj = {}; obj[Symbol.toStringTag] = 'Test'; obj");
13477 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013478 TryCatch try_catch(isolate);
13479 value = obj.As<v8::Object>()
13480 ->ObjectProtoToString(context.local())
13481 .ToLocalChecked();
13482 CHECK(value->IsString() &&
13483 value->Equals(context.local(), v8_str("[object Test]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013484 CHECK(!try_catch.HasCaught());
13485 }
13486
13487 // JS @@toStringTag getter throws
13488 obj = CompileRun(
13489 "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
13490 " get: function() { throw 'Test'; }"
13491 "}); obj");
13492 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013493 TryCatch try_catch(isolate);
13494 CHECK(obj.As<v8::Object>()->ObjectProtoToString(context.local()).IsEmpty());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013495 CHECK(try_catch.HasCaught());
13496 }
13497
13498 // JS @@toStringTag getter does not throw
13499 obj = CompileRun(
13500 "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
13501 " get: function() { return 'Test'; }"
13502 "}); obj");
13503 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013504 TryCatch try_catch(isolate);
13505 value = obj.As<v8::Object>()
13506 ->ObjectProtoToString(context.local())
13507 .ToLocalChecked();
13508 CHECK(value->IsString() &&
13509 value->Equals(context.local(), v8_str("[object Test]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013510 CHECK(!try_catch.HasCaught());
13511 }
13512}
13513
13514
13515THREADED_TEST(ObjectGetConstructorName) {
13516 v8::Isolate* isolate = CcTest::isolate();
13517 LocalContext context;
13518 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013519 v8_compile(
13520 "function Parent() {};"
13521 "function Child() {};"
13522 "Child.prototype = new Parent();"
13523 "Child.prototype.constructor = Child;"
13524 "var outer = { inner: function() { } };"
13525 "var p = new Parent();"
13526 "var c = new Child();"
13527 "var x = new outer.inner();"
13528 "var proto = Child.prototype;")
13529 ->Run(context.local())
13530 .ToLocalChecked();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080013531
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013532 Local<v8::Value> p =
13533 context->Global()->Get(context.local(), v8_str("p")).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013534 CHECK(p->IsObject() &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013535 p->ToObject(context.local())
13536 .ToLocalChecked()
13537 ->GetConstructorName()
13538 ->Equals(context.local(), v8_str("Parent"))
13539 .FromJust());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080013540
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013541 Local<v8::Value> c =
13542 context->Global()->Get(context.local(), v8_str("c")).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013543 CHECK(c->IsObject() &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013544 c->ToObject(context.local())
13545 .ToLocalChecked()
13546 ->GetConstructorName()
13547 ->Equals(context.local(), v8_str("Child"))
13548 .FromJust());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080013549
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013550 Local<v8::Value> x =
13551 context->Global()->Get(context.local(), v8_str("x")).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013552 CHECK(x->IsObject() &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013553 x->ToObject(context.local())
13554 .ToLocalChecked()
13555 ->GetConstructorName()
13556 ->Equals(context.local(), v8_str("outer.inner"))
13557 .FromJust());
13558
13559 Local<v8::Value> child_prototype =
13560 context->Global()->Get(context.local(), v8_str("proto")).ToLocalChecked();
13561 CHECK(child_prototype->IsObject() &&
13562 child_prototype->ToObject(context.local())
13563 .ToLocalChecked()
13564 ->GetConstructorName()
13565 ->Equals(context.local(), v8_str("Parent"))
13566 .FromJust());
13567}
13568
13569
13570THREADED_TEST(SubclassGetConstructorName) {
13571 v8::Isolate* isolate = CcTest::isolate();
13572 LocalContext context;
13573 v8::HandleScope scope(isolate);
13574 v8_compile(
13575 "\"use strict\";"
13576 "class Parent {}"
13577 "class Child extends Parent {}"
13578 "var p = new Parent();"
13579 "var c = new Child();")
13580 ->Run(context.local())
13581 .ToLocalChecked();
13582
13583 Local<v8::Value> p =
13584 context->Global()->Get(context.local(), v8_str("p")).ToLocalChecked();
13585 CHECK(p->IsObject() &&
13586 p->ToObject(context.local())
13587 .ToLocalChecked()
13588 ->GetConstructorName()
13589 ->Equals(context.local(), v8_str("Parent"))
13590 .FromJust());
13591
13592 Local<v8::Value> c =
13593 context->Global()->Get(context.local(), v8_str("c")).ToLocalChecked();
13594 CHECK(c->IsObject() &&
13595 c->ToObject(context.local())
13596 .ToLocalChecked()
13597 ->GetConstructorName()
13598 ->Equals(context.local(), v8_str("Child"))
13599 .FromJust());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080013600}
13601
13602
Steve Blocka7e24c12009-10-30 11:49:00 +000013603bool ApiTestFuzzer::fuzzing_ = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013604v8::base::Semaphore ApiTestFuzzer::all_tests_done_(0);
Steve Blocka7e24c12009-10-30 11:49:00 +000013605int ApiTestFuzzer::active_tests_;
13606int ApiTestFuzzer::tests_being_run_;
13607int ApiTestFuzzer::current_;
13608
13609
13610// We are in a callback and want to switch to another thread (if we
13611// are currently running the thread fuzzing test).
13612void ApiTestFuzzer::Fuzz() {
13613 if (!fuzzing_) return;
13614 ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
13615 test->ContextSwitch();
13616}
13617
13618
13619// Let the next thread go. Since it is also waiting on the V8 lock it may
13620// not start immediately.
13621bool ApiTestFuzzer::NextThread() {
13622 int test_position = GetNextTestNumber();
Steve Blockd0582a62009-12-15 09:54:21 +000013623 const char* test_name = RegisterThreadedTest::nth(current_)->name();
Steve Blocka7e24c12009-10-30 11:49:00 +000013624 if (test_position == current_) {
Steve Blockd0582a62009-12-15 09:54:21 +000013625 if (kLogThreading)
13626 printf("Stay with %s\n", test_name);
Steve Blocka7e24c12009-10-30 11:49:00 +000013627 return false;
13628 }
Steve Blockd0582a62009-12-15 09:54:21 +000013629 if (kLogThreading) {
13630 printf("Switch from %s to %s\n",
13631 test_name,
13632 RegisterThreadedTest::nth(test_position)->name());
13633 }
Steve Blocka7e24c12009-10-30 11:49:00 +000013634 current_ = test_position;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013635 RegisterThreadedTest::nth(current_)->fuzzer_->gate_.Signal();
Steve Blocka7e24c12009-10-30 11:49:00 +000013636 return true;
13637}
13638
13639
13640void ApiTestFuzzer::Run() {
13641 // When it is our turn...
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013642 gate_.Wait();
Steve Blocka7e24c12009-10-30 11:49:00 +000013643 {
13644 // ... get the V8 lock and start running the test.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013645 v8::Locker locker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013646 CallTest();
13647 }
13648 // This test finished.
13649 active_ = false;
13650 active_tests_--;
13651 // If it was the last then signal that fact.
13652 if (active_tests_ == 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013653 all_tests_done_.Signal();
Steve Blocka7e24c12009-10-30 11:49:00 +000013654 } else {
13655 // Otherwise select a new test and start that.
13656 NextThread();
13657 }
13658}
13659
13660
13661static unsigned linear_congruential_generator;
13662
13663
Ben Murdoch3ef787d2012-04-12 10:51:47 +010013664void ApiTestFuzzer::SetUp(PartOfTest part) {
Steve Blocka7e24c12009-10-30 11:49:00 +000013665 linear_congruential_generator = i::FLAG_testing_prng_seed;
13666 fuzzing_ = true;
Ben Murdoch257744e2011-11-30 15:57:28 +000013667 int count = RegisterThreadedTest::count();
13668 int start = count * part / (LAST_PART + 1);
13669 int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
13670 active_tests_ = tests_being_run_ = end - start + 1;
Steve Blocka7e24c12009-10-30 11:49:00 +000013671 for (int i = 0; i < tests_being_run_; i++) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000013672 RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
Steve Blocka7e24c12009-10-30 11:49:00 +000013673 }
13674 for (int i = 0; i < active_tests_; i++) {
13675 RegisterThreadedTest::nth(i)->fuzzer_->Start();
13676 }
13677}
13678
13679
13680static void CallTestNumber(int test_number) {
13681 (RegisterThreadedTest::nth(test_number)->callback())();
13682}
13683
13684
13685void ApiTestFuzzer::RunAllTests() {
13686 // Set off the first test.
13687 current_ = -1;
13688 NextThread();
13689 // Wait till they are all done.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013690 all_tests_done_.Wait();
Steve Blocka7e24c12009-10-30 11:49:00 +000013691}
13692
13693
13694int ApiTestFuzzer::GetNextTestNumber() {
13695 int next_test;
13696 do {
13697 next_test = (linear_congruential_generator >> 16) % tests_being_run_;
13698 linear_congruential_generator *= 1664525u;
13699 linear_congruential_generator += 1013904223u;
13700 } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
13701 return next_test;
13702}
13703
13704
13705void ApiTestFuzzer::ContextSwitch() {
13706 // If the new thread is the same as the current thread there is nothing to do.
13707 if (NextThread()) {
13708 // Now it can start.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013709 v8::Unlocker unlocker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013710 // Wait till someone starts us again.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013711 gate_.Wait();
Steve Blocka7e24c12009-10-30 11:49:00 +000013712 // And we're off.
13713 }
13714}
13715
13716
13717void ApiTestFuzzer::TearDown() {
13718 fuzzing_ = false;
13719 for (int i = 0; i < RegisterThreadedTest::count(); i++) {
13720 ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
13721 if (fuzzer != NULL) fuzzer->Join();
13722 }
13723}
13724
13725
13726// Lets not be needlessly self-referential.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013727TEST(Threading1) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010013728 ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART);
Steve Blocka7e24c12009-10-30 11:49:00 +000013729 ApiTestFuzzer::RunAllTests();
13730 ApiTestFuzzer::TearDown();
13731}
13732
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013733
Steve Blocka7e24c12009-10-30 11:49:00 +000013734TEST(Threading2) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010013735 ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
Steve Blocka7e24c12009-10-30 11:49:00 +000013736 ApiTestFuzzer::RunAllTests();
13737 ApiTestFuzzer::TearDown();
13738}
13739
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013740
Ben Murdoch257744e2011-11-30 15:57:28 +000013741TEST(Threading3) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010013742 ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
Ben Murdoch257744e2011-11-30 15:57:28 +000013743 ApiTestFuzzer::RunAllTests();
13744 ApiTestFuzzer::TearDown();
13745}
13746
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013747
Ben Murdoch257744e2011-11-30 15:57:28 +000013748TEST(Threading4) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010013749 ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
Ben Murdoch257744e2011-11-30 15:57:28 +000013750 ApiTestFuzzer::RunAllTests();
13751 ApiTestFuzzer::TearDown();
13752}
Steve Blocka7e24c12009-10-30 11:49:00 +000013753
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013754
Steve Blocka7e24c12009-10-30 11:49:00 +000013755void ApiTestFuzzer::CallTest() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013756 v8::Isolate::Scope scope(CcTest::isolate());
Steve Blockd0582a62009-12-15 09:54:21 +000013757 if (kLogThreading)
13758 printf("Start test %d\n", test_number_);
Steve Blocka7e24c12009-10-30 11:49:00 +000013759 CallTestNumber(test_number_);
Steve Blockd0582a62009-12-15 09:54:21 +000013760 if (kLogThreading)
13761 printf("End test %d\n", test_number_);
Steve Blocka7e24c12009-10-30 11:49:00 +000013762}
13763
13764
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013765static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
13766 v8::Isolate* isolate = args.GetIsolate();
13767 CHECK(v8::Locker::IsLocked(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000013768 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013769 v8::Unlocker unlocker(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000013770 const char* code = "throw 7;";
13771 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013772 v8::Locker nested_locker(isolate);
13773 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013774 v8::Local<Value> exception;
13775 {
13776 v8::TryCatch try_catch(isolate);
13777 v8::Local<Value> value = CompileRun(code);
Steve Blocka7e24c12009-10-30 11:49:00 +000013778 CHECK(value.IsEmpty());
13779 CHECK(try_catch.HasCaught());
13780 // Make sure to wrap the exception in a new handle because
13781 // the handle returned from the TryCatch is destroyed
13782 // when the TryCatch is destroyed.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013783 exception = Local<Value>::New(isolate, try_catch.Exception());
Steve Blocka7e24c12009-10-30 11:49:00 +000013784 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013785 args.GetIsolate()->ThrowException(exception);
Steve Blocka7e24c12009-10-30 11:49:00 +000013786 }
13787}
13788
13789
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013790static void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
13791 CHECK(v8::Locker::IsLocked(CcTest::isolate()));
Steve Blocka7e24c12009-10-30 11:49:00 +000013792 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013793 v8::Unlocker unlocker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013794 const char* code = "throw 7;";
13795 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013796 v8::Locker nested_locker(CcTest::isolate());
13797 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013798 v8::Local<Value> value = CompileRun(code);
Steve Blocka7e24c12009-10-30 11:49:00 +000013799 CHECK(value.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013800 args.GetReturnValue().Set(v8_str("foo"));
Steve Blocka7e24c12009-10-30 11:49:00 +000013801 }
13802}
13803
13804
13805// These are locking tests that don't need to be run again
13806// as part of the locking aggregation tests.
13807TEST(NestedLockers) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013808 v8::Isolate* isolate = CcTest::isolate();
13809 v8::Locker locker(isolate);
13810 CHECK(v8::Locker::IsLocked(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000013811 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013812 v8::HandleScope scope(env->GetIsolate());
13813 Local<v8::FunctionTemplate> fun_templ =
13814 v8::FunctionTemplate::New(isolate, ThrowInJS);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013815 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
13816 CHECK(env->Global()->Set(env.local(), v8_str("throw_in_js"), fun).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013817 Local<Script> script = v8_compile("(function () {"
13818 " try {"
13819 " throw_in_js();"
13820 " return 42;"
13821 " } catch (e) {"
13822 " return e * 13;"
13823 " }"
13824 "})();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013825 CHECK_EQ(91, script->Run(env.local())
13826 .ToLocalChecked()
13827 ->Int32Value(env.local())
13828 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013829}
13830
13831
13832// These are locking tests that don't need to be run again
13833// as part of the locking aggregation tests.
13834TEST(NestedLockersNoTryCatch) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013835 v8::Locker locker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013836 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013837 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013838 Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013839 v8::FunctionTemplate::New(env->GetIsolate(), ThrowInJSNoCatch);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013840 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
13841 CHECK(env->Global()->Set(env.local(), v8_str("throw_in_js"), fun).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013842 Local<Script> script = v8_compile("(function () {"
13843 " try {"
13844 " throw_in_js();"
13845 " return 42;"
13846 " } catch (e) {"
13847 " return e * 13;"
13848 " }"
13849 "})();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013850 CHECK_EQ(91, script->Run(env.local())
13851 .ToLocalChecked()
13852 ->Int32Value(env.local())
13853 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013854}
13855
13856
13857THREADED_TEST(RecursiveLocking) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013858 v8::Locker locker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013859 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013860 v8::Locker locker2(CcTest::isolate());
13861 CHECK(v8::Locker::IsLocked(CcTest::isolate()));
Steve Blocka7e24c12009-10-30 11:49:00 +000013862 }
13863}
13864
13865
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013866static void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +000013867 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013868 v8::Unlocker unlocker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013869}
13870
13871
13872THREADED_TEST(LockUnlockLock) {
13873 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013874 v8::Locker locker(CcTest::isolate());
13875 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013876 LocalContext env;
13877 Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013878 v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013879 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
13880 CHECK(env->Global()
13881 ->Set(env.local(), v8_str("unlock_for_a_moment"), fun)
13882 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013883 Local<Script> script = v8_compile("(function () {"
13884 " unlock_for_a_moment();"
13885 " return 42;"
13886 "})();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013887 CHECK_EQ(42, script->Run(env.local())
13888 .ToLocalChecked()
13889 ->Int32Value(env.local())
13890 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013891 }
13892 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013893 v8::Locker locker(CcTest::isolate());
13894 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013895 LocalContext env;
13896 Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013897 v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013898 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
13899 CHECK(env->Global()
13900 ->Set(env.local(), v8_str("unlock_for_a_moment"), fun)
13901 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013902 Local<Script> script = v8_compile("(function () {"
13903 " unlock_for_a_moment();"
13904 " return 42;"
13905 "})();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013906 CHECK_EQ(42, script->Run(env.local())
13907 .ToLocalChecked()
13908 ->Int32Value(env.local())
13909 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013910 }
13911}
13912
13913
Leon Clarked91b9f72010-01-27 17:25:45 +000013914static int GetGlobalObjectsCount() {
Leon Clarkeeab96aa2010-01-27 16:31:12 +000013915 int count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013916 i::HeapIterator it(CcTest::heap());
Leon Clarked91b9f72010-01-27 17:25:45 +000013917 for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013918 if (object->IsJSGlobalObject()) {
13919 i::JSGlobalObject* g = i::JSGlobalObject::cast(object);
13920 // Skip dummy global object.
13921 if (i::GlobalDictionary::cast(g->properties())->NumberOfElements() != 0) {
13922 count++;
13923 }
13924 }
Leon Clarked91b9f72010-01-27 17:25:45 +000013925 return count;
13926}
13927
13928
Ben Murdochf87a2032010-10-22 12:50:53 +010013929static void CheckSurvivingGlobalObjectsCount(int expected) {
Steve Blocka7e24c12009-10-30 11:49:00 +000013930 // We need to collect all garbage twice to be sure that everything
13931 // has been collected. This is because inline caches are cleared in
13932 // the first garbage collection but some of the maps have already
13933 // been marked at that point. Therefore some of the maps are not
13934 // collected until the second garbage collection.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013935 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013936 CcTest::heap()->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
Leon Clarked91b9f72010-01-27 17:25:45 +000013937 int count = GetGlobalObjectsCount();
Steve Blocka7e24c12009-10-30 11:49:00 +000013938#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013939 if (count != expected) CcTest::heap()->TracePathToGlobal();
Steve Blocka7e24c12009-10-30 11:49:00 +000013940#endif
Ben Murdochf87a2032010-10-22 12:50:53 +010013941 CHECK_EQ(expected, count);
Steve Blocka7e24c12009-10-30 11:49:00 +000013942}
13943
13944
13945TEST(DontLeakGlobalObjects) {
13946 // Regression test for issues 1139850 and 1174891.
13947
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013948 i::FLAG_expose_gc = true;
Steve Blocka7e24c12009-10-30 11:49:00 +000013949 v8::V8::Initialize();
13950
Steve Blocka7e24c12009-10-30 11:49:00 +000013951 for (int i = 0; i < 5; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013952 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013953 LocalContext context;
13954 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013955 CcTest::isolate()->ContextDisposedNotification();
Ben Murdochf87a2032010-10-22 12:50:53 +010013956 CheckSurvivingGlobalObjectsCount(0);
Steve Blocka7e24c12009-10-30 11:49:00 +000013957
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013958 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013959 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013960 v8_compile("Date")->Run(context.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000013961 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013962 CcTest::isolate()->ContextDisposedNotification();
Ben Murdochf87a2032010-10-22 12:50:53 +010013963 CheckSurvivingGlobalObjectsCount(0);
Steve Blocka7e24c12009-10-30 11:49:00 +000013964
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013965 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013966 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013967 v8_compile("/aaa/")->Run(context.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000013968 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013969 CcTest::isolate()->ContextDisposedNotification();
Ben Murdochf87a2032010-10-22 12:50:53 +010013970 CheckSurvivingGlobalObjectsCount(0);
Steve Blocka7e24c12009-10-30 11:49:00 +000013971
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013972 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013973 const char* extension_list[] = { "v8/gc" };
13974 v8::ExtensionConfiguration extensions(1, extension_list);
13975 LocalContext context(&extensions);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013976 v8_compile("gc();")->Run(context.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000013977 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013978 CcTest::isolate()->ContextDisposedNotification();
Ben Murdochf87a2032010-10-22 12:50:53 +010013979 CheckSurvivingGlobalObjectsCount(0);
Steve Blocka7e24c12009-10-30 11:49:00 +000013980 }
13981}
13982
13983
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013984TEST(CopyablePersistent) {
13985 LocalContext context;
13986 v8::Isolate* isolate = context->GetIsolate();
13987 i::GlobalHandles* globals =
13988 reinterpret_cast<i::Isolate*>(isolate)->global_handles();
13989 int initial_handles = globals->global_handles_count();
13990 typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> >
13991 CopyableObject;
13992 {
13993 CopyableObject handle1;
13994 {
13995 v8::HandleScope scope(isolate);
13996 handle1.Reset(isolate, v8::Object::New(isolate));
13997 }
13998 CHECK_EQ(initial_handles + 1, globals->global_handles_count());
13999 CopyableObject handle2;
14000 handle2 = handle1;
14001 CHECK(handle1 == handle2);
14002 CHECK_EQ(initial_handles + 2, globals->global_handles_count());
14003 CopyableObject handle3(handle2);
14004 CHECK(handle1 == handle3);
14005 CHECK_EQ(initial_handles + 3, globals->global_handles_count());
14006 }
14007 // Verify autodispose
14008 CHECK_EQ(initial_handles, globals->global_handles_count());
14009}
14010
14011
14012static void WeakApiCallback(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014013 const v8::WeakCallbackInfo<Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014014 data.GetParameter()->Reset();
14015 delete data.GetParameter();
14016}
14017
14018
14019TEST(WeakCallbackApi) {
14020 LocalContext context;
14021 v8::Isolate* isolate = context->GetIsolate();
14022 i::GlobalHandles* globals =
14023 reinterpret_cast<i::Isolate*>(isolate)->global_handles();
14024 int initial_handles = globals->global_handles_count();
14025 {
14026 v8::HandleScope scope(isolate);
14027 v8::Local<v8::Object> obj = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014028 CHECK(
14029 obj->Set(context.local(), v8_str("key"), v8::Integer::New(isolate, 231))
14030 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014031 v8::Persistent<v8::Object>* handle =
14032 new v8::Persistent<v8::Object>(isolate, obj);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014033 handle->SetWeak<v8::Persistent<v8::Object>>(
14034 handle, WeakApiCallback, v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014035 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014036 reinterpret_cast<i::Isolate*>(isolate)->heap()->CollectAllGarbage(
14037 i::Heap::kAbortIncrementalMarkingMask);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014038 // Verify disposed.
14039 CHECK_EQ(initial_handles, globals->global_handles_count());
14040}
14041
14042
Steve Blocka7e24c12009-10-30 11:49:00 +000014043v8::Persistent<v8::Object> some_object;
14044v8::Persistent<v8::Object> bad_handle;
14045
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014046
14047void NewPersistentHandleCallback2(
14048 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014049 v8::HandleScope scope(data.GetIsolate());
14050 bad_handle.Reset(data.GetIsolate(), some_object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014051}
14052
14053
14054void NewPersistentHandleCallback1(
14055 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014056 data.GetParameter()->Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014057 data.SetSecondPassCallback(NewPersistentHandleCallback2);
Steve Blocka7e24c12009-10-30 11:49:00 +000014058}
14059
14060
14061THREADED_TEST(NewPersistentHandleFromWeakCallback) {
14062 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014063 v8::Isolate* isolate = context->GetIsolate();
Steve Blocka7e24c12009-10-30 11:49:00 +000014064
14065 v8::Persistent<v8::Object> handle1, handle2;
14066 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014067 v8::HandleScope scope(isolate);
14068 some_object.Reset(isolate, v8::Object::New(isolate));
14069 handle1.Reset(isolate, v8::Object::New(isolate));
14070 handle2.Reset(isolate, v8::Object::New(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000014071 }
14072 // Note: order is implementation dependent alas: currently
14073 // global handle nodes are processed by PostGarbageCollectionProcessing
14074 // in reverse allocation order, so if second allocated handle is deleted,
14075 // weak callback of the first handle would be able to 'reallocate' it.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014076 handle1.SetWeak(&handle1, NewPersistentHandleCallback1,
14077 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014078 handle2.Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014079 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +000014080}
14081
14082
14083v8::Persistent<v8::Object> to_be_disposed;
14084
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014085
14086void DisposeAndForceGcCallback2(
14087 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014088 to_be_disposed.Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014089 CcTest::heap()->CollectAllGarbage();
14090}
14091
14092
14093void DisposeAndForceGcCallback1(
14094 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014095 data.GetParameter()->Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014096 data.SetSecondPassCallback(DisposeAndForceGcCallback2);
Steve Blocka7e24c12009-10-30 11:49:00 +000014097}
14098
14099
14100THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
14101 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014102 v8::Isolate* isolate = context->GetIsolate();
Steve Blocka7e24c12009-10-30 11:49:00 +000014103
14104 v8::Persistent<v8::Object> handle1, handle2;
14105 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014106 v8::HandleScope scope(isolate);
14107 handle1.Reset(isolate, v8::Object::New(isolate));
14108 handle2.Reset(isolate, v8::Object::New(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000014109 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014110 handle1.SetWeak(&handle1, DisposeAndForceGcCallback1,
14111 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014112 to_be_disposed.Reset(isolate, handle2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014113 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +000014114}
14115
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014116void DisposingCallback(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014117 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014118 data.GetParameter()->Reset();
Steve Blockd0582a62009-12-15 09:54:21 +000014119}
14120
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014121void HandleCreatingCallback2(
14122 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014123 v8::HandleScope scope(data.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014124 v8::Global<v8::Object>(data.GetIsolate(), v8::Object::New(data.GetIsolate()));
14125}
14126
14127
14128void HandleCreatingCallback1(
14129 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014130 data.GetParameter()->Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014131 data.SetSecondPassCallback(HandleCreatingCallback2);
Steve Blockd0582a62009-12-15 09:54:21 +000014132}
14133
14134
14135THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014136 v8::Locker locker(CcTest::isolate());
Steve Blockd0582a62009-12-15 09:54:21 +000014137 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014138 v8::Isolate* isolate = context->GetIsolate();
Steve Blockd0582a62009-12-15 09:54:21 +000014139
14140 v8::Persistent<v8::Object> handle1, handle2, handle3;
14141 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014142 v8::HandleScope scope(isolate);
14143 handle3.Reset(isolate, v8::Object::New(isolate));
14144 handle2.Reset(isolate, v8::Object::New(isolate));
14145 handle1.Reset(isolate, v8::Object::New(isolate));
Steve Blockd0582a62009-12-15 09:54:21 +000014146 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014147 handle2.SetWeak(&handle2, DisposingCallback,
14148 v8::WeakCallbackType::kParameter);
14149 handle3.SetWeak(&handle3, HandleCreatingCallback1,
14150 v8::WeakCallbackType::kParameter);
14151 CcTest::heap()->CollectAllGarbage();
14152 EmptyMessageQueues(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000014153}
14154
Steve Blocka7e24c12009-10-30 11:49:00 +000014155
14156THREADED_TEST(CheckForCrossContextObjectLiterals) {
14157 v8::V8::Initialize();
14158
14159 const int nof = 2;
14160 const char* sources[nof] = {
14161 "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
14162 "Object()"
14163 };
14164
14165 for (int i = 0; i < nof; i++) {
14166 const char* source = sources[i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014167 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000014168 LocalContext context;
14169 CompileRun(source);
14170 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014171 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000014172 LocalContext context;
14173 CompileRun(source);
14174 }
14175 }
14176}
14177
14178
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014179static v8::Local<Value> NestedScope(v8::Local<Context> env) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014180 v8::EscapableHandleScope inner(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000014181 env->Enter();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014182 v8::Local<Value> three = v8_num(3);
14183 v8::Local<Value> value = inner.Escape(three);
Steve Blocka7e24c12009-10-30 11:49:00 +000014184 env->Exit();
14185 return value;
14186}
14187
14188
14189THREADED_TEST(NestedHandleScopeAndContexts) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014190 v8::Isolate* isolate = CcTest::isolate();
14191 v8::HandleScope outer(isolate);
14192 v8::Local<Context> env = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000014193 env->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014194 v8::Local<Value> value = NestedScope(env);
14195 v8::Local<String> str(value->ToString(env).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010014196 CHECK(!str.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000014197 env->Exit();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014198}
14199
14200
14201static bool MatchPointers(void* key1, void* key2) {
14202 return key1 == key2;
14203}
14204
14205
14206struct SymbolInfo {
14207 size_t id;
14208 size_t size;
14209 std::string name;
14210};
14211
14212
14213class SetFunctionEntryHookTest {
14214 public:
14215 SetFunctionEntryHookTest() {
14216 CHECK(instance_ == NULL);
14217 instance_ = this;
14218 }
14219 ~SetFunctionEntryHookTest() {
14220 CHECK(instance_ == this);
14221 instance_ = NULL;
14222 }
14223 void Reset() {
14224 symbols_.clear();
14225 symbol_locations_.clear();
14226 invocations_.clear();
14227 }
14228 void RunTest();
14229 void OnJitEvent(const v8::JitCodeEvent* event);
14230 static void JitEvent(const v8::JitCodeEvent* event) {
14231 CHECK(instance_ != NULL);
14232 instance_->OnJitEvent(event);
14233 }
14234
14235 void OnEntryHook(uintptr_t function,
14236 uintptr_t return_addr_location);
14237 static void EntryHook(uintptr_t function,
14238 uintptr_t return_addr_location) {
14239 CHECK(instance_ != NULL);
14240 instance_->OnEntryHook(function, return_addr_location);
14241 }
14242
14243 static void RuntimeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
14244 CHECK(instance_ != NULL);
14245 args.GetReturnValue().Set(v8_num(42));
14246 }
14247 void RunLoopInNewEnv(v8::Isolate* isolate);
14248
14249 // Records addr as location of symbol.
14250 void InsertSymbolAt(i::Address addr, SymbolInfo* symbol);
14251
14252 // Finds the symbol containing addr
14253 SymbolInfo* FindSymbolForAddr(i::Address addr);
14254 // Returns the number of invocations where the caller name contains
14255 // \p caller_name and the function name contains \p function_name.
14256 int CountInvocations(const char* caller_name,
14257 const char* function_name);
14258
14259 i::Handle<i::JSFunction> foo_func_;
14260 i::Handle<i::JSFunction> bar_func_;
14261
14262 typedef std::map<size_t, SymbolInfo> SymbolMap;
14263 typedef std::map<i::Address, SymbolInfo*> SymbolLocationMap;
14264 typedef std::map<std::pair<SymbolInfo*, SymbolInfo*>, int> InvocationMap;
14265 SymbolMap symbols_;
14266 SymbolLocationMap symbol_locations_;
14267 InvocationMap invocations_;
14268
14269 static SetFunctionEntryHookTest* instance_;
14270};
14271SetFunctionEntryHookTest* SetFunctionEntryHookTest::instance_ = NULL;
14272
14273
14274// Returns true if addr is in the range [start, start+len).
14275static bool Overlaps(i::Address start, size_t len, i::Address addr) {
14276 if (start <= addr && start + len > addr)
14277 return true;
14278
14279 return false;
14280}
14281
14282void SetFunctionEntryHookTest::InsertSymbolAt(i::Address addr,
14283 SymbolInfo* symbol) {
14284 // Insert the symbol at the new location.
14285 SymbolLocationMap::iterator it =
14286 symbol_locations_.insert(std::make_pair(addr, symbol)).first;
14287 // Now erase symbols to the left and right that overlap this one.
14288 while (it != symbol_locations_.begin()) {
14289 SymbolLocationMap::iterator left = it;
14290 --left;
14291 if (!Overlaps(left->first, left->second->size, addr))
14292 break;
14293 symbol_locations_.erase(left);
14294 }
14295
14296 // Now erase symbols to the left and right that overlap this one.
14297 while (true) {
14298 SymbolLocationMap::iterator right = it;
14299 ++right;
14300 if (right == symbol_locations_.end())
14301 break;
14302 if (!Overlaps(addr, symbol->size, right->first))
14303 break;
14304 symbol_locations_.erase(right);
14305 }
14306}
14307
14308
14309void SetFunctionEntryHookTest::OnJitEvent(const v8::JitCodeEvent* event) {
14310 switch (event->type) {
14311 case v8::JitCodeEvent::CODE_ADDED: {
14312 CHECK(event->code_start != NULL);
14313 CHECK_NE(0, static_cast<int>(event->code_len));
14314 CHECK(event->name.str != NULL);
14315 size_t symbol_id = symbols_.size();
14316
14317 // Record the new symbol.
14318 SymbolInfo& info = symbols_[symbol_id];
14319 info.id = symbol_id;
14320 info.size = event->code_len;
14321 info.name.assign(event->name.str, event->name.str + event->name.len);
14322
14323 // And record it's location.
14324 InsertSymbolAt(reinterpret_cast<i::Address>(event->code_start), &info);
14325 }
14326 break;
14327
14328 case v8::JitCodeEvent::CODE_MOVED: {
14329 // We would like to never see code move that we haven't seen before,
14330 // but the code creation event does not happen until the line endings
14331 // have been calculated (this is so that we can report the line in the
14332 // script at which the function source is found, see
14333 // Compiler::RecordFunctionCompilation) and the line endings
14334 // calculations can cause a GC, which can move the newly created code
14335 // before its existence can be logged.
14336 SymbolLocationMap::iterator it(
14337 symbol_locations_.find(
14338 reinterpret_cast<i::Address>(event->code_start)));
14339 if (it != symbol_locations_.end()) {
14340 // Found a symbol at this location, move it.
14341 SymbolInfo* info = it->second;
14342 symbol_locations_.erase(it);
14343 InsertSymbolAt(reinterpret_cast<i::Address>(event->new_code_start),
14344 info);
14345 }
14346 }
14347 default:
14348 break;
14349 }
14350}
14351
14352void SetFunctionEntryHookTest::OnEntryHook(
14353 uintptr_t function, uintptr_t return_addr_location) {
14354 // Get the function's code object.
14355 i::Code* function_code = i::Code::GetCodeFromTargetAddress(
14356 reinterpret_cast<i::Address>(function));
14357 CHECK(function_code != NULL);
14358
14359 // Then try and look up the caller's code object.
14360 i::Address caller = *reinterpret_cast<i::Address*>(return_addr_location);
14361
14362 // Count the invocation.
14363 SymbolInfo* caller_symbol = FindSymbolForAddr(caller);
14364 SymbolInfo* function_symbol =
14365 FindSymbolForAddr(reinterpret_cast<i::Address>(function));
14366 ++invocations_[std::make_pair(caller_symbol, function_symbol)];
14367
14368 if (!bar_func_.is_null() && function_code == bar_func_->code()) {
14369 // Check that we have a symbol for the "bar" function at the right location.
14370 SymbolLocationMap::iterator it(
14371 symbol_locations_.find(function_code->instruction_start()));
14372 CHECK(it != symbol_locations_.end());
14373 }
14374
14375 if (!foo_func_.is_null() && function_code == foo_func_->code()) {
14376 // Check that we have a symbol for "foo" at the right location.
14377 SymbolLocationMap::iterator it(
14378 symbol_locations_.find(function_code->instruction_start()));
14379 CHECK(it != symbol_locations_.end());
14380 }
14381}
14382
14383
14384SymbolInfo* SetFunctionEntryHookTest::FindSymbolForAddr(i::Address addr) {
14385 SymbolLocationMap::iterator it(symbol_locations_.lower_bound(addr));
14386 // Do we have a direct hit on a symbol?
14387 if (it != symbol_locations_.end()) {
14388 if (it->first == addr)
14389 return it->second;
14390 }
14391
14392 // If not a direct hit, it'll have to be the previous symbol.
14393 if (it == symbol_locations_.begin())
14394 return NULL;
14395
14396 --it;
14397 size_t offs = addr - it->first;
14398 if (offs < it->second->size)
14399 return it->second;
14400
14401 return NULL;
14402}
14403
14404
14405int SetFunctionEntryHookTest::CountInvocations(
14406 const char* caller_name, const char* function_name) {
14407 InvocationMap::iterator it(invocations_.begin());
14408 int invocations = 0;
14409 for (; it != invocations_.end(); ++it) {
14410 SymbolInfo* caller = it->first.first;
14411 SymbolInfo* function = it->first.second;
14412
14413 // Filter out non-matching functions.
14414 if (function_name != NULL) {
14415 if (function->name.find(function_name) == std::string::npos)
14416 continue;
14417 }
14418
14419 // Filter out non-matching callers.
14420 if (caller_name != NULL) {
14421 if (caller == NULL)
14422 continue;
14423 if (caller->name.find(caller_name) == std::string::npos)
14424 continue;
14425 }
14426
14427 // It matches add the invocation count to the tally.
14428 invocations += it->second;
14429 }
14430
14431 return invocations;
14432}
14433
14434
14435void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
14436 v8::HandleScope outer(isolate);
14437 v8::Local<Context> env = Context::New(isolate);
14438 env->Enter();
14439
14440 Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
14441 t->Set(v8_str("asdf"), v8::FunctionTemplate::New(isolate, RuntimeCallback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014442 CHECK(env->Global()
14443 ->Set(env, v8_str("obj"), t->NewInstance(env).ToLocalChecked())
14444 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014445
14446 const char* script =
14447 "function bar() {\n"
14448 " var sum = 0;\n"
14449 " for (i = 0; i < 100; ++i)\n"
14450 " sum = foo(i);\n"
14451 " return sum;\n"
14452 "}\n"
14453 "function foo(i) { return i * i; }\n"
14454 "// Invoke on the runtime function.\n"
14455 "obj.asdf()";
14456 CompileRun(script);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014457 bar_func_ = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(
14458 *env->Global()->Get(env, v8_str("bar")).ToLocalChecked()));
14459 CHECK(!bar_func_.is_null());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014460
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014461 foo_func_ = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(
14462 *env->Global()->Get(env, v8_str("foo")).ToLocalChecked()));
14463 CHECK(!foo_func_.is_null());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014464
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014465 v8::Local<v8::Value> value = CompileRun("bar();");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014466 CHECK(value->IsNumber());
14467 CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
14468
14469 // Test the optimized codegen path.
14470 value = CompileRun("%OptimizeFunctionOnNextCall(foo);"
14471 "bar();");
14472 CHECK(value->IsNumber());
14473 CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
14474
14475 env->Exit();
14476}
14477
14478
14479void SetFunctionEntryHookTest::RunTest() {
14480 // Work in a new isolate throughout.
14481 v8::Isolate::CreateParams create_params;
14482 create_params.entry_hook = EntryHook;
14483 create_params.code_event_handler = JitEvent;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014484 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014485 v8::Isolate* isolate = v8::Isolate::New(create_params);
14486
14487 {
14488 v8::Isolate::Scope scope(isolate);
14489
14490 RunLoopInNewEnv(isolate);
14491
14492 // Check the exepected invocation counts.
14493 CHECK_EQ(2, CountInvocations(NULL, "bar"));
14494 CHECK_EQ(200, CountInvocations("bar", "foo"));
14495 CHECK_EQ(200, CountInvocations(NULL, "foo"));
14496
14497 // Verify that we have an entry hook on some specific stubs.
14498 CHECK_NE(0, CountInvocations(NULL, "CEntryStub"));
14499 CHECK_NE(0, CountInvocations(NULL, "JSEntryStub"));
14500 CHECK_NE(0, CountInvocations(NULL, "JSEntryTrampoline"));
14501 }
14502 isolate->Dispose();
14503
14504 Reset();
14505
14506 // Make sure a second isolate is unaffected by the previous entry hook.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014507 create_params = v8::Isolate::CreateParams();
14508 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
14509 isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014510 {
14511 v8::Isolate::Scope scope(isolate);
14512
14513 // Reset the entry count to zero and set the entry hook.
14514 RunLoopInNewEnv(isolate);
14515
14516 // We should record no invocations in this isolate.
14517 CHECK_EQ(0, static_cast<int>(invocations_.size()));
14518 }
14519
14520 isolate->Dispose();
14521}
14522
14523
14524TEST(SetFunctionEntryHook) {
14525 // FunctionEntryHook does not work well with experimental natives.
14526 // Experimental natives are compiled during snapshot deserialization.
14527 // This test breaks because InstallGetter (function from snapshot that
14528 // only gets called from experimental natives) is compiled with entry hooks.
14529 i::FLAG_allow_natives_syntax = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014530 i::FLAG_turbo_inlining = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014531 i::FLAG_use_inlining = false;
14532
14533 SetFunctionEntryHookTest test;
14534 test.RunTest();
14535}
14536
14537
14538static i::HashMap* code_map = NULL;
14539static i::HashMap* jitcode_line_info = NULL;
14540static int saw_bar = 0;
14541static int move_events = 0;
14542
14543
14544static bool FunctionNameIs(const char* expected,
14545 const v8::JitCodeEvent* event) {
14546 // Log lines for functions are of the general form:
14547 // "LazyCompile:<type><function_name>", where the type is one of
14548 // "*", "~" or "".
14549 static const char kPreamble[] = "LazyCompile:";
14550 static size_t kPreambleLen = sizeof(kPreamble) - 1;
14551
14552 if (event->name.len < sizeof(kPreamble) - 1 ||
14553 strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
14554 return false;
14555 }
14556
14557 const char* tail = event->name.str + kPreambleLen;
14558 size_t tail_len = event->name.len - kPreambleLen;
14559 size_t expected_len = strlen(expected);
14560 if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
14561 --tail_len;
14562 ++tail;
14563 }
14564
14565 // Check for tails like 'bar :1'.
14566 if (tail_len > expected_len + 2 &&
14567 tail[expected_len] == ' ' &&
14568 tail[expected_len + 1] == ':' &&
14569 tail[expected_len + 2] &&
14570 !strncmp(tail, expected, expected_len)) {
14571 return true;
14572 }
14573
14574 if (tail_len != expected_len)
14575 return false;
14576
14577 return strncmp(tail, expected, expected_len) == 0;
14578}
14579
14580
14581static void event_handler(const v8::JitCodeEvent* event) {
14582 CHECK(event != NULL);
14583 CHECK(code_map != NULL);
14584 CHECK(jitcode_line_info != NULL);
14585
14586 class DummyJitCodeLineInfo {
14587 };
14588
14589 switch (event->type) {
14590 case v8::JitCodeEvent::CODE_ADDED: {
14591 CHECK(event->code_start != NULL);
14592 CHECK_NE(0, static_cast<int>(event->code_len));
14593 CHECK(event->name.str != NULL);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014594 i::HashMap::Entry* entry = code_map->LookupOrInsert(
14595 event->code_start, i::ComputePointerHash(event->code_start));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014596 entry->value = reinterpret_cast<void*>(event->code_len);
14597
14598 if (FunctionNameIs("bar", event)) {
14599 ++saw_bar;
14600 }
14601 }
14602 break;
14603
14604 case v8::JitCodeEvent::CODE_MOVED: {
14605 uint32_t hash = i::ComputePointerHash(event->code_start);
14606 // We would like to never see code move that we haven't seen before,
14607 // but the code creation event does not happen until the line endings
14608 // have been calculated (this is so that we can report the line in the
14609 // script at which the function source is found, see
14610 // Compiler::RecordFunctionCompilation) and the line endings
14611 // calculations can cause a GC, which can move the newly created code
14612 // before its existence can be logged.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014613 i::HashMap::Entry* entry = code_map->Lookup(event->code_start, hash);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014614 if (entry != NULL) {
14615 ++move_events;
14616
14617 CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
14618 code_map->Remove(event->code_start, hash);
14619
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014620 entry = code_map->LookupOrInsert(
14621 event->new_code_start,
14622 i::ComputePointerHash(event->new_code_start));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014623 entry->value = reinterpret_cast<void*>(event->code_len);
14624 }
14625 }
14626 break;
14627
14628 case v8::JitCodeEvent::CODE_REMOVED:
14629 // Object/code removal events are currently not dispatched from the GC.
14630 CHECK(false);
14631 break;
14632
14633 // For CODE_START_LINE_INFO_RECORDING event, we will create one
14634 // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
14635 // record it in jitcode_line_info.
14636 case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
14637 DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
14638 v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
14639 temp_event->user_data = line_info;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014640 i::HashMap::Entry* entry = jitcode_line_info->LookupOrInsert(
14641 line_info, i::ComputePointerHash(line_info));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014642 entry->value = reinterpret_cast<void*>(line_info);
14643 }
14644 break;
14645 // For these two events, we will check whether the event->user_data
14646 // data structure is created before during CODE_START_LINE_INFO_RECORDING
14647 // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
14648 case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
14649 CHECK(event->user_data != NULL);
14650 uint32_t hash = i::ComputePointerHash(event->user_data);
14651 i::HashMap::Entry* entry =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014652 jitcode_line_info->Lookup(event->user_data, hash);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014653 CHECK(entry != NULL);
14654 delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
14655 }
14656 break;
14657
14658 case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
14659 CHECK(event->user_data != NULL);
14660 uint32_t hash = i::ComputePointerHash(event->user_data);
14661 i::HashMap::Entry* entry =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014662 jitcode_line_info->Lookup(event->user_data, hash);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014663 CHECK(entry != NULL);
14664 }
14665 break;
14666
14667 default:
14668 // Impossible event.
14669 CHECK(false);
14670 break;
14671 }
14672}
14673
14674
14675UNINITIALIZED_TEST(SetJitCodeEventHandler) {
14676 i::FLAG_stress_compaction = true;
14677 i::FLAG_incremental_marking = false;
14678 if (i::FLAG_never_compact) return;
14679 const char* script =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014680 "function bar() {"
14681 " var sum = 0;"
14682 " for (i = 0; i < 10; ++i)"
14683 " sum = foo(i);"
14684 " return sum;"
14685 "}"
14686 "function foo(i) { return i; };"
14687 "bar();";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014688
14689 // Run this test in a new isolate to make sure we don't
14690 // have remnants of state from other code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014691 v8::Isolate::CreateParams create_params;
14692 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
14693 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014694 isolate->Enter();
14695 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
14696 i::Heap* heap = i_isolate->heap();
14697
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014698 // Start with a clean slate.
14699 heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler_Prepare");
14700
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014701 {
14702 v8::HandleScope scope(isolate);
14703 i::HashMap code(MatchPointers);
14704 code_map = &code;
14705
14706 i::HashMap lineinfo(MatchPointers);
14707 jitcode_line_info = &lineinfo;
14708
14709 saw_bar = 0;
14710 move_events = 0;
14711
14712 isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
14713
14714 // Generate new code objects sparsely distributed across several
14715 // different fragmented code-space pages.
14716 const int kIterations = 10;
14717 for (int i = 0; i < kIterations; ++i) {
14718 LocalContext env(isolate);
14719 i::AlwaysAllocateScope always_allocate(i_isolate);
14720 SimulateFullSpace(heap->code_space());
14721 CompileRun(script);
14722
14723 // Keep a strong reference to the code object in the handle scope.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014724 i::Handle<i::Code> bar_code(
14725 i::Handle<i::JSFunction>::cast(
14726 v8::Utils::OpenHandle(*env->Global()
14727 ->Get(env.local(), v8_str("bar"))
14728 .ToLocalChecked()))
14729 ->code());
14730 i::Handle<i::Code> foo_code(
14731 i::Handle<i::JSFunction>::cast(
14732 v8::Utils::OpenHandle(*env->Global()
14733 ->Get(env.local(), v8_str("foo"))
14734 .ToLocalChecked()))
14735 ->code());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014736
14737 // Clear the compilation cache to get more wastage.
14738 reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear();
14739 }
14740
14741 // Force code movement.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014742 heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler_Move");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014743
14744 isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
14745
14746 CHECK_LE(kIterations, saw_bar);
14747 CHECK_LT(0, move_events);
14748
14749 code_map = NULL;
14750 jitcode_line_info = NULL;
14751 }
14752
14753 isolate->Exit();
14754 isolate->Dispose();
14755
14756 // Do this in a new isolate.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014757 isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014758 isolate->Enter();
14759
14760 // Verify that we get callbacks for existing code objects when we
14761 // request enumeration of existing code.
14762 {
14763 v8::HandleScope scope(isolate);
14764 LocalContext env(isolate);
14765 CompileRun(script);
14766
14767 // Now get code through initial iteration.
14768 i::HashMap code(MatchPointers);
14769 code_map = &code;
14770
14771 i::HashMap lineinfo(MatchPointers);
14772 jitcode_line_info = &lineinfo;
14773
14774 isolate->SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting,
14775 event_handler);
14776 isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
14777
14778 jitcode_line_info = NULL;
14779 // We expect that we got some events. Note that if we could get code removal
14780 // notifications, we could compare two collections, one created by listening
14781 // from the time of creation of an isolate, and the other by subscribing
14782 // with EnumExisting.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014783 CHECK_LT(0u, code.occupancy());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014784
14785 code_map = NULL;
14786 }
14787
14788 isolate->Exit();
14789 isolate->Dispose();
Steve Blocka7e24c12009-10-30 11:49:00 +000014790}
14791
14792
14793THREADED_TEST(ExternalAllocatedMemory) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014794 v8::Isolate* isolate = CcTest::isolate();
14795 v8::HandleScope outer(isolate);
14796 v8::Local<Context> env(Context::New(isolate));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010014797 CHECK(!env.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014798 const int64_t kSize = 1024*1024;
14799 int64_t baseline = isolate->AdjustAmountOfExternalAllocatedMemory(0);
14800 CHECK_EQ(baseline + kSize,
14801 isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
14802 CHECK_EQ(baseline,
14803 isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014804 const int64_t kTriggerGCSize =
14805 v8::internal::Internals::kExternalAllocationLimit + 1;
14806 CHECK_EQ(baseline + kTriggerGCSize,
14807 isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize));
14808 CHECK_EQ(baseline,
14809 isolate->AdjustAmountOfExternalAllocatedMemory(-kTriggerGCSize));
14810}
14811
14812
14813TEST(Regress51719) {
14814 i::FLAG_incremental_marking = false;
14815 CcTest::InitializeVM();
14816
14817 const int64_t kTriggerGCSize =
14818 v8::internal::Internals::kExternalAllocationLimit + 1;
14819 v8::Isolate* isolate = CcTest::isolate();
14820 isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize);
Steve Blocka7e24c12009-10-30 11:49:00 +000014821}
14822
14823
14824// Regression test for issue 54, object templates with internal fields
14825// but no accessors or interceptors did not get their internal field
14826// count set on instances.
14827THREADED_TEST(Regress54) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014828 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014829 v8::Isolate* isolate = context->GetIsolate();
14830 v8::HandleScope outer(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000014831 static v8::Persistent<v8::ObjectTemplate> templ;
14832 if (templ.IsEmpty()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014833 v8::EscapableHandleScope inner(isolate);
14834 v8::Local<v8::ObjectTemplate> local = v8::ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000014835 local->SetInternalFieldCount(1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014836 templ.Reset(isolate, inner.Escape(local));
Steve Blocka7e24c12009-10-30 11:49:00 +000014837 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014838 v8::Local<v8::Object> result =
14839 v8::Local<v8::ObjectTemplate>::New(isolate, templ)
14840 ->NewInstance(context.local())
14841 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000014842 CHECK_EQ(1, result->InternalFieldCount());
14843}
14844
14845
14846// If part of the threaded tests, this test makes ThreadingTest fail
14847// on mac.
14848TEST(CatchStackOverflow) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014849 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014850 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014851 v8::TryCatch try_catch(context->GetIsolate());
14852 v8::Local<v8::Value> result = CompileRun(
14853 "function f() {"
14854 " return f();"
14855 "}"
14856 ""
14857 "f();");
Steve Blocka7e24c12009-10-30 11:49:00 +000014858 CHECK(result.IsEmpty());
14859}
14860
14861
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014862static void CheckTryCatchSourceInfo(v8::Local<v8::Script> script,
Steve Blocka7e24c12009-10-30 11:49:00 +000014863 const char* resource_name,
14864 int line_offset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014865 v8::HandleScope scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014866 v8::TryCatch try_catch(CcTest::isolate());
14867 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
14868 CHECK(script->Run(context).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000014869 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014870 v8::Local<v8::Message> message = try_catch.Message();
Steve Blocka7e24c12009-10-30 11:49:00 +000014871 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014872 CHECK_EQ(10 + line_offset, message->GetLineNumber(context).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000014873 CHECK_EQ(91, message->GetStartPosition());
14874 CHECK_EQ(92, message->GetEndPosition());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014875 CHECK_EQ(2, message->GetStartColumn(context).FromJust());
14876 CHECK_EQ(3, message->GetEndColumn(context).FromJust());
14877 v8::String::Utf8Value line(message->GetSourceLine(context).ToLocalChecked());
14878 CHECK_EQ(0, strcmp(" throw 'nirk';", *line));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014879 v8::String::Utf8Value name(message->GetScriptOrigin().ResourceName());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014880 CHECK_EQ(0, strcmp(resource_name, *name));
Steve Blocka7e24c12009-10-30 11:49:00 +000014881}
14882
14883
14884THREADED_TEST(TryCatchSourceInfo) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014885 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014886 v8::HandleScope scope(context->GetIsolate());
14887 v8::Local<v8::String> source = v8_str(
Steve Blocka7e24c12009-10-30 11:49:00 +000014888 "function Foo() {\n"
14889 " return Bar();\n"
14890 "}\n"
14891 "\n"
14892 "function Bar() {\n"
14893 " return Baz();\n"
14894 "}\n"
14895 "\n"
14896 "function Baz() {\n"
14897 " throw 'nirk';\n"
14898 "}\n"
14899 "\n"
14900 "Foo();\n");
14901
14902 const char* resource_name;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014903 v8::Local<v8::Script> script;
Steve Blocka7e24c12009-10-30 11:49:00 +000014904 resource_name = "test.js";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014905 script = CompileWithOrigin(source, resource_name);
Steve Blocka7e24c12009-10-30 11:49:00 +000014906 CheckTryCatchSourceInfo(script, resource_name, 0);
14907
14908 resource_name = "test1.js";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014909 v8::ScriptOrigin origin1(v8_str(resource_name));
14910 script =
14911 v8::Script::Compile(context.local(), source, &origin1).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000014912 CheckTryCatchSourceInfo(script, resource_name, 0);
14913
14914 resource_name = "test2.js";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014915 v8::ScriptOrigin origin2(v8_str(resource_name),
14916 v8::Integer::New(context->GetIsolate(), 7));
14917 script =
14918 v8::Script::Compile(context.local(), source, &origin2).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000014919 CheckTryCatchSourceInfo(script, resource_name, 7);
14920}
14921
14922
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014923THREADED_TEST(TryCatchSourceInfoForEOSError) {
14924 LocalContext context;
14925 v8::HandleScope scope(context->GetIsolate());
14926 v8::TryCatch try_catch(context->GetIsolate());
14927 CHECK(v8::Script::Compile(context.local(), v8_str("!\n")).IsEmpty());
14928 CHECK(try_catch.HasCaught());
14929 v8::Local<v8::Message> message = try_catch.Message();
14930 CHECK_EQ(1, message->GetLineNumber(context.local()).FromJust());
14931 CHECK_EQ(0, message->GetStartColumn(context.local()).FromJust());
14932}
14933
14934
Steve Blocka7e24c12009-10-30 11:49:00 +000014935THREADED_TEST(CompilationCache) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014936 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014937 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014938 v8::Local<v8::String> source0 = v8_str("1234");
14939 v8::Local<v8::String> source1 = v8_str("1234");
14940 v8::Local<v8::Script> script0 = CompileWithOrigin(source0, "test.js");
14941 v8::Local<v8::Script> script1 = CompileWithOrigin(source1, "test.js");
14942 v8::Local<v8::Script> script2 = v8::Script::Compile(context.local(), source0)
14943 .ToLocalChecked(); // different origin
14944 CHECK_EQ(1234, script0->Run(context.local())
14945 .ToLocalChecked()
14946 ->Int32Value(context.local())
14947 .FromJust());
14948 CHECK_EQ(1234, script1->Run(context.local())
14949 .ToLocalChecked()
14950 ->Int32Value(context.local())
14951 .FromJust());
14952 CHECK_EQ(1234, script2->Run(context.local())
14953 .ToLocalChecked()
14954 ->Int32Value(context.local())
14955 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000014956}
14957
14958
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014959static void FunctionNameCallback(
14960 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014961 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014962 args.GetReturnValue().Set(v8_num(42));
Steve Blocka7e24c12009-10-30 11:49:00 +000014963}
14964
14965
14966THREADED_TEST(CallbackFunctionName) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014967 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014968 v8::Isolate* isolate = context->GetIsolate();
14969 v8::HandleScope scope(isolate);
14970 Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
14971 t->Set(v8_str("asdf"),
14972 v8::FunctionTemplate::New(isolate, FunctionNameCallback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014973 CHECK(context->Global()
14974 ->Set(context.local(), v8_str("obj"),
14975 t->NewInstance(context.local()).ToLocalChecked())
14976 .FromJust());
14977 v8::Local<v8::Value> value = CompileRun("obj.asdf.name");
Steve Blocka7e24c12009-10-30 11:49:00 +000014978 CHECK(value->IsString());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014979 v8::String::Utf8Value name(value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014980 CHECK_EQ(0, strcmp("asdf", *name));
Steve Blocka7e24c12009-10-30 11:49:00 +000014981}
14982
14983
14984THREADED_TEST(DateAccess) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014985 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014986 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014987 v8::Local<v8::Value> date =
14988 v8::Date::New(context.local(), 1224744689038.0).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000014989 CHECK(date->IsDate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014990 CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
Steve Blocka7e24c12009-10-30 11:49:00 +000014991}
14992
14993
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014994void CheckProperties(v8::Isolate* isolate, v8::Local<v8::Value> val,
14995 unsigned elmc, const char* elmv[]) {
14996 v8::Local<v8::Context> context = isolate->GetCurrentContext();
14997 v8::Local<v8::Object> obj = val.As<v8::Object>();
14998 v8::Local<v8::Array> props = obj->GetPropertyNames(context).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000014999 CHECK_EQ(elmc, props->Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015000 for (unsigned i = 0; i < elmc; i++) {
15001 v8::String::Utf8Value elm(
15002 props->Get(context, v8::Integer::New(isolate, i)).ToLocalChecked());
15003 CHECK_EQ(0, strcmp(elmv[i], *elm));
Steve Blocka7e24c12009-10-30 11:49:00 +000015004 }
15005}
15006
15007
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015008void CheckOwnProperties(v8::Isolate* isolate, v8::Local<v8::Value> val,
15009 unsigned elmc, const char* elmv[]) {
15010 v8::Local<v8::Context> context = isolate->GetCurrentContext();
15011 v8::Local<v8::Object> obj = val.As<v8::Object>();
15012 v8::Local<v8::Array> props =
15013 obj->GetOwnPropertyNames(context).ToLocalChecked();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000015014 CHECK_EQ(elmc, props->Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015015 for (unsigned i = 0; i < elmc; i++) {
15016 v8::String::Utf8Value elm(
15017 props->Get(context, v8::Integer::New(isolate, i)).ToLocalChecked());
15018 CHECK_EQ(0, strcmp(elmv[i], *elm));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000015019 }
15020}
15021
15022
Steve Blocka7e24c12009-10-30 11:49:00 +000015023THREADED_TEST(PropertyEnumeration) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015024 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015025 v8::Isolate* isolate = context->GetIsolate();
15026 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015027 v8::Local<v8::Value> obj = CompileRun(
Steve Blocka7e24c12009-10-30 11:49:00 +000015028 "var result = [];"
15029 "result[0] = {};"
15030 "result[1] = {a: 1, b: 2};"
15031 "result[2] = [1, 2, 3];"
15032 "var proto = {x: 1, y: 2, z: 3};"
15033 "var x = { __proto__: proto, w: 0, z: 1 };"
15034 "result[3] = x;"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015035 "result;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015036 v8::Local<v8::Array> elms = obj.As<v8::Array>();
15037 CHECK_EQ(4u, elms->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +000015038 int elmc0 = 0;
15039 const char** elmv0 = NULL;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015040 CheckProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015041 isolate,
15042 elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
15043 elmc0, elmv0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015044 CheckOwnProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015045 isolate,
15046 elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
15047 elmc0, elmv0);
Steve Blocka7e24c12009-10-30 11:49:00 +000015048 int elmc1 = 2;
15049 const char* elmv1[] = {"a", "b"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015050 CheckProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015051 isolate,
15052 elms->Get(context.local(), v8::Integer::New(isolate, 1)).ToLocalChecked(),
15053 elmc1, elmv1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015054 CheckOwnProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015055 isolate,
15056 elms->Get(context.local(), v8::Integer::New(isolate, 1)).ToLocalChecked(),
15057 elmc1, elmv1);
Steve Blocka7e24c12009-10-30 11:49:00 +000015058 int elmc2 = 3;
15059 const char* elmv2[] = {"0", "1", "2"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015060 CheckProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015061 isolate,
15062 elms->Get(context.local(), v8::Integer::New(isolate, 2)).ToLocalChecked(),
15063 elmc2, elmv2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015064 CheckOwnProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015065 isolate,
15066 elms->Get(context.local(), v8::Integer::New(isolate, 2)).ToLocalChecked(),
15067 elmc2, elmv2);
Steve Blocka7e24c12009-10-30 11:49:00 +000015068 int elmc3 = 4;
15069 const char* elmv3[] = {"w", "z", "x", "y"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015070 CheckProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015071 isolate,
15072 elms->Get(context.local(), v8::Integer::New(isolate, 3)).ToLocalChecked(),
15073 elmc3, elmv3);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000015074 int elmc4 = 2;
15075 const char* elmv4[] = {"w", "z"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015076 CheckOwnProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015077 isolate,
15078 elms->Get(context.local(), v8::Integer::New(isolate, 3)).ToLocalChecked(),
15079 elmc4, elmv4);
Steve Blocka7e24c12009-10-30 11:49:00 +000015080}
15081
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015082
Steve Block44f0eee2011-05-26 01:26:41 +010015083THREADED_TEST(PropertyEnumeration2) {
Steve Block44f0eee2011-05-26 01:26:41 +010015084 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015085 v8::Isolate* isolate = context->GetIsolate();
15086 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015087 v8::Local<v8::Value> obj = CompileRun(
Steve Block44f0eee2011-05-26 01:26:41 +010015088 "var result = [];"
15089 "result[0] = {};"
15090 "result[1] = {a: 1, b: 2};"
15091 "result[2] = [1, 2, 3];"
15092 "var proto = {x: 1, y: 2, z: 3};"
15093 "var x = { __proto__: proto, w: 0, z: 1 };"
15094 "result[3] = x;"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015095 "result;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015096 v8::Local<v8::Array> elms = obj.As<v8::Array>();
15097 CHECK_EQ(4u, elms->Length());
Steve Block44f0eee2011-05-26 01:26:41 +010015098 int elmc0 = 0;
15099 const char** elmv0 = NULL;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015100 CheckProperties(
15101 isolate,
15102 elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
15103 elmc0, elmv0);
Steve Block44f0eee2011-05-26 01:26:41 +010015104
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015105 v8::Local<v8::Value> val =
15106 elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked();
15107 v8::Local<v8::Array> props =
15108 val.As<v8::Object>()->GetPropertyNames(context.local()).ToLocalChecked();
15109 CHECK_EQ(0u, props->Length());
Steve Block44f0eee2011-05-26 01:26:41 +010015110 for (uint32_t i = 0; i < props->Length(); i++) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015111 printf("p[%u]\n", i);
Steve Block44f0eee2011-05-26 01:26:41 +010015112 }
15113}
Steve Blocka7e24c12009-10-30 11:49:00 +000015114
Steve Blocka7e24c12009-10-30 11:49:00 +000015115
15116THREADED_TEST(AccessChecksReenabledCorrectly) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015117 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015118 v8::Isolate* isolate = context->GetIsolate();
15119 v8::HandleScope scope(isolate);
15120 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015121 templ->SetAccessCheckCallback(AccessAlwaysBlocked);
Steve Blocka7e24c12009-10-30 11:49:00 +000015122 templ->Set(v8_str("a"), v8_str("a"));
15123 // Add more than 8 (see kMaxFastProperties) properties
15124 // so that the constructor will force copying map.
15125 // Cannot sprintf, gcc complains unsafety.
15126 char buf[4];
15127 for (char i = '0'; i <= '9' ; i++) {
15128 buf[0] = i;
15129 for (char j = '0'; j <= '9'; j++) {
15130 buf[1] = j;
15131 for (char k = '0'; k <= '9'; k++) {
15132 buf[2] = k;
15133 buf[3] = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015134 templ->Set(v8_str(buf), v8::Number::New(isolate, k));
Steve Blocka7e24c12009-10-30 11:49:00 +000015135 }
15136 }
15137 }
15138
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015139 Local<v8::Object> instance_1 =
15140 templ->NewInstance(context.local()).ToLocalChecked();
15141 CHECK(context->Global()
15142 ->Set(context.local(), v8_str("obj_1"), instance_1)
15143 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015144
15145 Local<Value> value_1 = CompileRun("obj_1.a");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015146 CHECK(value_1.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000015147
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015148 Local<v8::Object> instance_2 =
15149 templ->NewInstance(context.local()).ToLocalChecked();
15150 CHECK(context->Global()
15151 ->Set(context.local(), v8_str("obj_2"), instance_2)
15152 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015153
15154 Local<Value> value_2 = CompileRun("obj_2.a");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015155 CHECK(value_2.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000015156}
15157
15158
Leon Clarkef7060e22010-06-03 12:02:55 +010015159// Tests that ScriptData can be serialized and deserialized.
15160TEST(PreCompileSerialization) {
15161 v8::V8::Initialize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015162 LocalContext env;
15163 v8::Isolate* isolate = env->GetIsolate();
15164 HandleScope handle_scope(isolate);
Leon Clarkef7060e22010-06-03 12:02:55 +010015165
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015166 i::FLAG_min_preparse_length = 0;
15167 const char* script = "function foo(a) { return a+1; }";
15168 v8::ScriptCompiler::Source source(v8_str(script));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015169 v8::ScriptCompiler::Compile(env.local(), &source,
15170 v8::ScriptCompiler::kProduceParserCache)
15171 .ToLocalChecked();
Leon Clarkef7060e22010-06-03 12:02:55 +010015172 // Serialize.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015173 const v8::ScriptCompiler::CachedData* cd = source.GetCachedData();
15174 i::byte* serialized_data = i::NewArray<i::byte>(cd->length);
15175 i::MemCopy(serialized_data, cd->data, cd->length);
Leon Clarkef7060e22010-06-03 12:02:55 +010015176
15177 // Deserialize.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015178 i::ScriptData* deserialized = new i::ScriptData(serialized_data, cd->length);
Leon Clarkef7060e22010-06-03 12:02:55 +010015179
15180 // Verify that the original is the same as the deserialized.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015181 CHECK_EQ(cd->length, deserialized->length());
15182 CHECK_EQ(0, memcmp(cd->data, deserialized->data(), cd->length));
Leon Clarkef7060e22010-06-03 12:02:55 +010015183
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015184 delete deserialized;
15185 i::DeleteArray(serialized_data);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010015186}
15187
15188
Steve Blocka7e24c12009-10-30 11:49:00 +000015189// This tests that we do not allow dictionary load/call inline caches
15190// to use functions that have not yet been compiled. The potential
15191// problem of loading a function that has not yet been compiled can
15192// arise because we share code between contexts via the compilation
15193// cache.
15194THREADED_TEST(DictionaryICLoadedFunction) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015195 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000015196 // Test LoadIC.
15197 for (int i = 0; i < 2; i++) {
15198 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015199 CHECK(context->Global()
15200 ->Set(context.local(), v8_str("tmp"), v8::True(CcTest::isolate()))
15201 .FromJust());
15202 context->Global()->Delete(context.local(), v8_str("tmp")).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +000015203 CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
15204 }
15205 // Test CallIC.
15206 for (int i = 0; i < 2; i++) {
15207 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015208 CHECK(context->Global()
15209 ->Set(context.local(), v8_str("tmp"), v8::True(CcTest::isolate()))
15210 .FromJust());
15211 context->Global()->Delete(context.local(), v8_str("tmp")).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +000015212 CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
15213 }
15214}
15215
15216
15217// Test that cross-context new calls use the context of the callee to
15218// create the new JavaScript object.
15219THREADED_TEST(CrossContextNew) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015220 v8::Isolate* isolate = CcTest::isolate();
15221 v8::HandleScope scope(isolate);
15222 v8::Local<Context> context0 = Context::New(isolate);
15223 v8::Local<Context> context1 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000015224
15225 // Allow cross-domain access.
15226 Local<String> token = v8_str("<security token>");
15227 context0->SetSecurityToken(token);
15228 context1->SetSecurityToken(token);
15229
15230 // Set an 'x' property on the Object prototype and define a
15231 // constructor function in context0.
15232 context0->Enter();
15233 CompileRun("Object.prototype.x = 42; function C() {};");
15234 context0->Exit();
15235
15236 // Call the constructor function from context0 and check that the
15237 // result has the 'x' property.
15238 context1->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015239 CHECK(context1->Global()
15240 ->Set(context1, v8_str("other"), context0->Global())
15241 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015242 Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
15243 CHECK(value->IsInt32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015244 CHECK_EQ(42, value->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015245 context1->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +000015246}
15247
15248
15249// Verify that we can clone an object
15250TEST(ObjectClone) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015251 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015252 v8::Isolate* isolate = env->GetIsolate();
15253 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000015254
15255 const char* sample =
15256 "var rv = {};" \
15257 "rv.alpha = 'hello';" \
15258 "rv.beta = 123;" \
15259 "rv;";
15260
15261 // Create an object, verify basics.
15262 Local<Value> val = CompileRun(sample);
15263 CHECK(val->IsObject());
Steve Block6ded16b2010-05-10 14:33:55 +010015264 Local<v8::Object> obj = val.As<v8::Object>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015265 obj->Set(env.local(), v8_str("gamma"), v8_str("cloneme")).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +000015266
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015267 CHECK(v8_str("hello")
15268 ->Equals(env.local(),
15269 obj->Get(env.local(), v8_str("alpha")).ToLocalChecked())
15270 .FromJust());
15271 CHECK(v8::Integer::New(isolate, 123)
15272 ->Equals(env.local(),
15273 obj->Get(env.local(), v8_str("beta")).ToLocalChecked())
15274 .FromJust());
15275 CHECK(v8_str("cloneme")
15276 ->Equals(env.local(),
15277 obj->Get(env.local(), v8_str("gamma")).ToLocalChecked())
15278 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015279
15280 // Clone it.
15281 Local<v8::Object> clone = obj->Clone();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015282 CHECK(v8_str("hello")
15283 ->Equals(env.local(),
15284 clone->Get(env.local(), v8_str("alpha")).ToLocalChecked())
15285 .FromJust());
15286 CHECK(v8::Integer::New(isolate, 123)
15287 ->Equals(env.local(),
15288 clone->Get(env.local(), v8_str("beta")).ToLocalChecked())
15289 .FromJust());
15290 CHECK(v8_str("cloneme")
15291 ->Equals(env.local(),
15292 clone->Get(env.local(), v8_str("gamma")).ToLocalChecked())
15293 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015294
15295 // Set a property on the clone, verify each object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015296 CHECK(clone->Set(env.local(), v8_str("beta"), v8::Integer::New(isolate, 456))
15297 .FromJust());
15298 CHECK(v8::Integer::New(isolate, 123)
15299 ->Equals(env.local(),
15300 obj->Get(env.local(), v8_str("beta")).ToLocalChecked())
15301 .FromJust());
15302 CHECK(v8::Integer::New(isolate, 456)
15303 ->Equals(env.local(),
15304 clone->Get(env.local(), v8_str("beta")).ToLocalChecked())
15305 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015306}
15307
15308
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015309class OneByteVectorResource : public v8::String::ExternalOneByteStringResource {
Steve Blocka7e24c12009-10-30 11:49:00 +000015310 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015311 explicit OneByteVectorResource(i::Vector<const char> vector)
Steve Blocka7e24c12009-10-30 11:49:00 +000015312 : data_(vector) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015313 virtual ~OneByteVectorResource() {}
Steve Blocka7e24c12009-10-30 11:49:00 +000015314 virtual size_t length() const { return data_.length(); }
15315 virtual const char* data() const { return data_.start(); }
15316 private:
15317 i::Vector<const char> data_;
15318};
15319
15320
15321class UC16VectorResource : public v8::String::ExternalStringResource {
15322 public:
15323 explicit UC16VectorResource(i::Vector<const i::uc16> vector)
15324 : data_(vector) {}
15325 virtual ~UC16VectorResource() {}
15326 virtual size_t length() const { return data_.length(); }
15327 virtual const i::uc16* data() const { return data_.start(); }
15328 private:
15329 i::Vector<const i::uc16> data_;
15330};
15331
15332
15333static void MorphAString(i::String* string,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015334 OneByteVectorResource* one_byte_resource,
Steve Blocka7e24c12009-10-30 11:49:00 +000015335 UC16VectorResource* uc16_resource) {
15336 CHECK(i::StringShape(string).IsExternal());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015337 if (string->IsOneByteRepresentation()) {
15338 // Check old map is not internalized or long.
15339 CHECK(string->map() == CcTest::heap()->external_one_byte_string_map());
Steve Blocka7e24c12009-10-30 11:49:00 +000015340 // Morph external string to be TwoByte string.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015341 string->set_map(CcTest::heap()->external_string_map());
Steve Blocka7e24c12009-10-30 11:49:00 +000015342 i::ExternalTwoByteString* morphed =
15343 i::ExternalTwoByteString::cast(string);
15344 morphed->set_resource(uc16_resource);
15345 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015346 // Check old map is not internalized or long.
15347 CHECK(string->map() == CcTest::heap()->external_string_map());
15348 // Morph external string to be one-byte string.
15349 string->set_map(CcTest::heap()->external_one_byte_string_map());
15350 i::ExternalOneByteString* morphed = i::ExternalOneByteString::cast(string);
15351 morphed->set_resource(one_byte_resource);
Steve Blocka7e24c12009-10-30 11:49:00 +000015352 }
15353}
15354
15355
15356// Test that we can still flatten a string if the components it is built up
15357// from have been turned into 16 bit strings in the mean time.
15358THREADED_TEST(MorphCompositeStringTest) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010015359 char utf_buffer[129];
Steve Blocka7e24c12009-10-30 11:49:00 +000015360 const char* c_string = "Now is the time for all good men"
15361 " to come to the aid of the party";
15362 uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
15363 {
Steve Blocka7e24c12009-10-30 11:49:00 +000015364 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015365 i::Factory* factory = CcTest::i_isolate()->factory();
15366 v8::HandleScope scope(env->GetIsolate());
15367 OneByteVectorResource one_byte_resource(
Steve Blockd0582a62009-12-15 09:54:21 +000015368 i::Vector<const char>(c_string, i::StrLength(c_string)));
Steve Blocka7e24c12009-10-30 11:49:00 +000015369 UC16VectorResource uc16_resource(
Steve Blockd0582a62009-12-15 09:54:21 +000015370 i::Vector<const uint16_t>(two_byte_string,
15371 i::StrLength(c_string)));
Steve Blocka7e24c12009-10-30 11:49:00 +000015372
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015373 Local<String> lhs(
15374 v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
15375 &one_byte_resource).ToHandleChecked()));
15376 Local<String> rhs(
15377 v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
15378 &one_byte_resource).ToHandleChecked()));
Steve Blocka7e24c12009-10-30 11:49:00 +000015379
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015380 CHECK(env->Global()->Set(env.local(), v8_str("lhs"), lhs).FromJust());
15381 CHECK(env->Global()->Set(env.local(), v8_str("rhs"), rhs).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015382
15383 CompileRun(
15384 "var cons = lhs + rhs;"
15385 "var slice = lhs.substring(1, lhs.length - 1);"
15386 "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
15387
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015388 CHECK(lhs->IsOneByte());
15389 CHECK(rhs->IsOneByte());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010015390
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015391 MorphAString(*v8::Utils::OpenHandle(*lhs), &one_byte_resource,
15392 &uc16_resource);
15393 MorphAString(*v8::Utils::OpenHandle(*rhs), &one_byte_resource,
15394 &uc16_resource);
Steve Blocka7e24c12009-10-30 11:49:00 +000015395
Ben Murdoch3ef787d2012-04-12 10:51:47 +010015396 // This should UTF-8 without flattening, since everything is ASCII.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015397 Local<String> cons =
15398 v8_compile("cons")->Run(env.local()).ToLocalChecked().As<String>();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010015399 CHECK_EQ(128, cons->Utf8Length());
15400 int nchars = -1;
15401 CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
15402 CHECK_EQ(128, nchars);
15403 CHECK_EQ(0, strcmp(
15404 utf_buffer,
15405 "Now is the time for all good men to come to the aid of the party"
15406 "Now is the time for all good men to come to the aid of the party"));
15407
Steve Blocka7e24c12009-10-30 11:49:00 +000015408 // Now do some stuff to make sure the strings are flattened, etc.
15409 CompileRun(
15410 "/[^a-z]/.test(cons);"
15411 "/[^a-z]/.test(slice);"
15412 "/[^a-z]/.test(slice_on_cons);");
15413 const char* expected_cons =
15414 "Now is the time for all good men to come to the aid of the party"
15415 "Now is the time for all good men to come to the aid of the party";
15416 const char* expected_slice =
15417 "ow is the time for all good men to come to the aid of the part";
15418 const char* expected_slice_on_cons =
15419 "ow is the time for all good men to come to the aid of the party"
15420 "Now is the time for all good men to come to the aid of the part";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015421 CHECK(v8_str(expected_cons)
15422 ->Equals(env.local(), env->Global()
15423 ->Get(env.local(), v8_str("cons"))
15424 .ToLocalChecked())
15425 .FromJust());
15426 CHECK(v8_str(expected_slice)
15427 ->Equals(env.local(), env->Global()
15428 ->Get(env.local(), v8_str("slice"))
15429 .ToLocalChecked())
15430 .FromJust());
15431 CHECK(v8_str(expected_slice_on_cons)
15432 ->Equals(env.local(),
15433 env->Global()
15434 ->Get(env.local(), v8_str("slice_on_cons"))
15435 .ToLocalChecked())
15436 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015437 }
Ben Murdoch3bec4d22010-07-22 14:51:16 +010015438 i::DeleteArray(two_byte_string);
Steve Blocka7e24c12009-10-30 11:49:00 +000015439}
15440
15441
15442TEST(CompileExternalTwoByteSource) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015443 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015444 v8::HandleScope scope(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000015445
15446 // This is a very short list of sources, which currently is to check for a
15447 // regression caused by r2703.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015448 const char* one_byte_sources[] = {
15449 "0.5",
15450 "-0.5", // This mainly testes PushBack in the Scanner.
15451 "--0.5", // This mainly testes PushBack in the Scanner.
15452 NULL};
Steve Blocka7e24c12009-10-30 11:49:00 +000015453
15454 // Compile the sources as external two byte strings.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015455 for (int i = 0; one_byte_sources[i] != NULL; i++) {
15456 uint16_t* two_byte_string = AsciiToTwoByteString(one_byte_sources[i]);
15457 TestResource* uc16_resource = new TestResource(two_byte_string);
15458 v8::Local<v8::String> source =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015459 v8::String::NewExternalTwoByte(context->GetIsolate(), uc16_resource)
15460 .ToLocalChecked();
15461 v8::Script::Compile(context.local(), source).FromMaybe(Local<Script>());
Steve Blocka7e24c12009-10-30 11:49:00 +000015462 }
15463}
15464
15465
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015466#ifndef V8_INTERPRETED_REGEXP
15467
15468struct RegExpInterruptionData {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015469 v8::base::Atomic32 loop_count;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015470 UC16VectorResource* string_resource;
15471 v8::Persistent<v8::String> string;
15472} regexp_interruption_data;
15473
15474
15475class RegExpInterruptionThread : public v8::base::Thread {
Steve Blocka7e24c12009-10-30 11:49:00 +000015476 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015477 explicit RegExpInterruptionThread(v8::Isolate* isolate)
15478 : Thread(Options("TimeoutThread")), isolate_(isolate) {}
Steve Blocka7e24c12009-10-30 11:49:00 +000015479
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015480 virtual void Run() {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015481 for (v8::base::NoBarrier_Store(&regexp_interruption_data.loop_count, 0);
15482 v8::base::NoBarrier_Load(&regexp_interruption_data.loop_count) < 7;
15483 v8::base::NoBarrier_AtomicIncrement(
15484 &regexp_interruption_data.loop_count, 1)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015485 // Wait a bit before requesting GC.
15486 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015487 reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
Steve Blocka7e24c12009-10-30 11:49:00 +000015488 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015489 // Wait a bit before terminating.
15490 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
15491 isolate_->TerminateExecution();
Steve Blocka7e24c12009-10-30 11:49:00 +000015492 }
Steve Blocka7e24c12009-10-30 11:49:00 +000015493
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000015494 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015495 v8::Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +000015496};
15497
15498
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015499void RunBeforeGC(v8::Isolate* isolate, v8::GCType type,
15500 v8::GCCallbackFlags flags) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015501 if (v8::base::NoBarrier_Load(&regexp_interruption_data.loop_count) != 2) {
15502 return;
15503 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015504 v8::HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015505 v8::Local<v8::String> string = v8::Local<v8::String>::New(
15506 CcTest::isolate(), regexp_interruption_data.string);
15507 string->MakeExternal(regexp_interruption_data.string_resource);
Steve Blocka7e24c12009-10-30 11:49:00 +000015508}
15509
15510
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015511// Test that RegExp execution can be interrupted. Specifically, we test
15512// * interrupting with GC
15513// * turn the subject string from one-byte internal to two-byte external string
15514// * force termination
15515TEST(RegExpInterruption) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015516 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015517 v8::HandleScope scope(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015518
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015519 RegExpInterruptionThread timeout_thread(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015520
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015521 env->GetIsolate()->AddGCPrologueCallback(RunBeforeGC);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015522 static const char* one_byte_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
15523 i::uc16* uc16_content = AsciiToTwoByteString(one_byte_content);
15524 v8::Local<v8::String> string = v8_str(one_byte_content);
15525
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015526 env->Global()->Set(env.local(), v8_str("a"), string).FromJust();
15527 regexp_interruption_data.string.Reset(env->GetIsolate(), string);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015528 regexp_interruption_data.string_resource = new UC16VectorResource(
15529 i::Vector<const i::uc16>(uc16_content, i::StrLength(one_byte_content)));
15530
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015531 v8::TryCatch try_catch(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015532 timeout_thread.Start();
15533
15534 CompileRun("/((a*)*)*b/.exec(a)");
15535 CHECK(try_catch.HasTerminated());
15536
15537 timeout_thread.Join();
15538
15539 regexp_interruption_data.string.Reset();
15540 i::DeleteArray(uc16_content);
15541}
15542
15543#endif // V8_INTERPRETED_REGEXP
15544
15545
15546// Test that we cannot set a property on the global object if there
Steve Blocka7e24c12009-10-30 11:49:00 +000015547// is a read-only property in the prototype chain.
15548TEST(ReadOnlyPropertyInGlobalProto) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015549 v8::Isolate* isolate = CcTest::isolate();
15550 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015551 v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000015552 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015553 v8::Local<v8::Object> global = context->Global();
15554 v8::Local<v8::Object> global_proto = v8::Local<v8::Object>::Cast(
15555 global->Get(context.local(), v8_str("__proto__")).ToLocalChecked());
15556 global_proto->DefineOwnProperty(context.local(), v8_str("x"),
15557 v8::Integer::New(isolate, 0), v8::ReadOnly)
15558 .FromJust();
15559 global_proto->DefineOwnProperty(context.local(), v8_str("y"),
15560 v8::Integer::New(isolate, 0), v8::ReadOnly)
15561 .FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +000015562 // Check without 'eval' or 'with'.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015563 v8::Local<v8::Value> res =
Steve Blocka7e24c12009-10-30 11:49:00 +000015564 CompileRun("function f() { x = 42; return x; }; f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015565 CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015566 // Check with 'eval'.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015567 res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015568 CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015569 // Check with 'with'.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015570 res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015571 CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015572}
15573
Steve Blocka7e24c12009-10-30 11:49:00 +000015574
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015575TEST(CreateDataProperty) {
15576 LocalContext env;
15577 v8::Isolate* isolate = env->GetIsolate();
15578 v8::HandleScope handle_scope(isolate);
15579
15580 CompileRun(
15581 "var a = {};"
15582 "var b = [];"
15583 "Object.defineProperty(a, 'foo', {value: 23});"
15584 "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
15585
15586 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
15587 env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
15588 v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(
15589 env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
15590 {
15591 // Can't change a non-configurable properties.
15592 v8::TryCatch try_catch(isolate);
15593 CHECK(!obj->CreateDataProperty(env.local(), v8_str("foo"),
15594 v8::Integer::New(isolate, 42)).FromJust());
15595 CHECK(!try_catch.HasCaught());
15596 CHECK(obj->CreateDataProperty(env.local(), v8_str("bar"),
15597 v8::Integer::New(isolate, 42)).FromJust());
15598 CHECK(!try_catch.HasCaught());
15599 v8::Local<v8::Value> val =
15600 obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
15601 CHECK(val->IsNumber());
15602 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015603 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015604
15605 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015606 // Set a regular property.
15607 v8::TryCatch try_catch(isolate);
15608 CHECK(obj->CreateDataProperty(env.local(), v8_str("blub"),
15609 v8::Integer::New(isolate, 42)).FromJust());
15610 CHECK(!try_catch.HasCaught());
15611 v8::Local<v8::Value> val =
15612 obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
15613 CHECK(val->IsNumber());
15614 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15615 }
15616
15617 {
15618 // Set an indexed property.
15619 v8::TryCatch try_catch(isolate);
15620 CHECK(obj->CreateDataProperty(env.local(), v8_str("1"),
15621 v8::Integer::New(isolate, 42)).FromJust());
15622 CHECK(!try_catch.HasCaught());
15623 v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
15624 CHECK(val->IsNumber());
15625 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15626 }
15627
15628 {
15629 // Special cases for arrays.
15630 v8::TryCatch try_catch(isolate);
15631 CHECK(!arr->CreateDataProperty(env.local(), v8_str("length"),
15632 v8::Integer::New(isolate, 1)).FromJust());
15633 CHECK(!try_catch.HasCaught());
15634 }
15635 {
15636 // Special cases for arrays: index exceeds the array's length
15637 v8::TryCatch try_catch(isolate);
15638 CHECK(arr->CreateDataProperty(env.local(), 1, v8::Integer::New(isolate, 23))
15639 .FromJust());
15640 CHECK(!try_catch.HasCaught());
15641 CHECK_EQ(2U, arr->Length());
15642 v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
15643 CHECK(val->IsNumber());
15644 CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
15645
15646 // Set an existing entry.
15647 CHECK(arr->CreateDataProperty(env.local(), 0, v8::Integer::New(isolate, 42))
15648 .FromJust());
15649 CHECK(!try_catch.HasCaught());
15650 val = arr->Get(env.local(), 0).ToLocalChecked();
15651 CHECK(val->IsNumber());
15652 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15653 }
15654
15655 CompileRun("Object.freeze(a);");
15656 {
15657 // Can't change non-extensible objects.
15658 v8::TryCatch try_catch(isolate);
15659 CHECK(!obj->CreateDataProperty(env.local(), v8_str("baz"),
15660 v8::Integer::New(isolate, 42)).FromJust());
15661 CHECK(!try_catch.HasCaught());
15662 }
15663
15664 v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
15665 templ->SetAccessCheckCallback(AccessAlwaysBlocked);
15666 v8::Local<v8::Object> access_checked =
15667 templ->NewInstance(env.local()).ToLocalChecked();
15668 {
15669 v8::TryCatch try_catch(isolate);
15670 CHECK(access_checked->CreateDataProperty(env.local(), v8_str("foo"),
15671 v8::Integer::New(isolate, 42))
15672 .IsNothing());
15673 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015674 }
15675}
15676
15677
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015678TEST(DefineOwnProperty) {
15679 LocalContext env;
15680 v8::Isolate* isolate = env->GetIsolate();
15681 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000015682
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015683 CompileRun(
15684 "var a = {};"
15685 "var b = [];"
15686 "Object.defineProperty(a, 'foo', {value: 23});"
15687 "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
Steve Blocka7e24c12009-10-30 11:49:00 +000015688
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015689 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
15690 env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
15691 v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(
15692 env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
15693 {
15694 // Can't change a non-configurable properties.
15695 v8::TryCatch try_catch(isolate);
15696 CHECK(!obj->DefineOwnProperty(env.local(), v8_str("foo"),
15697 v8::Integer::New(isolate, 42)).FromJust());
15698 CHECK(!try_catch.HasCaught());
15699 CHECK(obj->DefineOwnProperty(env.local(), v8_str("bar"),
15700 v8::Integer::New(isolate, 42)).FromJust());
15701 CHECK(!try_catch.HasCaught());
15702 v8::Local<v8::Value> val =
15703 obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
15704 CHECK(val->IsNumber());
15705 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15706 }
15707
15708 {
15709 // Set a regular property.
15710 v8::TryCatch try_catch(isolate);
15711 CHECK(obj->DefineOwnProperty(env.local(), v8_str("blub"),
15712 v8::Integer::New(isolate, 42)).FromJust());
15713 CHECK(!try_catch.HasCaught());
15714 v8::Local<v8::Value> val =
15715 obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
15716 CHECK(val->IsNumber());
15717 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15718 }
15719
15720 {
15721 // Set an indexed property.
15722 v8::TryCatch try_catch(isolate);
15723 CHECK(obj->DefineOwnProperty(env.local(), v8_str("1"),
15724 v8::Integer::New(isolate, 42)).FromJust());
15725 CHECK(!try_catch.HasCaught());
15726 v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
15727 CHECK(val->IsNumber());
15728 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15729 }
15730
15731 {
15732 // Special cases for arrays.
15733 v8::TryCatch try_catch(isolate);
15734 CHECK(!arr->DefineOwnProperty(env.local(), v8_str("length"),
15735 v8::Integer::New(isolate, 1)).FromJust());
15736 CHECK(!try_catch.HasCaught());
15737 }
15738 {
15739 // Special cases for arrays: index exceeds the array's length
15740 v8::TryCatch try_catch(isolate);
15741 CHECK(arr->DefineOwnProperty(env.local(), v8_str("1"),
15742 v8::Integer::New(isolate, 23)).FromJust());
15743 CHECK(!try_catch.HasCaught());
15744 CHECK_EQ(2U, arr->Length());
15745 v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
15746 CHECK(val->IsNumber());
15747 CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
15748
15749 // Set an existing entry.
15750 CHECK(arr->DefineOwnProperty(env.local(), v8_str("0"),
15751 v8::Integer::New(isolate, 42)).FromJust());
15752 CHECK(!try_catch.HasCaught());
15753 val = arr->Get(env.local(), 0).ToLocalChecked();
15754 CHECK(val->IsNumber());
15755 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15756 }
15757
15758 {
15759 // Set a non-writable property.
15760 v8::TryCatch try_catch(isolate);
15761 CHECK(obj->DefineOwnProperty(env.local(), v8_str("lala"),
15762 v8::Integer::New(isolate, 42),
15763 v8::ReadOnly).FromJust());
15764 CHECK(!try_catch.HasCaught());
15765 v8::Local<v8::Value> val =
15766 obj->Get(env.local(), v8_str("lala")).ToLocalChecked();
15767 CHECK(val->IsNumber());
15768 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15769 CHECK_EQ(v8::ReadOnly, obj->GetPropertyAttributes(
15770 env.local(), v8_str("lala")).FromJust());
15771 CHECK(!try_catch.HasCaught());
15772 }
15773
15774 CompileRun("Object.freeze(a);");
15775 {
15776 // Can't change non-extensible objects.
15777 v8::TryCatch try_catch(isolate);
15778 CHECK(!obj->DefineOwnProperty(env.local(), v8_str("baz"),
15779 v8::Integer::New(isolate, 42)).FromJust());
15780 CHECK(!try_catch.HasCaught());
15781 }
15782
15783 v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
15784 templ->SetAccessCheckCallback(AccessAlwaysBlocked);
15785 v8::Local<v8::Object> access_checked =
15786 templ->NewInstance(env.local()).ToLocalChecked();
15787 {
15788 v8::TryCatch try_catch(isolate);
15789 CHECK(access_checked->DefineOwnProperty(env.local(), v8_str("foo"),
15790 v8::Integer::New(isolate, 42))
15791 .IsNothing());
15792 CHECK(try_catch.HasCaught());
15793 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015794}
15795
15796
15797THREADED_TEST(GetCurrentContextWhenNotInContext) {
15798 i::Isolate* isolate = CcTest::i_isolate();
15799 CHECK(isolate != NULL);
15800 CHECK(isolate->context() == NULL);
15801 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
15802 v8::HandleScope scope(v8_isolate);
15803 // The following should not crash, but return an empty handle.
15804 v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
15805 CHECK(current.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000015806}
15807
15808
Steve Blocka7e24c12009-10-30 11:49:00 +000015809// Check that a variable declaration with no explicit initialization
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015810// value does shadow an existing property in the prototype chain.
Steve Blocka7e24c12009-10-30 11:49:00 +000015811THREADED_TEST(InitGlobalVarInProtoChain) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015812 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015813 v8::HandleScope scope(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000015814 // Introduce a variable in the prototype chain.
15815 CompileRun("__proto__.x = 42");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015816 v8::Local<v8::Value> result = CompileRun("var x = 43; x");
Steve Blocka7e24c12009-10-30 11:49:00 +000015817 CHECK(!result->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015818 CHECK_EQ(43, result->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015819}
15820
15821
15822// Regression test for issue 398.
15823// If a function is added to an object, creating a constant function
15824// field, and the result is cloned, replacing the constant function on the
15825// original should not affect the clone.
15826// See http://code.google.com/p/v8/issues/detail?id=398
15827THREADED_TEST(ReplaceConstantFunction) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015828 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015829 v8::Isolate* isolate = context->GetIsolate();
15830 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015831 v8::Local<v8::Object> obj = v8::Object::New(isolate);
15832 v8::Local<v8::FunctionTemplate> func_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015833 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015834 v8::Local<v8::String> foo_string = v8_str("foo");
15835 obj->Set(context.local(), foo_string,
15836 func_templ->GetFunction(context.local()).ToLocalChecked())
15837 .FromJust();
15838 v8::Local<v8::Object> obj_clone = obj->Clone();
15839 obj_clone->Set(context.local(), foo_string, v8_str("Hello")).FromJust();
15840 CHECK(!obj->Get(context.local(), foo_string).ToLocalChecked()->IsUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +000015841}
15842
15843
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015844static void CheckElementValue(i::Isolate* isolate,
15845 int expected,
15846 i::Handle<i::Object> obj,
15847 int offset) {
15848 i::Object* element =
15849 *i::Object::GetElement(isolate, obj, offset).ToHandleChecked();
15850 CHECK_EQ(expected, i::Smi::cast(element)->value());
Steve Blocka7e24c12009-10-30 11:49:00 +000015851}
15852
15853
Steve Block3ce2e202009-11-05 08:53:23 +000015854template <class ExternalArrayClass, class ElementType>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015855static void ObjectWithExternalArrayTestHelper(Local<Context> context,
15856 v8::Local<Object> obj,
15857 int element_count,
15858 i::ExternalArrayType array_type,
15859 int64_t low, int64_t high) {
15860 i::Handle<i::JSReceiver> jsobj = v8::Utils::OpenHandle(*obj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015861 i::Isolate* isolate = jsobj->GetIsolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015862 obj->Set(context, v8_str("field"),
15863 v8::Int32::New(reinterpret_cast<v8::Isolate*>(isolate), 1503))
15864 .FromJust();
15865 CHECK(context->Global()->Set(context, v8_str("ext_array"), obj).FromJust());
15866 v8::Local<v8::Value> result = CompileRun("ext_array.field");
15867 CHECK_EQ(1503, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015868 result = CompileRun("ext_array[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015869 CHECK_EQ(1, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015870
Steve Block3ce2e202009-11-05 08:53:23 +000015871 // Check assigned smis
15872 result = CompileRun("for (var i = 0; i < 8; i++) {"
15873 " ext_array[i] = i;"
15874 "}"
15875 "var sum = 0;"
15876 "for (var i = 0; i < 8; i++) {"
15877 " sum += ext_array[i];"
15878 "}"
15879 "sum;");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015880
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015881 CHECK_EQ(28, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015882 // Check pass through of assigned smis
15883 result = CompileRun("var sum = 0;"
15884 "for (var i = 0; i < 8; i++) {"
15885 " sum += ext_array[i] = ext_array[i] = -i;"
15886 "}"
15887 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015888 CHECK_EQ(-28, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015889
Steve Block3ce2e202009-11-05 08:53:23 +000015890
15891 // Check assigned smis in reverse order
15892 result = CompileRun("for (var i = 8; --i >= 0; ) {"
15893 " ext_array[i] = i;"
15894 "}"
15895 "var sum = 0;"
15896 "for (var i = 0; i < 8; i++) {"
15897 " sum += ext_array[i];"
15898 "}"
15899 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015900 CHECK_EQ(28, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015901
15902 // Check pass through of assigned HeapNumbers
15903 result = CompileRun("var sum = 0;"
15904 "for (var i = 0; i < 16; i+=2) {"
15905 " sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
15906 "}"
15907 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015908 CHECK_EQ(-28, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015909
15910 // Check assigned HeapNumbers
15911 result = CompileRun("for (var i = 0; i < 16; i+=2) {"
15912 " ext_array[i] = (i * 0.5);"
15913 "}"
15914 "var sum = 0;"
15915 "for (var i = 0; i < 16; i+=2) {"
15916 " sum += ext_array[i];"
15917 "}"
15918 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015919 CHECK_EQ(28, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015920
15921 // Check assigned HeapNumbers in reverse order
15922 result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
15923 " ext_array[i] = (i * 0.5);"
15924 "}"
15925 "var sum = 0;"
15926 "for (var i = 0; i < 16; i+=2) {"
15927 " sum += ext_array[i];"
15928 "}"
15929 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015930 CHECK_EQ(28, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015931
15932 i::ScopedVector<char> test_buf(1024);
15933
15934 // Check legal boundary conditions.
15935 // The repeated loads and stores ensure the ICs are exercised.
15936 const char* boundary_program =
15937 "var res = 0;"
15938 "for (var i = 0; i < 16; i++) {"
15939 " ext_array[i] = %lld;"
15940 " if (i > 8) {"
15941 " res = ext_array[i];"
15942 " }"
15943 "}"
15944 "res;";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015945 i::SNPrintF(test_buf,
15946 boundary_program,
15947 low);
Steve Block3ce2e202009-11-05 08:53:23 +000015948 result = CompileRun(test_buf.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015949 CHECK_EQ(low, result->IntegerValue(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015950
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015951 i::SNPrintF(test_buf,
15952 boundary_program,
15953 high);
Steve Block3ce2e202009-11-05 08:53:23 +000015954 result = CompileRun(test_buf.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015955 CHECK_EQ(high, result->IntegerValue(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015956
15957 // Check misprediction of type in IC.
15958 result = CompileRun("var tmp_array = ext_array;"
15959 "var sum = 0;"
15960 "for (var i = 0; i < 8; i++) {"
15961 " tmp_array[i] = i;"
15962 " sum += tmp_array[i];"
15963 " if (i == 4) {"
15964 " tmp_array = {};"
15965 " }"
15966 "}"
15967 "sum;");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010015968 // Force GC to trigger verification.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015969 CcTest::heap()->CollectAllGarbage();
15970 CHECK_EQ(28, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015971
15972 // Make sure out-of-range loads do not throw.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015973 i::SNPrintF(test_buf,
15974 "var caught_exception = false;"
15975 "try {"
15976 " ext_array[%d];"
15977 "} catch (e) {"
15978 " caught_exception = true;"
15979 "}"
15980 "caught_exception;",
15981 element_count);
Steve Block3ce2e202009-11-05 08:53:23 +000015982 result = CompileRun(test_buf.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015983 CHECK_EQ(false, result->BooleanValue(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015984
15985 // Make sure out-of-range stores do not throw.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015986 i::SNPrintF(test_buf,
15987 "var caught_exception = false;"
15988 "try {"
15989 " ext_array[%d] = 1;"
15990 "} catch (e) {"
15991 " caught_exception = true;"
15992 "}"
15993 "caught_exception;",
15994 element_count);
Steve Block3ce2e202009-11-05 08:53:23 +000015995 result = CompileRun(test_buf.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015996 CHECK_EQ(false, result->BooleanValue(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015997
15998 // Check other boundary conditions, values and operations.
15999 result = CompileRun("for (var i = 0; i < 8; i++) {"
16000 " ext_array[7] = undefined;"
16001 "}"
16002 "ext_array[7];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016003 CHECK_EQ(0, result->Int32Value(context).FromJust());
16004 if (array_type == i::kExternalFloat64Array ||
16005 array_type == i::kExternalFloat32Array) {
16006 CHECK(std::isnan(
16007 i::Object::GetElement(isolate, jsobj, 7).ToHandleChecked()->Number()));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016008 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016009 CheckElementValue(isolate, 0, jsobj, 7);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016010 }
Steve Block3ce2e202009-11-05 08:53:23 +000016011
16012 result = CompileRun("for (var i = 0; i < 8; i++) {"
16013 " ext_array[6] = '2.3';"
16014 "}"
16015 "ext_array[6];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016016 CHECK_EQ(2, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016017 CHECK_EQ(2,
16018 static_cast<int>(
16019 i::Object::GetElement(
16020 isolate, jsobj, 6).ToHandleChecked()->Number()));
Steve Block3ce2e202009-11-05 08:53:23 +000016021
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016022 if (array_type != i::kExternalFloat32Array &&
16023 array_type != i::kExternalFloat64Array) {
Steve Block3ce2e202009-11-05 08:53:23 +000016024 // Though the specification doesn't state it, be explicit about
16025 // converting NaNs and +/-Infinity to zero.
16026 result = CompileRun("for (var i = 0; i < 8; i++) {"
16027 " ext_array[i] = 5;"
16028 "}"
16029 "for (var i = 0; i < 8; i++) {"
16030 " ext_array[i] = NaN;"
16031 "}"
16032 "ext_array[5];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016033 CHECK_EQ(0, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016034 CheckElementValue(isolate, 0, jsobj, 5);
Steve Block3ce2e202009-11-05 08:53:23 +000016035
16036 result = CompileRun("for (var i = 0; i < 8; i++) {"
16037 " ext_array[i] = 5;"
16038 "}"
16039 "for (var i = 0; i < 8; i++) {"
16040 " ext_array[i] = Infinity;"
16041 "}"
16042 "ext_array[5];");
Steve Block44f0eee2011-05-26 01:26:41 +010016043 int expected_value =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016044 (array_type == i::kExternalUint8ClampedArray) ? 255 : 0;
16045 CHECK_EQ(expected_value, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016046 CheckElementValue(isolate, expected_value, jsobj, 5);
Steve Block3ce2e202009-11-05 08:53:23 +000016047
16048 result = CompileRun("for (var i = 0; i < 8; i++) {"
16049 " ext_array[i] = 5;"
16050 "}"
16051 "for (var i = 0; i < 8; i++) {"
16052 " ext_array[i] = -Infinity;"
16053 "}"
16054 "ext_array[5];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016055 CHECK_EQ(0, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016056 CheckElementValue(isolate, 0, jsobj, 5);
Steve Block1e0659c2011-05-24 12:43:12 +010016057
16058 // Check truncation behavior of integral arrays.
16059 const char* unsigned_data =
16060 "var source_data = [0.6, 10.6];"
16061 "var expected_results = [0, 10];";
16062 const char* signed_data =
16063 "var source_data = [0.6, 10.6, -0.6, -10.6];"
16064 "var expected_results = [0, 10, 0, -10];";
Steve Block44f0eee2011-05-26 01:26:41 +010016065 const char* pixel_data =
16066 "var source_data = [0.6, 10.6];"
16067 "var expected_results = [1, 11];";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016068 bool is_unsigned = (array_type == i::kExternalUint8Array ||
16069 array_type == i::kExternalUint16Array ||
16070 array_type == i::kExternalUint32Array);
16071 bool is_pixel_data = array_type == i::kExternalUint8ClampedArray;
Steve Block1e0659c2011-05-24 12:43:12 +010016072
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016073 i::SNPrintF(test_buf,
16074 "%s"
16075 "var all_passed = true;"
16076 "for (var i = 0; i < source_data.length; i++) {"
16077 " for (var j = 0; j < 8; j++) {"
16078 " ext_array[j] = source_data[i];"
16079 " }"
16080 " all_passed = all_passed &&"
16081 " (ext_array[5] == expected_results[i]);"
16082 "}"
16083 "all_passed;",
16084 (is_unsigned ?
16085 unsigned_data :
16086 (is_pixel_data ? pixel_data : signed_data)));
Steve Block1e0659c2011-05-24 12:43:12 +010016087 result = CompileRun(test_buf.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016088 CHECK_EQ(true, result->BooleanValue(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016089 }
16090
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016091 i::Handle<ExternalArrayClass> array(ExternalArrayClass::cast(
16092 i::Handle<i::JSObject>::cast(jsobj)->elements()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016093 for (int i = 0; i < element_count; i++) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010016094 array->set(i, static_cast<ElementType>(i));
16095 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016096
Ben Murdoch8b112d22011-06-08 16:22:53 +010016097 // Test complex assignments
16098 result = CompileRun("function ee_op_test_complex_func(sum) {"
16099 " for (var i = 0; i < 40; ++i) {"
16100 " sum += (ext_array[i] += 1);"
16101 " sum += (ext_array[i] -= 1);"
16102 " } "
16103 " return sum;"
16104 "}"
16105 "sum=0;"
16106 "for (var i=0;i<10000;++i) {"
16107 " sum=ee_op_test_complex_func(sum);"
16108 "}"
16109 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016110 CHECK_EQ(16000000, result->Int32Value(context).FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010016111
16112 // Test count operations
16113 result = CompileRun("function ee_op_test_count_func(sum) {"
16114 " for (var i = 0; i < 40; ++i) {"
16115 " sum += (++ext_array[i]);"
16116 " sum += (--ext_array[i]);"
16117 " } "
16118 " return sum;"
16119 "}"
16120 "sum=0;"
16121 "for (var i=0;i<10000;++i) {"
16122 " sum=ee_op_test_count_func(sum);"
16123 "}"
16124 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016125 CHECK_EQ(16000000, result->Int32Value(context).FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010016126
Steve Block3ce2e202009-11-05 08:53:23 +000016127 result = CompileRun("ext_array[3] = 33;"
16128 "delete ext_array[3];"
16129 "ext_array[3];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016130 CHECK_EQ(33, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016131
16132 result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
16133 "ext_array[2] = 12; ext_array[3] = 13;"
16134 "ext_array.__defineGetter__('2',"
16135 "function() { return 120; });"
16136 "ext_array[2];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016137 CHECK_EQ(12, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016138
16139 result = CompileRun("var js_array = new Array(40);"
16140 "js_array[0] = 77;"
16141 "js_array;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016142 CHECK_EQ(77, v8::Object::Cast(*result)
16143 ->Get(context, v8_str("0"))
16144 .ToLocalChecked()
16145 ->Int32Value(context)
16146 .FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016147
16148 result = CompileRun("ext_array[1] = 23;"
16149 "ext_array.__proto__ = [];"
16150 "js_array.__proto__ = ext_array;"
16151 "js_array.concat(ext_array);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016152 CHECK_EQ(77, v8::Object::Cast(*result)
16153 ->Get(context, v8_str("0"))
16154 .ToLocalChecked()
16155 ->Int32Value(context)
16156 .FromJust());
16157 CHECK_EQ(23, v8::Object::Cast(*result)
16158 ->Get(context, v8_str("1"))
16159 .ToLocalChecked()
16160 ->Int32Value(context)
16161 .FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016162
16163 result = CompileRun("ext_array[1] = 23;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016164 CHECK_EQ(23, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016165}
16166
16167
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016168template <class FixedTypedArrayClass, i::ElementsKind elements_kind,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016169 class ElementType>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016170static void FixedTypedArrayTestHelper(i::ExternalArrayType array_type,
16171 ElementType low, ElementType high) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016172 i::FLAG_allow_natives_syntax = true;
16173 LocalContext context;
16174 i::Isolate* isolate = CcTest::i_isolate();
16175 i::Factory* factory = isolate->factory();
16176 v8::HandleScope scope(context->GetIsolate());
16177 const int kElementCount = 260;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016178 i::Handle<i::JSTypedArray> jsobj =
16179 factory->NewJSTypedArray(elements_kind, kElementCount);
16180 i::Handle<FixedTypedArrayClass> fixed_array(
16181 FixedTypedArrayClass::cast(jsobj->elements()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016182 CHECK_EQ(FixedTypedArrayClass::kInstanceType,
16183 fixed_array->map()->instance_type());
16184 CHECK_EQ(kElementCount, fixed_array->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016185 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016186 for (int i = 0; i < kElementCount; i++) {
16187 fixed_array->set(i, static_cast<ElementType>(i));
16188 }
16189 // Force GC to trigger verification.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016190 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016191 for (int i = 0; i < kElementCount; i++) {
16192 CHECK_EQ(static_cast<int64_t>(static_cast<ElementType>(i)),
16193 static_cast<int64_t>(fixed_array->get_scalar(i)));
16194 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016195 v8::Local<v8::Object> obj = v8::Utils::ToLocal(jsobj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016196
16197 ObjectWithExternalArrayTestHelper<FixedTypedArrayClass, ElementType>(
16198 context.local(), obj, kElementCount, array_type,
16199 static_cast<int64_t>(low),
16200 static_cast<int64_t>(high));
16201}
16202
16203
16204THREADED_TEST(FixedUint8Array) {
16205 FixedTypedArrayTestHelper<i::FixedUint8Array, i::UINT8_ELEMENTS, uint8_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016206 i::kExternalUint8Array, 0x0, 0xFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016207}
16208
16209
16210THREADED_TEST(FixedUint8ClampedArray) {
16211 FixedTypedArrayTestHelper<i::FixedUint8ClampedArray,
16212 i::UINT8_CLAMPED_ELEMENTS, uint8_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016213 i::kExternalUint8ClampedArray, 0x0, 0xFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016214}
16215
16216
16217THREADED_TEST(FixedInt8Array) {
16218 FixedTypedArrayTestHelper<i::FixedInt8Array, i::INT8_ELEMENTS, int8_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016219 i::kExternalInt8Array, -0x80, 0x7F);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016220}
16221
16222
16223THREADED_TEST(FixedUint16Array) {
16224 FixedTypedArrayTestHelper<i::FixedUint16Array, i::UINT16_ELEMENTS, uint16_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016225 i::kExternalUint16Array, 0x0, 0xFFFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016226}
16227
16228
16229THREADED_TEST(FixedInt16Array) {
16230 FixedTypedArrayTestHelper<i::FixedInt16Array, i::INT16_ELEMENTS, int16_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016231 i::kExternalInt16Array, -0x8000, 0x7FFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016232}
16233
16234
16235THREADED_TEST(FixedUint32Array) {
16236 FixedTypedArrayTestHelper<i::FixedUint32Array, i::UINT32_ELEMENTS, uint32_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016237 i::kExternalUint32Array, 0x0, UINT_MAX);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016238}
16239
16240
16241THREADED_TEST(FixedInt32Array) {
16242 FixedTypedArrayTestHelper<i::FixedInt32Array, i::INT32_ELEMENTS, int32_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016243 i::kExternalInt32Array, INT_MIN, INT_MAX);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016244}
16245
16246
16247THREADED_TEST(FixedFloat32Array) {
16248 FixedTypedArrayTestHelper<i::FixedFloat32Array, i::FLOAT32_ELEMENTS, float>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016249 i::kExternalFloat32Array, -500, 500);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016250}
16251
16252
16253THREADED_TEST(FixedFloat64Array) {
16254 FixedTypedArrayTestHelper<i::FixedFloat64Array, i::FLOAT64_ELEMENTS, float>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016255 i::kExternalFloat64Array, -500, 500);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016256}
16257
16258
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016259template <typename ElementType, typename TypedArray, class ExternalArrayClass,
16260 class ArrayBufferType>
16261void TypedArrayTestHelper(i::ExternalArrayType array_type, int64_t low,
16262 int64_t high) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016263 const int kElementCount = 50;
16264
16265 i::ScopedVector<ElementType> backing_store(kElementCount+2);
16266
16267 LocalContext env;
16268 v8::Isolate* isolate = env->GetIsolate();
16269 v8::HandleScope handle_scope(isolate);
16270
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016271 Local<ArrayBufferType> ab =
16272 ArrayBufferType::New(isolate, backing_store.start(),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016273 (kElementCount + 2) * sizeof(ElementType));
16274 Local<TypedArray> ta =
16275 TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
16276 CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
16277 CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016278 CHECK_EQ(2 * sizeof(ElementType), ta->ByteOffset());
16279 CHECK_EQ(kElementCount * sizeof(ElementType), ta->ByteLength());
16280 CHECK(ab->Equals(env.local(), ta->Buffer()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016281
16282 ElementType* data = backing_store.start() + 2;
16283 for (int i = 0; i < kElementCount; i++) {
16284 data[i] = static_cast<ElementType>(i);
16285 }
16286
16287 ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
16288 env.local(), ta, kElementCount, array_type, low, high);
16289}
16290
16291
16292THREADED_TEST(Uint8Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016293 TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
16294 v8::ArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016295}
16296
16297
16298THREADED_TEST(Int8Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016299 TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
16300 v8::ArrayBuffer>(i::kExternalInt8Array, -0x80, 0x7F);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016301}
16302
16303
16304THREADED_TEST(Uint16Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016305 TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
16306 v8::ArrayBuffer>(i::kExternalUint16Array, 0, 0xFFFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016307}
16308
16309
16310THREADED_TEST(Int16Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016311 TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
16312 v8::ArrayBuffer>(i::kExternalInt16Array, -0x8000,
16313 0x7FFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016314}
16315
16316
16317THREADED_TEST(Uint32Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016318 TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
16319 v8::ArrayBuffer>(i::kExternalUint32Array, 0, UINT_MAX);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016320}
16321
16322
16323THREADED_TEST(Int32Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016324 TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
16325 v8::ArrayBuffer>(i::kExternalInt32Array, INT_MIN,
16326 INT_MAX);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016327}
16328
16329
16330THREADED_TEST(Float32Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016331 TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
16332 v8::ArrayBuffer>(i::kExternalFloat32Array, -500, 500);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016333}
16334
16335
16336THREADED_TEST(Float64Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016337 TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
16338 v8::ArrayBuffer>(i::kExternalFloat64Array, -500, 500);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016339}
16340
16341
16342THREADED_TEST(Uint8ClampedArray) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016343 TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
16344 i::FixedUint8ClampedArray, v8::ArrayBuffer>(
16345 i::kExternalUint8ClampedArray, 0, 0xFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016346}
16347
16348
16349THREADED_TEST(DataView) {
16350 const int kSize = 50;
16351
16352 i::ScopedVector<uint8_t> backing_store(kSize+2);
16353
16354 LocalContext env;
16355 v8::Isolate* isolate = env->GetIsolate();
16356 v8::HandleScope handle_scope(isolate);
16357
16358 Local<v8::ArrayBuffer> ab =
16359 v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016360 Local<v8::DataView> dv = v8::DataView::New(ab, 2, kSize);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016361 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016362 CHECK_EQ(2u, dv->ByteOffset());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016363 CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016364 CHECK(ab->Equals(env.local(), dv->Buffer()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016365}
16366
16367
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016368THREADED_TEST(SkipArrayBufferBackingStoreDuringGC) {
16369 LocalContext env;
16370 v8::Isolate* isolate = env->GetIsolate();
16371 v8::HandleScope handle_scope(isolate);
16372
16373 // Make sure the pointer looks like a heap object
16374 uint8_t* store_ptr = reinterpret_cast<uint8_t*>(i::kHeapObjectTag);
16375
16376 // Create ArrayBuffer with pointer-that-cannot-be-visited in the backing store
16377 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, store_ptr, 8);
16378
16379 // Should not crash
16380 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
16381 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
16382 CcTest::heap()->CollectAllGarbage();
16383 CcTest::heap()->CollectAllGarbage();
16384
16385 // Should not move the pointer
16386 CHECK_EQ(ab->GetContents().Data(), store_ptr);
16387}
16388
16389
16390THREADED_TEST(SkipArrayBufferDuringScavenge) {
16391 LocalContext env;
16392 v8::Isolate* isolate = env->GetIsolate();
16393 v8::HandleScope handle_scope(isolate);
16394
16395 // Make sure the pointer looks like a heap object
16396 Local<v8::Object> tmp = v8::Object::New(isolate);
16397 uint8_t* store_ptr =
16398 reinterpret_cast<uint8_t*>(*reinterpret_cast<uintptr_t*>(*tmp));
16399
16400 // Make `store_ptr` point to from space
16401 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
16402
16403 // Create ArrayBuffer with pointer-that-cannot-be-visited in the backing store
16404 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, store_ptr, 8);
16405
16406 // Should not crash,
16407 // i.e. backing store pointer should not be treated as a heap object pointer
16408 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
16409 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
16410
16411 // Use `ab` to silence compiler warning
16412 CHECK_EQ(ab->GetContents().Data(), store_ptr);
16413}
16414
16415
16416THREADED_TEST(SharedUint8Array) {
16417 i::FLAG_harmony_sharedarraybuffer = true;
16418 TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
16419 v8::SharedArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
16420}
16421
16422
16423THREADED_TEST(SharedInt8Array) {
16424 i::FLAG_harmony_sharedarraybuffer = true;
16425 TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
16426 v8::SharedArrayBuffer>(i::kExternalInt8Array, -0x80,
16427 0x7F);
16428}
16429
16430
16431THREADED_TEST(SharedUint16Array) {
16432 i::FLAG_harmony_sharedarraybuffer = true;
16433 TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
16434 v8::SharedArrayBuffer>(i::kExternalUint16Array, 0,
16435 0xFFFF);
16436}
16437
16438
16439THREADED_TEST(SharedInt16Array) {
16440 i::FLAG_harmony_sharedarraybuffer = true;
16441 TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
16442 v8::SharedArrayBuffer>(i::kExternalInt16Array, -0x8000,
16443 0x7FFF);
16444}
16445
16446
16447THREADED_TEST(SharedUint32Array) {
16448 i::FLAG_harmony_sharedarraybuffer = true;
16449 TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
16450 v8::SharedArrayBuffer>(i::kExternalUint32Array, 0,
16451 UINT_MAX);
16452}
16453
16454
16455THREADED_TEST(SharedInt32Array) {
16456 i::FLAG_harmony_sharedarraybuffer = true;
16457 TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
16458 v8::SharedArrayBuffer>(i::kExternalInt32Array, INT_MIN,
16459 INT_MAX);
16460}
16461
16462
16463THREADED_TEST(SharedFloat32Array) {
16464 i::FLAG_harmony_sharedarraybuffer = true;
16465 TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
16466 v8::SharedArrayBuffer>(i::kExternalFloat32Array, -500,
16467 500);
16468}
16469
16470
16471THREADED_TEST(SharedFloat64Array) {
16472 i::FLAG_harmony_sharedarraybuffer = true;
16473 TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
16474 v8::SharedArrayBuffer>(i::kExternalFloat64Array, -500,
16475 500);
16476}
16477
16478
16479THREADED_TEST(SharedUint8ClampedArray) {
16480 i::FLAG_harmony_sharedarraybuffer = true;
16481 TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
16482 i::FixedUint8ClampedArray, v8::SharedArrayBuffer>(
16483 i::kExternalUint8ClampedArray, 0, 0xFF);
16484}
16485
16486
16487THREADED_TEST(SharedDataView) {
16488 i::FLAG_harmony_sharedarraybuffer = true;
16489 const int kSize = 50;
16490
16491 i::ScopedVector<uint8_t> backing_store(kSize + 2);
16492
16493 LocalContext env;
16494 v8::Isolate* isolate = env->GetIsolate();
16495 v8::HandleScope handle_scope(isolate);
16496
16497 Local<v8::SharedArrayBuffer> ab =
16498 v8::SharedArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
16499 Local<v8::DataView> dv =
16500 v8::DataView::New(ab, 2, kSize);
16501 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
16502 CHECK_EQ(2u, dv->ByteOffset());
16503 CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
16504 CHECK(ab->Equals(env.local(), dv->Buffer()).FromJust());
16505}
16506
16507
16508#define IS_ARRAY_BUFFER_VIEW_TEST(View) \
16509 THREADED_TEST(Is##View) { \
16510 LocalContext env; \
16511 v8::Isolate* isolate = env->GetIsolate(); \
16512 v8::HandleScope handle_scope(isolate); \
16513 \
16514 Local<Value> result = CompileRun( \
16515 "var ab = new ArrayBuffer(128);" \
16516 "new " #View "(ab)"); \
16517 CHECK(result->IsArrayBufferView()); \
16518 CHECK(result->Is##View()); \
16519 CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>()); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016520 }
16521
16522IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
16523IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
16524IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
16525IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
16526IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
16527IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
16528IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
16529IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
16530IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
16531IS_ARRAY_BUFFER_VIEW_TEST(DataView)
16532
16533#undef IS_ARRAY_BUFFER_VIEW_TEST
16534
16535
16536
Steve Blocka7e24c12009-10-30 11:49:00 +000016537THREADED_TEST(ScriptContextDependence) {
Steve Blocka7e24c12009-10-30 11:49:00 +000016538 LocalContext c1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016539 v8::HandleScope scope(c1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000016540 const char *source = "foo";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016541 v8::Local<v8::Script> dep = v8_compile(source);
16542 v8::ScriptCompiler::Source script_source(
16543 v8::String::NewFromUtf8(c1->GetIsolate(), source,
16544 v8::NewStringType::kNormal)
16545 .ToLocalChecked());
16546 v8::Local<v8::UnboundScript> indep =
16547 v8::ScriptCompiler::CompileUnboundScript(c1->GetIsolate(), &script_source)
16548 .ToLocalChecked();
16549 c1->Global()
16550 ->Set(c1.local(), v8::String::NewFromUtf8(c1->GetIsolate(), "foo",
16551 v8::NewStringType::kNormal)
16552 .ToLocalChecked(),
16553 v8::Integer::New(c1->GetIsolate(), 100))
16554 .FromJust();
16555 CHECK_EQ(
16556 dep->Run(c1.local()).ToLocalChecked()->Int32Value(c1.local()).FromJust(),
16557 100);
16558 CHECK_EQ(indep->BindToCurrentContext()
16559 ->Run(c1.local())
16560 .ToLocalChecked()
16561 ->Int32Value(c1.local())
16562 .FromJust(),
16563 100);
Steve Blocka7e24c12009-10-30 11:49:00 +000016564 LocalContext c2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016565 c2->Global()
16566 ->Set(c2.local(), v8::String::NewFromUtf8(c2->GetIsolate(), "foo",
16567 v8::NewStringType::kNormal)
16568 .ToLocalChecked(),
16569 v8::Integer::New(c2->GetIsolate(), 101))
16570 .FromJust();
16571 CHECK_EQ(
16572 dep->Run(c2.local()).ToLocalChecked()->Int32Value(c2.local()).FromJust(),
16573 100);
16574 CHECK_EQ(indep->BindToCurrentContext()
16575 ->Run(c2.local())
16576 .ToLocalChecked()
16577 ->Int32Value(c2.local())
16578 .FromJust(),
16579 101);
Steve Blocka7e24c12009-10-30 11:49:00 +000016580}
16581
16582
16583THREADED_TEST(StackTrace) {
Steve Blocka7e24c12009-10-30 11:49:00 +000016584 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016585 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016586 v8::TryCatch try_catch(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000016587 const char *source = "function foo() { FAIL.FAIL; }; foo();";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016588 v8::Local<v8::String> src = v8_str(source);
16589 v8::Local<v8::String> origin = v8_str("stack-trace-test");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016590 v8::ScriptCompiler::Source script_source(src, v8::ScriptOrigin(origin));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016591 CHECK(v8::ScriptCompiler::CompileUnboundScript(context->GetIsolate(),
16592 &script_source)
16593 .ToLocalChecked()
16594 ->BindToCurrentContext()
16595 ->Run(context.local())
16596 .IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000016597 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016598 v8::String::Utf8Value stack(
16599 try_catch.StackTrace(context.local()).ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +000016600 CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
16601}
16602
16603
Kristian Monsen25f61362010-05-21 11:50:48 +010016604// Checks that a StackFrame has certain expected values.
16605void checkStackFrame(const char* expected_script_name,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016606 const char* expected_func_name, int expected_line_number,
16607 int expected_column, bool is_eval, bool is_constructor,
16608 v8::Local<v8::StackFrame> frame) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016609 v8::HandleScope scope(CcTest::isolate());
Kristian Monsen25f61362010-05-21 11:50:48 +010016610 v8::String::Utf8Value func_name(frame->GetFunctionName());
16611 v8::String::Utf8Value script_name(frame->GetScriptName());
16612 if (*script_name == NULL) {
16613 // The situation where there is no associated script, like for evals.
16614 CHECK(expected_script_name == NULL);
16615 } else {
16616 CHECK(strstr(*script_name, expected_script_name) != NULL);
16617 }
16618 CHECK(strstr(*func_name, expected_func_name) != NULL);
16619 CHECK_EQ(expected_line_number, frame->GetLineNumber());
16620 CHECK_EQ(expected_column, frame->GetColumn());
16621 CHECK_EQ(is_eval, frame->IsEval());
16622 CHECK_EQ(is_constructor, frame->IsConstructor());
16623}
16624
16625
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016626void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
16627 v8::HandleScope scope(args.GetIsolate());
Kristian Monsen25f61362010-05-21 11:50:48 +010016628 const char* origin = "capture-stack-trace-test";
16629 const int kOverviewTest = 1;
16630 const int kDetailedTest = 2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016631 const int kFunctionName = 3;
16632 const int kDisplayName = 4;
16633 const int kFunctionNameAndDisplayName = 5;
16634 const int kDisplayNameIsNotString = 6;
16635 const int kFunctionNameIsNotString = 7;
Kristian Monsen25f61362010-05-21 11:50:48 +010016636
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016637 CHECK(args.Length() == 1);
Kristian Monsen25f61362010-05-21 11:50:48 +010016638
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016639 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
16640 int testGroup = args[0]->Int32Value(context).FromJust();
Kristian Monsen25f61362010-05-21 11:50:48 +010016641 if (testGroup == kOverviewTest) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016642 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016643 args.GetIsolate(), 10, v8::StackTrace::kOverview);
Kristian Monsen25f61362010-05-21 11:50:48 +010016644 CHECK_EQ(4, stackTrace->GetFrameCount());
16645 checkStackFrame(origin, "bar", 2, 10, false, false,
16646 stackTrace->GetFrame(0));
16647 checkStackFrame(origin, "foo", 6, 3, false, false,
16648 stackTrace->GetFrame(1));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000016649 // This is the source string inside the eval which has the call to foo.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016650 checkStackFrame(NULL, "", 1, 1, false, false, stackTrace->GetFrame(2));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000016651 // The last frame is an anonymous function which has the initial eval call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016652 checkStackFrame(origin, "", 8, 7, false, false, stackTrace->GetFrame(3));
Kristian Monsen25f61362010-05-21 11:50:48 +010016653
16654 CHECK(stackTrace->AsArray()->IsArray());
16655 } else if (testGroup == kDetailedTest) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016656 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016657 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
Kristian Monsen25f61362010-05-21 11:50:48 +010016658 CHECK_EQ(4, stackTrace->GetFrameCount());
16659 checkStackFrame(origin, "bat", 4, 22, false, false,
16660 stackTrace->GetFrame(0));
16661 checkStackFrame(origin, "baz", 8, 3, false, true,
16662 stackTrace->GetFrame(1));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +010016663 bool is_eval = true;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000016664 // This is the source string inside the eval which has the call to baz.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016665 checkStackFrame(NULL, "", 1, 1, is_eval, false, stackTrace->GetFrame(2));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000016666 // The last frame is an anonymous function which has the initial eval call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016667 checkStackFrame(origin, "", 10, 1, false, false, stackTrace->GetFrame(3));
Kristian Monsen25f61362010-05-21 11:50:48 +010016668
16669 CHECK(stackTrace->AsArray()->IsArray());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016670 } else if (testGroup == kFunctionName) {
16671 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
16672 args.GetIsolate(), 5, v8::StackTrace::kOverview);
16673 CHECK_EQ(3, stackTrace->GetFrameCount());
16674 checkStackFrame(origin, "function.name", 2, 24, false, false,
16675 stackTrace->GetFrame(0));
16676 } else if (testGroup == kDisplayName) {
16677 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
16678 args.GetIsolate(), 5, v8::StackTrace::kOverview);
16679 CHECK_EQ(3, stackTrace->GetFrameCount());
16680 checkStackFrame(origin, "function.displayName", 2, 24, false, false,
16681 stackTrace->GetFrame(0));
16682 } else if (testGroup == kFunctionNameAndDisplayName) {
16683 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
16684 args.GetIsolate(), 5, v8::StackTrace::kOverview);
16685 CHECK_EQ(3, stackTrace->GetFrameCount());
16686 checkStackFrame(origin, "function.displayName", 2, 24, false, false,
16687 stackTrace->GetFrame(0));
16688 } else if (testGroup == kDisplayNameIsNotString) {
16689 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
16690 args.GetIsolate(), 5, v8::StackTrace::kOverview);
16691 CHECK_EQ(3, stackTrace->GetFrameCount());
16692 checkStackFrame(origin, "function.name", 2, 24, false, false,
16693 stackTrace->GetFrame(0));
16694 } else if (testGroup == kFunctionNameIsNotString) {
16695 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
16696 args.GetIsolate(), 5, v8::StackTrace::kOverview);
16697 CHECK_EQ(3, stackTrace->GetFrameCount());
16698 checkStackFrame(origin, "f", 2, 24, false, false, stackTrace->GetFrame(0));
Kristian Monsen25f61362010-05-21 11:50:48 +010016699 }
Kristian Monsen25f61362010-05-21 11:50:48 +010016700}
16701
16702
16703// Tests the C++ StackTrace API.
Ben Murdochb0fe1622011-05-05 13:52:32 +010016704// TODO(3074796): Reenable this as a THREADED_TEST once it passes.
16705// THREADED_TEST(CaptureStackTrace) {
16706TEST(CaptureStackTrace) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016707 v8::Isolate* isolate = CcTest::isolate();
16708 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016709 v8::Local<v8::String> origin = v8_str("capture-stack-trace-test");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016710 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Kristian Monsen25f61362010-05-21 11:50:48 +010016711 templ->Set(v8_str("AnalyzeStackInNativeCode"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016712 v8::FunctionTemplate::New(isolate, AnalyzeStackInNativeCode));
Kristian Monsen25f61362010-05-21 11:50:48 +010016713 LocalContext context(0, templ);
16714
16715 // Test getting OVERVIEW information. Should ignore information that is not
16716 // script name, function name, line number, and column offset.
16717 const char *overview_source =
16718 "function bar() {\n"
16719 " var y; AnalyzeStackInNativeCode(1);\n"
16720 "}\n"
16721 "function foo() {\n"
16722 "\n"
16723 " bar();\n"
16724 "}\n"
16725 "var x;eval('new foo();');";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016726 v8::Local<v8::String> overview_src = v8_str(overview_source);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016727 v8::ScriptCompiler::Source script_source(overview_src,
16728 v8::ScriptOrigin(origin));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016729 v8::Local<Value> overview_result(
16730 v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source)
16731 .ToLocalChecked()
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016732 ->BindToCurrentContext()
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016733 ->Run(context.local())
16734 .ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016735 CHECK(!overview_result.IsEmpty());
16736 CHECK(overview_result->IsObject());
Kristian Monsen25f61362010-05-21 11:50:48 +010016737
16738 // Test getting DETAILED information.
16739 const char *detailed_source =
16740 "function bat() {AnalyzeStackInNativeCode(2);\n"
16741 "}\n"
16742 "\n"
16743 "function baz() {\n"
16744 " bat();\n"
16745 "}\n"
16746 "eval('new baz();');";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016747 v8::Local<v8::String> detailed_src = v8_str(detailed_source);
Kristian Monsen25f61362010-05-21 11:50:48 +010016748 // Make the script using a non-zero line and column offset.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016749 v8::Local<v8::Integer> line_offset = v8::Integer::New(isolate, 3);
16750 v8::Local<v8::Integer> column_offset = v8::Integer::New(isolate, 5);
Kristian Monsen25f61362010-05-21 11:50:48 +010016751 v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016752 v8::ScriptCompiler::Source script_source2(detailed_src, detailed_origin);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016753 v8::Local<v8::UnboundScript> detailed_script(
16754 v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source2)
16755 .ToLocalChecked());
16756 v8::Local<Value> detailed_result(detailed_script->BindToCurrentContext()
16757 ->Run(context.local())
16758 .ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016759 CHECK(!detailed_result.IsEmpty());
16760 CHECK(detailed_result->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016761
16762 // Test using function.name and function.displayName in stack trace
16763 const char* function_name_source =
16764 "function bar(function_name, display_name, testGroup) {\n"
16765 " var f = function() { AnalyzeStackInNativeCode(testGroup); };\n"
16766 " if (function_name) {\n"
16767 " Object.defineProperty(f, 'name', { value: function_name });\n"
16768 " }\n"
16769 " if (display_name) {\n"
16770 " f.displayName = display_name;"
16771 " }\n"
16772 " f()\n"
16773 "}\n"
16774 "bar('function.name', undefined, 3);\n"
16775 "bar(undefined, 'function.displayName', 4);\n"
16776 "bar('function.name', 'function.displayName', 5);\n"
16777 "bar('function.name', 239, 6);\n"
16778 "bar(239, undefined, 7);\n";
16779 v8::Local<v8::String> function_name_src =
16780 v8::String::NewFromUtf8(isolate, function_name_source,
16781 v8::NewStringType::kNormal)
16782 .ToLocalChecked();
16783 v8::ScriptCompiler::Source script_source3(function_name_src,
16784 v8::ScriptOrigin(origin));
16785 v8::Local<Value> function_name_result(
16786 v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source3)
16787 .ToLocalChecked()
16788 ->BindToCurrentContext()
16789 ->Run(context.local())
16790 .ToLocalChecked());
16791 CHECK(!function_name_result.IsEmpty());
Kristian Monsen25f61362010-05-21 11:50:48 +010016792}
16793
16794
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016795static void StackTraceForUncaughtExceptionListener(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016796 v8::Local<v8::Message> message, v8::Local<Value>) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016797 report_count++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016798 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016799 CHECK_EQ(2, stack_trace->GetFrameCount());
16800 checkStackFrame("origin", "foo", 2, 3, false, false,
16801 stack_trace->GetFrame(0));
16802 checkStackFrame("origin", "bar", 5, 3, false, false,
16803 stack_trace->GetFrame(1));
16804}
16805
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016806
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016807TEST(CaptureStackTraceForUncaughtException) {
16808 report_count = 0;
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016809 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016810 v8::Isolate* isolate = env->GetIsolate();
16811 v8::HandleScope scope(isolate);
16812 isolate->AddMessageListener(StackTraceForUncaughtExceptionListener);
16813 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016814
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016815 CompileRunWithOrigin(
16816 "function foo() {\n"
16817 " throw 1;\n"
16818 "};\n"
16819 "function bar() {\n"
16820 " foo();\n"
16821 "};",
16822 "origin");
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016823 v8::Local<v8::Object> global = env->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016824 Local<Value> trouble =
16825 global->Get(env.local(), v8_str("bar")).ToLocalChecked();
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016826 CHECK(trouble->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016827 CHECK(Function::Cast(*trouble)->Call(env.local(), global, 0, NULL).IsEmpty());
16828 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
16829 isolate->RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016830 CHECK_EQ(1, report_count);
16831}
16832
16833
16834TEST(GetStackTraceForUncaughtExceptionFromSimpleStackTrace) {
16835 report_count = 0;
16836 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016837 v8::Isolate* isolate = env->GetIsolate();
16838 v8::HandleScope scope(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016839
16840 // Create an Error object first.
16841 CompileRunWithOrigin(
16842 "function foo() {\n"
16843 "e=new Error('err');\n"
16844 "};\n"
16845 "function bar() {\n"
16846 " foo();\n"
16847 "};\n"
16848 "var e;",
16849 "origin");
16850 v8::Local<v8::Object> global = env->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016851 Local<Value> trouble =
16852 global->Get(env.local(), v8_str("bar")).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016853 CHECK(trouble->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016854 Function::Cast(*trouble)->Call(env.local(), global, 0, NULL).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016855
16856 // Enable capturing detailed stack trace late, and throw the exception.
16857 // The detailed stack trace should be extracted from the simple stack.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016858 isolate->AddMessageListener(StackTraceForUncaughtExceptionListener);
16859 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016860 CompileRunWithOrigin("throw e", "origin");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016861 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
16862 isolate->RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016863 CHECK_EQ(1, report_count);
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016864}
16865
16866
Steve Block1e0659c2011-05-24 12:43:12 +010016867TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
Steve Block1e0659c2011-05-24 12:43:12 +010016868 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016869 v8::Isolate* isolate = env->GetIsolate();
16870 v8::HandleScope scope(isolate);
16871 isolate->SetCaptureStackTraceForUncaughtExceptions(true, 1024,
16872 v8::StackTrace::kDetailed);
Steve Block1e0659c2011-05-24 12:43:12 +010016873
16874 CompileRun(
16875 "var setters = ['column', 'lineNumber', 'scriptName',\n"
16876 " 'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
16877 " 'isConstructor'];\n"
16878 "for (var i = 0; i < setters.length; i++) {\n"
16879 " var prop = setters[i];\n"
16880 " Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
16881 "}\n");
16882 CompileRun("throw 'exception';");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016883 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
Steve Block1e0659c2011-05-24 12:43:12 +010016884}
16885
16886
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016887static void StackTraceFunctionNameListener(v8::Local<v8::Message> message,
16888 v8::Local<Value>) {
16889 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
16890 CHECK_EQ(5, stack_trace->GetFrameCount());
16891 checkStackFrame("origin", "foo:0", 4, 7, false, false,
16892 stack_trace->GetFrame(0));
16893 checkStackFrame("origin", "foo:1", 5, 27, false, false,
16894 stack_trace->GetFrame(1));
16895 checkStackFrame("origin", "foo", 5, 27, false, false,
16896 stack_trace->GetFrame(2));
16897 checkStackFrame("origin", "foo", 5, 27, false, false,
16898 stack_trace->GetFrame(3));
16899 checkStackFrame("origin", "", 1, 14, false, false, stack_trace->GetFrame(4));
16900}
16901
16902
16903TEST(GetStackTraceContainsFunctionsWithFunctionName) {
16904 LocalContext env;
16905 v8::Isolate* isolate = env->GetIsolate();
16906 v8::HandleScope scope(isolate);
16907
16908 CompileRunWithOrigin(
16909 "function gen(name, counter) {\n"
16910 " var f = function foo() {\n"
16911 " if (counter === 0)\n"
16912 " throw 1;\n"
16913 " gen(name, counter - 1)();\n"
16914 " };\n"
16915 " if (counter == 3) {\n"
16916 " Object.defineProperty(f, 'name', {get: function(){ throw 239; }});\n"
16917 " } else {\n"
16918 " Object.defineProperty(f, 'name', {writable:true});\n"
16919 " if (counter == 2)\n"
16920 " f.name = 42;\n"
16921 " else\n"
16922 " f.name = name + ':' + counter;\n"
16923 " }\n"
16924 " return f;\n"
16925 "};",
16926 "origin");
16927
16928 isolate->AddMessageListener(StackTraceFunctionNameListener);
16929 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
16930 CompileRunWithOrigin("gen('foo', 3)();", "origin");
16931 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
16932 isolate->RemoveMessageListeners(StackTraceFunctionNameListener);
16933}
16934
16935
16936static void RethrowStackTraceHandler(v8::Local<v8::Message> message,
16937 v8::Local<v8::Value> data) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016938 // Use the frame where JavaScript is called from.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016939 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016940 CHECK(!stack_trace.IsEmpty());
16941 int frame_count = stack_trace->GetFrameCount();
16942 CHECK_EQ(3, frame_count);
16943 int line_number[] = {1, 2, 5};
16944 for (int i = 0; i < frame_count; i++) {
16945 CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
16946 }
16947}
16948
16949
16950// Test that we only return the stack trace at the site where the exception
16951// is first thrown (not where it is rethrown).
16952TEST(RethrowStackTrace) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016953 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016954 v8::Isolate* isolate = env->GetIsolate();
16955 v8::HandleScope scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016956 // We make sure that
16957 // - the stack trace of the ReferenceError in g() is reported.
16958 // - the stack trace is not overwritten when e1 is rethrown by t().
16959 // - the stack trace of e2 does not overwrite that of e1.
16960 const char* source =
16961 "function g() { error; } \n"
16962 "function f() { g(); } \n"
16963 "function t(e) { throw e; } \n"
16964 "try { \n"
16965 " f(); \n"
16966 "} catch (e1) { \n"
16967 " try { \n"
16968 " error; \n"
16969 " } catch (e2) { \n"
16970 " t(e1); \n"
16971 " } \n"
16972 "} \n";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016973 isolate->AddMessageListener(RethrowStackTraceHandler);
16974 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016975 CompileRun(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016976 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
16977 isolate->RemoveMessageListeners(RethrowStackTraceHandler);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016978}
16979
16980
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016981static void RethrowPrimitiveStackTraceHandler(v8::Local<v8::Message> message,
16982 v8::Local<v8::Value> data) {
16983 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016984 CHECK(!stack_trace.IsEmpty());
16985 int frame_count = stack_trace->GetFrameCount();
16986 CHECK_EQ(2, frame_count);
16987 int line_number[] = {3, 7};
16988 for (int i = 0; i < frame_count; i++) {
16989 CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
16990 }
16991}
16992
16993
16994// Test that we do not recognize identity for primitive exceptions.
16995TEST(RethrowPrimitiveStackTrace) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016996 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016997 v8::Isolate* isolate = env->GetIsolate();
16998 v8::HandleScope scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016999 // We do not capture stack trace for non Error objects on creation time.
17000 // Instead, we capture the stack trace on last throw.
17001 const char* source =
17002 "function g() { throw 404; } \n"
17003 "function f() { g(); } \n"
17004 "function t(e) { throw e; } \n"
17005 "try { \n"
17006 " f(); \n"
17007 "} catch (e1) { \n"
17008 " t(e1) \n"
17009 "} \n";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017010 isolate->AddMessageListener(RethrowPrimitiveStackTraceHandler);
17011 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017012 CompileRun(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017013 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
17014 isolate->RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017015}
17016
17017
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017018static void RethrowExistingStackTraceHandler(v8::Local<v8::Message> message,
17019 v8::Local<v8::Value> data) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017020 // Use the frame where JavaScript is called from.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017021 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017022 CHECK(!stack_trace.IsEmpty());
17023 CHECK_EQ(1, stack_trace->GetFrameCount());
17024 CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
17025}
17026
17027
17028// Test that the stack trace is captured when the error object is created and
17029// not where it is thrown.
17030TEST(RethrowExistingStackTrace) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017031 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017032 v8::Isolate* isolate = env->GetIsolate();
17033 v8::HandleScope scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017034 const char* source =
17035 "var e = new Error(); \n"
17036 "throw e; \n";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017037 isolate->AddMessageListener(RethrowExistingStackTraceHandler);
17038 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017039 CompileRun(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017040 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
17041 isolate->RemoveMessageListeners(RethrowExistingStackTraceHandler);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017042}
17043
17044
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017045static void RethrowBogusErrorStackTraceHandler(v8::Local<v8::Message> message,
17046 v8::Local<v8::Value> data) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017047 // Use the frame where JavaScript is called from.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017048 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017049 CHECK(!stack_trace.IsEmpty());
17050 CHECK_EQ(1, stack_trace->GetFrameCount());
17051 CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
17052}
17053
17054
17055// Test that the stack trace is captured where the bogus Error object is thrown.
17056TEST(RethrowBogusErrorStackTrace) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017057 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017058 v8::Isolate* isolate = env->GetIsolate();
17059 v8::HandleScope scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017060 const char* source =
17061 "var e = {__proto__: new Error()} \n"
17062 "throw e; \n";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017063 isolate->AddMessageListener(RethrowBogusErrorStackTraceHandler);
17064 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017065 CompileRun(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017066 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
17067 isolate->RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017068}
17069
17070
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017071v8::PromiseRejectEvent reject_event = v8::kPromiseRejectWithNoHandler;
17072int promise_reject_counter = 0;
17073int promise_revoke_counter = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017074int promise_reject_msg_line_number = -1;
17075int promise_reject_msg_column_number = -1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017076int promise_reject_line_number = -1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017077int promise_reject_column_number = -1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017078int promise_reject_frame_count = -1;
17079
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017080void PromiseRejectCallback(v8::PromiseRejectMessage reject_message) {
17081 v8::Local<v8::Object> global = CcTest::global();
17082 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
17083 if (reject_message.GetEvent() == v8::kPromiseRejectWithNoHandler) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017084 promise_reject_counter++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017085 global->Set(context, v8_str("rejected"), reject_message.GetPromise())
17086 .FromJust();
17087 global->Set(context, v8_str("value"), reject_message.GetValue()).FromJust();
17088 v8::Local<v8::Message> message = v8::Exception::CreateMessage(
17089 CcTest::isolate(), reject_message.GetValue());
17090 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
17091
17092 promise_reject_msg_line_number = message->GetLineNumber(context).FromJust();
17093 promise_reject_msg_column_number =
17094 message->GetStartColumn(context).FromJust() + 1;
17095
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017096 if (!stack_trace.IsEmpty()) {
17097 promise_reject_frame_count = stack_trace->GetFrameCount();
17098 if (promise_reject_frame_count > 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017099 CHECK(stack_trace->GetFrame(0)
17100 ->GetScriptName()
17101 ->Equals(context, v8_str("pro"))
17102 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017103 promise_reject_line_number = stack_trace->GetFrame(0)->GetLineNumber();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017104 promise_reject_column_number = stack_trace->GetFrame(0)->GetColumn();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017105 } else {
17106 promise_reject_line_number = -1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017107 promise_reject_column_number = -1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017108 }
17109 }
17110 } else {
17111 promise_revoke_counter++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017112 global->Set(context, v8_str("revoked"), reject_message.GetPromise())
17113 .FromJust();
17114 CHECK(reject_message.GetValue().IsEmpty());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017115 }
17116}
17117
17118
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017119v8::Local<v8::Promise> GetPromise(const char* name) {
17120 return v8::Local<v8::Promise>::Cast(
17121 CcTest::global()
17122 ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(name))
17123 .ToLocalChecked());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017124}
17125
17126
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017127v8::Local<v8::Value> RejectValue() {
17128 return CcTest::global()
17129 ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value"))
17130 .ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017131}
17132
17133
17134void ResetPromiseStates() {
17135 promise_reject_counter = 0;
17136 promise_revoke_counter = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017137 promise_reject_msg_line_number = -1;
17138 promise_reject_msg_column_number = -1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017139 promise_reject_line_number = -1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017140 promise_reject_column_number = -1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017141 promise_reject_frame_count = -1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017142
17143 v8::Local<v8::Object> global = CcTest::global();
17144 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
17145 global->Set(context, v8_str("rejected"), v8_str("")).FromJust();
17146 global->Set(context, v8_str("value"), v8_str("")).FromJust();
17147 global->Set(context, v8_str("revoked"), v8_str("")).FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017148}
17149
17150
17151TEST(PromiseRejectCallback) {
17152 LocalContext env;
17153 v8::Isolate* isolate = env->GetIsolate();
17154 v8::HandleScope scope(isolate);
17155
17156 isolate->SetPromiseRejectCallback(PromiseRejectCallback);
17157
17158 ResetPromiseStates();
17159
17160 // Create promise p0.
17161 CompileRun(
17162 "var reject; \n"
17163 "var p0 = new Promise( \n"
17164 " function(res, rej) { \n"
17165 " reject = rej; \n"
17166 " } \n"
17167 "); \n");
17168 CHECK(!GetPromise("p0")->HasHandler());
17169 CHECK_EQ(0, promise_reject_counter);
17170 CHECK_EQ(0, promise_revoke_counter);
17171
17172 // Add resolve handler (and default reject handler) to p0.
17173 CompileRun("var p1 = p0.then(function(){});");
17174 CHECK(GetPromise("p0")->HasHandler());
17175 CHECK(!GetPromise("p1")->HasHandler());
17176 CHECK_EQ(0, promise_reject_counter);
17177 CHECK_EQ(0, promise_revoke_counter);
17178
17179 // Reject p0.
17180 CompileRun("reject('ppp');");
17181 CHECK(GetPromise("p0")->HasHandler());
17182 CHECK(!GetPromise("p1")->HasHandler());
17183 CHECK_EQ(1, promise_reject_counter);
17184 CHECK_EQ(0, promise_revoke_counter);
17185 CHECK_EQ(v8::kPromiseRejectWithNoHandler, reject_event);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017186 CHECK(
17187 GetPromise("rejected")->Equals(env.local(), GetPromise("p1")).FromJust());
17188 CHECK(RejectValue()->Equals(env.local(), v8_str("ppp")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017189
17190 // Reject p0 again. Callback is not triggered again.
17191 CompileRun("reject();");
17192 CHECK(GetPromise("p0")->HasHandler());
17193 CHECK(!GetPromise("p1")->HasHandler());
17194 CHECK_EQ(1, promise_reject_counter);
17195 CHECK_EQ(0, promise_revoke_counter);
17196
17197 // Add resolve handler to p1.
17198 CompileRun("var p2 = p1.then(function(){});");
17199 CHECK(GetPromise("p0")->HasHandler());
17200 CHECK(GetPromise("p1")->HasHandler());
17201 CHECK(!GetPromise("p2")->HasHandler());
17202 CHECK_EQ(2, promise_reject_counter);
17203 CHECK_EQ(1, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017204 CHECK(
17205 GetPromise("rejected")->Equals(env.local(), GetPromise("p2")).FromJust());
17206 CHECK(RejectValue()->Equals(env.local(), v8_str("ppp")).FromJust());
17207 CHECK(
17208 GetPromise("revoked")->Equals(env.local(), GetPromise("p1")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017209
17210 ResetPromiseStates();
17211
17212 // Create promise q0.
17213 CompileRun(
17214 "var q0 = new Promise( \n"
17215 " function(res, rej) { \n"
17216 " reject = rej; \n"
17217 " } \n"
17218 "); \n");
17219 CHECK(!GetPromise("q0")->HasHandler());
17220 CHECK_EQ(0, promise_reject_counter);
17221 CHECK_EQ(0, promise_revoke_counter);
17222
17223 // Add reject handler to q0.
17224 CompileRun("var q1 = q0.catch(function() {});");
17225 CHECK(GetPromise("q0")->HasHandler());
17226 CHECK(!GetPromise("q1")->HasHandler());
17227 CHECK_EQ(0, promise_reject_counter);
17228 CHECK_EQ(0, promise_revoke_counter);
17229
17230 // Reject q0.
17231 CompileRun("reject('qq')");
17232 CHECK(GetPromise("q0")->HasHandler());
17233 CHECK(!GetPromise("q1")->HasHandler());
17234 CHECK_EQ(0, promise_reject_counter);
17235 CHECK_EQ(0, promise_revoke_counter);
17236
17237 // Add a new reject handler, which rejects by returning Promise.reject().
17238 // The returned promise q_ triggers a reject callback at first, only to
17239 // revoke it when returning it causes q2 to be rejected.
17240 CompileRun(
17241 "var q_;"
17242 "var q2 = q0.catch( \n"
17243 " function() { \n"
17244 " q_ = Promise.reject('qqq'); \n"
17245 " return q_; \n"
17246 " } \n"
17247 "); \n");
17248 CHECK(GetPromise("q0")->HasHandler());
17249 CHECK(!GetPromise("q1")->HasHandler());
17250 CHECK(!GetPromise("q2")->HasHandler());
17251 CHECK(GetPromise("q_")->HasHandler());
17252 CHECK_EQ(2, promise_reject_counter);
17253 CHECK_EQ(1, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017254 CHECK(
17255 GetPromise("rejected")->Equals(env.local(), GetPromise("q2")).FromJust());
17256 CHECK(
17257 GetPromise("revoked")->Equals(env.local(), GetPromise("q_")).FromJust());
17258 CHECK(RejectValue()->Equals(env.local(), v8_str("qqq")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017259
17260 // Add a reject handler to the resolved q1, which rejects by throwing.
17261 CompileRun(
17262 "var q3 = q1.then( \n"
17263 " function() { \n"
17264 " throw 'qqqq'; \n"
17265 " } \n"
17266 "); \n");
17267 CHECK(GetPromise("q0")->HasHandler());
17268 CHECK(GetPromise("q1")->HasHandler());
17269 CHECK(!GetPromise("q2")->HasHandler());
17270 CHECK(!GetPromise("q3")->HasHandler());
17271 CHECK_EQ(3, promise_reject_counter);
17272 CHECK_EQ(1, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017273 CHECK(
17274 GetPromise("rejected")->Equals(env.local(), GetPromise("q3")).FromJust());
17275 CHECK(RejectValue()->Equals(env.local(), v8_str("qqqq")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017276
17277 ResetPromiseStates();
17278
17279 // Create promise r0, which has three handlers, two of which handle rejects.
17280 CompileRun(
17281 "var r0 = new Promise( \n"
17282 " function(res, rej) { \n"
17283 " reject = rej; \n"
17284 " } \n"
17285 "); \n"
17286 "var r1 = r0.catch(function() {}); \n"
17287 "var r2 = r0.then(function() {}); \n"
17288 "var r3 = r0.then(function() {}, \n"
17289 " function() {}); \n");
17290 CHECK(GetPromise("r0")->HasHandler());
17291 CHECK(!GetPromise("r1")->HasHandler());
17292 CHECK(!GetPromise("r2")->HasHandler());
17293 CHECK(!GetPromise("r3")->HasHandler());
17294 CHECK_EQ(0, promise_reject_counter);
17295 CHECK_EQ(0, promise_revoke_counter);
17296
17297 // Reject r0.
17298 CompileRun("reject('rrr')");
17299 CHECK(GetPromise("r0")->HasHandler());
17300 CHECK(!GetPromise("r1")->HasHandler());
17301 CHECK(!GetPromise("r2")->HasHandler());
17302 CHECK(!GetPromise("r3")->HasHandler());
17303 CHECK_EQ(1, promise_reject_counter);
17304 CHECK_EQ(0, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017305 CHECK(
17306 GetPromise("rejected")->Equals(env.local(), GetPromise("r2")).FromJust());
17307 CHECK(RejectValue()->Equals(env.local(), v8_str("rrr")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017308
17309 // Add reject handler to r2.
17310 CompileRun("var r4 = r2.catch(function() {});");
17311 CHECK(GetPromise("r0")->HasHandler());
17312 CHECK(!GetPromise("r1")->HasHandler());
17313 CHECK(GetPromise("r2")->HasHandler());
17314 CHECK(!GetPromise("r3")->HasHandler());
17315 CHECK(!GetPromise("r4")->HasHandler());
17316 CHECK_EQ(1, promise_reject_counter);
17317 CHECK_EQ(1, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017318 CHECK(
17319 GetPromise("revoked")->Equals(env.local(), GetPromise("r2")).FromJust());
17320 CHECK(RejectValue()->Equals(env.local(), v8_str("rrr")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017321
17322 // Add reject handlers to r4.
17323 CompileRun("var r5 = r4.then(function() {}, function() {});");
17324 CHECK(GetPromise("r0")->HasHandler());
17325 CHECK(!GetPromise("r1")->HasHandler());
17326 CHECK(GetPromise("r2")->HasHandler());
17327 CHECK(!GetPromise("r3")->HasHandler());
17328 CHECK(GetPromise("r4")->HasHandler());
17329 CHECK(!GetPromise("r5")->HasHandler());
17330 CHECK_EQ(1, promise_reject_counter);
17331 CHECK_EQ(1, promise_revoke_counter);
17332
17333 ResetPromiseStates();
17334
17335 // Create promise s0, which has three handlers, none of which handle rejects.
17336 CompileRun(
17337 "var s0 = new Promise( \n"
17338 " function(res, rej) { \n"
17339 " reject = rej; \n"
17340 " } \n"
17341 "); \n"
17342 "var s1 = s0.then(function() {}); \n"
17343 "var s2 = s0.then(function() {}); \n"
17344 "var s3 = s0.then(function() {}); \n");
17345 CHECK(GetPromise("s0")->HasHandler());
17346 CHECK(!GetPromise("s1")->HasHandler());
17347 CHECK(!GetPromise("s2")->HasHandler());
17348 CHECK(!GetPromise("s3")->HasHandler());
17349 CHECK_EQ(0, promise_reject_counter);
17350 CHECK_EQ(0, promise_revoke_counter);
17351
17352 // Reject s0.
17353 CompileRun("reject('sss')");
17354 CHECK(GetPromise("s0")->HasHandler());
17355 CHECK(!GetPromise("s1")->HasHandler());
17356 CHECK(!GetPromise("s2")->HasHandler());
17357 CHECK(!GetPromise("s3")->HasHandler());
17358 CHECK_EQ(3, promise_reject_counter);
17359 CHECK_EQ(0, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017360 CHECK(RejectValue()->Equals(env.local(), v8_str("sss")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017361
17362 // Test stack frames.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017363 env->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017364
17365 ResetPromiseStates();
17366
17367 // Create promise t0, which is rejected in the constructor with an error.
17368 CompileRunWithOrigin(
17369 "var t0 = new Promise( \n"
17370 " function(res, rej) { \n"
17371 " reference_error; \n"
17372 " } \n"
17373 "); \n",
17374 "pro", 0, 0);
17375 CHECK(!GetPromise("t0")->HasHandler());
17376 CHECK_EQ(1, promise_reject_counter);
17377 CHECK_EQ(0, promise_revoke_counter);
17378 CHECK_EQ(2, promise_reject_frame_count);
17379 CHECK_EQ(3, promise_reject_line_number);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017380 CHECK_EQ(5, promise_reject_column_number);
17381 CHECK_EQ(3, promise_reject_msg_line_number);
17382 CHECK_EQ(5, promise_reject_msg_column_number);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017383
17384 ResetPromiseStates();
17385
17386 // Create promise u0 and chain u1 to it, which is rejected via throw.
17387 CompileRunWithOrigin(
17388 "var u0 = Promise.resolve(); \n"
17389 "var u1 = u0.then( \n"
17390 " function() { \n"
17391 " (function() { \n"
17392 " throw new Error(); \n"
17393 " })(); \n"
17394 " } \n"
17395 " ); \n",
17396 "pro", 0, 0);
17397 CHECK(GetPromise("u0")->HasHandler());
17398 CHECK(!GetPromise("u1")->HasHandler());
17399 CHECK_EQ(1, promise_reject_counter);
17400 CHECK_EQ(0, promise_revoke_counter);
17401 CHECK_EQ(2, promise_reject_frame_count);
17402 CHECK_EQ(5, promise_reject_line_number);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017403 CHECK_EQ(23, promise_reject_column_number);
17404 CHECK_EQ(5, promise_reject_msg_line_number);
17405 CHECK_EQ(23, promise_reject_msg_column_number);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017406
17407 // Throw in u3, which handles u1's rejection.
17408 CompileRunWithOrigin(
17409 "function f() { \n"
17410 " return (function() { \n"
17411 " return new Error(); \n"
17412 " })(); \n"
17413 "} \n"
17414 "var u2 = Promise.reject(f()); \n"
17415 "var u3 = u1.catch( \n"
17416 " function() { \n"
17417 " return u2; \n"
17418 " } \n"
17419 " ); \n",
17420 "pro", 0, 0);
17421 CHECK(GetPromise("u0")->HasHandler());
17422 CHECK(GetPromise("u1")->HasHandler());
17423 CHECK(GetPromise("u2")->HasHandler());
17424 CHECK(!GetPromise("u3")->HasHandler());
17425 CHECK_EQ(3, promise_reject_counter);
17426 CHECK_EQ(2, promise_revoke_counter);
17427 CHECK_EQ(3, promise_reject_frame_count);
17428 CHECK_EQ(3, promise_reject_line_number);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017429 CHECK_EQ(12, promise_reject_column_number);
17430 CHECK_EQ(3, promise_reject_msg_line_number);
17431 CHECK_EQ(12, promise_reject_msg_column_number);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017432
17433 ResetPromiseStates();
17434
17435 // Create promise rejected promise v0, which is incorrectly handled by v1
17436 // via chaining cycle.
17437 CompileRunWithOrigin(
17438 "var v0 = Promise.reject(); \n"
17439 "var v1 = v0.catch( \n"
17440 " function() { \n"
17441 " return v1; \n"
17442 " } \n"
17443 " ); \n",
17444 "pro", 0, 0);
17445 CHECK(GetPromise("v0")->HasHandler());
17446 CHECK(!GetPromise("v1")->HasHandler());
17447 CHECK_EQ(2, promise_reject_counter);
17448 CHECK_EQ(1, promise_revoke_counter);
17449 CHECK_EQ(0, promise_reject_frame_count);
17450 CHECK_EQ(-1, promise_reject_line_number);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017451 CHECK_EQ(-1, promise_reject_column_number);
17452
17453 ResetPromiseStates();
17454
17455 // Create promise t1, which rejects by throwing syntax error from eval.
17456 CompileRunWithOrigin(
17457 "var t1 = new Promise( \n"
17458 " function(res, rej) { \n"
17459 " var content = '\\n\\\n"
17460 " }'; \n"
17461 " eval(content); \n"
17462 " } \n"
17463 "); \n",
17464 "pro", 0, 0);
17465 CHECK(!GetPromise("t1")->HasHandler());
17466 CHECK_EQ(1, promise_reject_counter);
17467 CHECK_EQ(0, promise_revoke_counter);
17468 CHECK_EQ(2, promise_reject_frame_count);
17469 CHECK_EQ(5, promise_reject_line_number);
17470 CHECK_EQ(10, promise_reject_column_number);
17471 CHECK_EQ(2, promise_reject_msg_line_number);
17472 CHECK_EQ(7, promise_reject_msg_column_number);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017473}
17474
17475
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017476void AnalyzeStackOfEvalWithSourceURL(
17477 const v8::FunctionCallbackInfo<v8::Value>& args) {
17478 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017479 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017480 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
Ben Murdochf87a2032010-10-22 12:50:53 +010017481 CHECK_EQ(5, stackTrace->GetFrameCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017482 v8::Local<v8::String> url = v8_str("eval_url");
Ben Murdochf87a2032010-10-22 12:50:53 +010017483 for (int i = 0; i < 3; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017484 v8::Local<v8::String> name =
Ben Murdochf87a2032010-10-22 12:50:53 +010017485 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17486 CHECK(!name.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017487 CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
Ben Murdochf87a2032010-10-22 12:50:53 +010017488 }
Ben Murdochf87a2032010-10-22 12:50:53 +010017489}
17490
17491
17492TEST(SourceURLInStackTrace) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017493 v8::Isolate* isolate = CcTest::isolate();
17494 v8::HandleScope scope(isolate);
17495 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdochf87a2032010-10-22 12:50:53 +010017496 templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017497 v8::FunctionTemplate::New(isolate,
17498 AnalyzeStackOfEvalWithSourceURL));
Ben Murdochf87a2032010-10-22 12:50:53 +010017499 LocalContext context(0, templ);
17500
17501 const char *source =
17502 "function outer() {\n"
17503 "function bar() {\n"
17504 " AnalyzeStackOfEvalWithSourceURL();\n"
17505 "}\n"
17506 "function foo() {\n"
17507 "\n"
17508 " bar();\n"
17509 "}\n"
17510 "foo();\n"
17511 "}\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017512 "eval('(' + outer +')()%s');";
17513
17514 i::ScopedVector<char> code(1024);
17515 i::SNPrintF(code, source, "//# sourceURL=eval_url");
17516 CHECK(CompileRun(code.start())->IsUndefined());
17517 i::SNPrintF(code, source, "//@ sourceURL=eval_url");
17518 CHECK(CompileRun(code.start())->IsUndefined());
17519}
17520
17521
17522static int scriptIdInStack[2];
17523
17524void AnalyzeScriptIdInStack(
17525 const v8::FunctionCallbackInfo<v8::Value>& args) {
17526 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017527 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017528 args.GetIsolate(), 10, v8::StackTrace::kScriptId);
17529 CHECK_EQ(2, stackTrace->GetFrameCount());
17530 for (int i = 0; i < 2; i++) {
17531 scriptIdInStack[i] = stackTrace->GetFrame(i)->GetScriptId();
17532 }
17533}
17534
17535
17536TEST(ScriptIdInStackTrace) {
17537 v8::Isolate* isolate = CcTest::isolate();
17538 v8::HandleScope scope(isolate);
17539 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17540 templ->Set(v8_str("AnalyzeScriptIdInStack"),
17541 v8::FunctionTemplate::New(isolate, AnalyzeScriptIdInStack));
17542 LocalContext context(0, templ);
17543
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017544 v8::Local<v8::String> scriptSource = v8_str(
17545 "function foo() {\n"
17546 " AnalyzeScriptIdInStack();"
17547 "}\n"
17548 "foo();\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017549 v8::Local<v8::Script> script = CompileWithOrigin(scriptSource, "test");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017550 script->Run(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017551 for (int i = 0; i < 2; i++) {
17552 CHECK(scriptIdInStack[i] != v8::Message::kNoScriptIdInfo);
17553 CHECK_EQ(scriptIdInStack[i], script->GetUnboundScript()->GetId());
17554 }
17555}
17556
17557
17558void AnalyzeStackOfInlineScriptWithSourceURL(
17559 const v8::FunctionCallbackInfo<v8::Value>& args) {
17560 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017561 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017562 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
17563 CHECK_EQ(4, stackTrace->GetFrameCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017564 v8::Local<v8::String> url = v8_str("source_url");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017565 for (int i = 0; i < 3; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017566 v8::Local<v8::String> name =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017567 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17568 CHECK(!name.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017569 CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017570 }
17571}
17572
17573
17574TEST(InlineScriptWithSourceURLInStackTrace) {
17575 v8::Isolate* isolate = CcTest::isolate();
17576 v8::HandleScope scope(isolate);
17577 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17578 templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
17579 v8::FunctionTemplate::New(
17580 CcTest::isolate(), AnalyzeStackOfInlineScriptWithSourceURL));
17581 LocalContext context(0, templ);
17582
17583 const char *source =
17584 "function outer() {\n"
17585 "function bar() {\n"
17586 " AnalyzeStackOfInlineScriptWithSourceURL();\n"
17587 "}\n"
17588 "function foo() {\n"
17589 "\n"
17590 " bar();\n"
17591 "}\n"
17592 "foo();\n"
17593 "}\n"
17594 "outer()\n%s";
17595
17596 i::ScopedVector<char> code(1024);
17597 i::SNPrintF(code, source, "//# sourceURL=source_url");
17598 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
17599 i::SNPrintF(code, source, "//@ sourceURL=source_url");
17600 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
17601}
17602
17603
17604void AnalyzeStackOfDynamicScriptWithSourceURL(
17605 const v8::FunctionCallbackInfo<v8::Value>& args) {
17606 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017607 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017608 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
17609 CHECK_EQ(4, stackTrace->GetFrameCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017610 v8::Local<v8::String> url = v8_str("source_url");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017611 for (int i = 0; i < 3; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017612 v8::Local<v8::String> name =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017613 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17614 CHECK(!name.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017615 CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017616 }
17617}
17618
17619
17620TEST(DynamicWithSourceURLInStackTrace) {
17621 v8::Isolate* isolate = CcTest::isolate();
17622 v8::HandleScope scope(isolate);
17623 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17624 templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
17625 v8::FunctionTemplate::New(
17626 CcTest::isolate(), AnalyzeStackOfDynamicScriptWithSourceURL));
17627 LocalContext context(0, templ);
17628
17629 const char *source =
17630 "function outer() {\n"
17631 "function bar() {\n"
17632 " AnalyzeStackOfDynamicScriptWithSourceURL();\n"
17633 "}\n"
17634 "function foo() {\n"
17635 "\n"
17636 " bar();\n"
17637 "}\n"
17638 "foo();\n"
17639 "}\n"
17640 "outer()\n%s";
17641
17642 i::ScopedVector<char> code(1024);
17643 i::SNPrintF(code, source, "//# sourceURL=source_url");
17644 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
17645 i::SNPrintF(code, source, "//@ sourceURL=source_url");
17646 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
17647}
17648
17649
17650TEST(DynamicWithSourceURLInStackTraceString) {
17651 LocalContext context;
17652 v8::HandleScope scope(context->GetIsolate());
17653
17654 const char *source =
17655 "function outer() {\n"
17656 " function foo() {\n"
17657 " FAIL.FAIL;\n"
17658 " }\n"
17659 " foo();\n"
17660 "}\n"
17661 "outer()\n%s";
17662
17663 i::ScopedVector<char> code(1024);
17664 i::SNPrintF(code, source, "//# sourceURL=source_url");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017665 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017666 CompileRunWithOrigin(code.start(), "", 0, 0);
17667 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017668 v8::String::Utf8Value stack(
17669 try_catch.StackTrace(context.local()).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017670 CHECK(strstr(*stack, "at foo (source_url:3:5)") != NULL);
17671}
17672
17673
17674TEST(EvalWithSourceURLInMessageScriptResourceNameOrSourceURL) {
17675 LocalContext context;
17676 v8::HandleScope scope(context->GetIsolate());
17677
17678 const char *source =
17679 "function outer() {\n"
17680 " var scriptContents = \"function foo() { FAIL.FAIL; }\\\n"
17681 " //# sourceURL=source_url\";\n"
17682 " eval(scriptContents);\n"
17683 " foo(); }\n"
17684 "outer();\n"
17685 "//# sourceURL=outer_url";
17686
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017687 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017688 CompileRun(source);
17689 CHECK(try_catch.HasCaught());
17690
17691 Local<v8::Message> message = try_catch.Message();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017692 Local<Value> sourceURL = message->GetScriptOrigin().ResourceName();
17693 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(sourceURL), "source_url"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017694}
17695
17696
17697TEST(RecursionWithSourceURLInMessageScriptResourceNameOrSourceURL) {
17698 LocalContext context;
17699 v8::HandleScope scope(context->GetIsolate());
17700
17701 const char *source =
17702 "function outer() {\n"
17703 " var scriptContents = \"function boo(){ boo(); }\\\n"
17704 " //# sourceURL=source_url\";\n"
17705 " eval(scriptContents);\n"
17706 " boo(); }\n"
17707 "outer();\n"
17708 "//# sourceURL=outer_url";
17709
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017710 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017711 CompileRun(source);
17712 CHECK(try_catch.HasCaught());
17713
17714 Local<v8::Message> message = try_catch.Message();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017715 Local<Value> sourceURL = message->GetScriptOrigin().ResourceName();
17716 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(sourceURL), "source_url"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017717}
17718
17719
17720static void CreateGarbageInOldSpace() {
17721 i::Factory* factory = CcTest::i_isolate()->factory();
17722 v8::HandleScope scope(CcTest::isolate());
17723 i::AlwaysAllocateScope always_allocate(CcTest::i_isolate());
17724 for (int i = 0; i < 1000; i++) {
17725 factory->NewFixedArray(1000, i::TENURED);
17726 }
Ben Murdochf87a2032010-10-22 12:50:53 +010017727}
17728
17729
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017730// Test that idle notification can be handled and eventually collects garbage.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017731TEST(TestIdleNotification) {
17732 if (!i::FLAG_incremental_marking) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017733 const intptr_t MB = 1024 * 1024;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017734 const double IdlePauseInSeconds = 1.0;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017735 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017736 v8::HandleScope scope(env->GetIsolate());
17737 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
17738 CreateGarbageInOldSpace();
17739 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
17740 CHECK_GT(size_with_garbage, initial_size + MB);
17741 bool finished = false;
17742 for (int i = 0; i < 200 && !finished; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017743 if (i < 10 && CcTest::heap()->incremental_marking()->IsStopped()) {
17744 CcTest::heap()->StartIdleIncrementalMarking();
17745 }
17746 finished = env->GetIsolate()->IdleNotificationDeadline(
17747 (v8::base::TimeTicks::HighResolutionNow().ToInternalValue() /
17748 static_cast<double>(v8::base::Time::kMicrosecondsPerSecond)) +
17749 IdlePauseInSeconds);
17750 if (CcTest::heap()->mark_compact_collector()->sweeping_in_progress()) {
17751 CcTest::heap()->mark_compact_collector()->EnsureSweepingCompleted();
17752 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017753 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017754 intptr_t final_size = CcTest::heap()->SizeOfObjects();
17755 CHECK(finished);
17756 CHECK_LT(final_size, initial_size + 1);
Ben Murdochc7cc0282012-03-05 14:35:55 +000017757}
17758
Steve Blocka7e24c12009-10-30 11:49:00 +000017759
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017760TEST(Regress2333) {
17761 LocalContext env;
17762 for (int i = 0; i < 3; i++) {
17763 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
17764 }
17765}
17766
Steve Blocka7e24c12009-10-30 11:49:00 +000017767static uint32_t* stack_limit;
17768
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017769static void GetStackLimitCallback(
17770 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Block44f0eee2011-05-26 01:26:41 +010017771 stack_limit = reinterpret_cast<uint32_t*>(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017772 CcTest::i_isolate()->stack_guard()->real_climit());
Steve Blocka7e24c12009-10-30 11:49:00 +000017773}
17774
17775
17776// Uses the address of a local variable to determine the stack top now.
17777// Given a size, returns an address that is that far from the current
17778// top of stack.
17779static uint32_t* ComputeStackLimit(uint32_t size) {
17780 uint32_t* answer = &size - (size / sizeof(size));
17781 // If the size is very large and the stack is very near the bottom of
17782 // memory then the calculation above may wrap around and give an address
17783 // that is above the (downwards-growing) stack. In that case we return
17784 // a very low address.
17785 if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
17786 return answer;
17787}
17788
17789
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017790// We need at least 165kB for an x64 debug build with clang and ASAN.
17791static const int stack_breathing_room = 256 * i::KB;
17792
17793
17794TEST(SetStackLimit) {
17795 uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
Steve Blocka7e24c12009-10-30 11:49:00 +000017796
17797 // Set stack limit.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017798 CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
Steve Blocka7e24c12009-10-30 11:49:00 +000017799
17800 // Execute a script.
Steve Blocka7e24c12009-10-30 11:49:00 +000017801 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017802 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000017803 Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017804 v8::FunctionTemplate::New(env->GetIsolate(), GetStackLimitCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017805 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
17806 CHECK(env->Global()
17807 ->Set(env.local(), v8_str("get_stack_limit"), fun)
17808 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000017809 CompileRun("get_stack_limit();");
17810
17811 CHECK(stack_limit == set_limit);
17812}
17813
17814
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017815TEST(SetStackLimitInThread) {
Steve Blocka7e24c12009-10-30 11:49:00 +000017816 uint32_t* set_limit;
17817 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017818 v8::Locker locker(CcTest::isolate());
17819 set_limit = ComputeStackLimit(stack_breathing_room);
Steve Blocka7e24c12009-10-30 11:49:00 +000017820
17821 // Set stack limit.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017822 CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
Steve Blocka7e24c12009-10-30 11:49:00 +000017823
17824 // Execute a script.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017825 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000017826 LocalContext env;
17827 Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017828 v8::FunctionTemplate::New(CcTest::isolate(), GetStackLimitCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017829 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
17830 CHECK(env->Global()
17831 ->Set(env.local(), v8_str("get_stack_limit"), fun)
17832 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000017833 CompileRun("get_stack_limit();");
17834
17835 CHECK(stack_limit == set_limit);
17836 }
17837 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017838 v8::Locker locker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000017839 CHECK(stack_limit == set_limit);
17840 }
17841}
Steve Block3ce2e202009-11-05 08:53:23 +000017842
17843
17844THREADED_TEST(GetHeapStatistics) {
Steve Block3ce2e202009-11-05 08:53:23 +000017845 LocalContext c1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017846 v8::HandleScope scope(c1->GetIsolate());
Steve Block3ce2e202009-11-05 08:53:23 +000017847 v8::HeapStatistics heap_statistics;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017848 CHECK_EQ(0u, heap_statistics.total_heap_size());
17849 CHECK_EQ(0u, heap_statistics.used_heap_size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017850 c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
Steve Blockd0582a62009-12-15 09:54:21 +000017851 CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
17852 CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
17853}
17854
17855
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017856class VisitorImpl : public v8::ExternalResourceVisitor {
17857 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017858 explicit VisitorImpl(TestResource** resource) {
17859 for (int i = 0; i < 4; i++) {
17860 resource_[i] = resource[i];
17861 found_resource_[i] = false;
17862 }
17863 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017864 virtual ~VisitorImpl() {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017865 virtual void VisitExternalString(v8::Local<v8::String> string) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017866 if (!string->IsExternal()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017867 CHECK(string->IsExternalOneByte());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017868 return;
17869 }
17870 v8::String::ExternalStringResource* resource =
17871 string->GetExternalStringResource();
17872 CHECK(resource);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017873 for (int i = 0; i < 4; i++) {
17874 if (resource_[i] == resource) {
17875 CHECK(!found_resource_[i]);
17876 found_resource_[i] = true;
17877 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017878 }
17879 }
17880 void CheckVisitedResources() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017881 for (int i = 0; i < 4; i++) {
17882 CHECK(found_resource_[i]);
17883 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017884 }
17885
17886 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017887 v8::String::ExternalStringResource* resource_[4];
17888 bool found_resource_[4];
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017889};
17890
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017891
17892TEST(ExternalizeOldSpaceTwoByteCons) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017893 v8::Isolate* isolate = CcTest::isolate();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017894 LocalContext env;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017895 v8::HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017896 v8::Local<v8::String> cons =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017897 CompileRun("'Romeo Montague ' + 'Juliet Capulet'")
17898 ->ToString(env.local())
17899 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017900 CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
17901 CcTest::heap()->CollectAllAvailableGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017902 CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017903
17904 TestResource* resource = new TestResource(
17905 AsciiToTwoByteString("Romeo Montague Juliet Capulet"));
17906 cons->MakeExternal(resource);
17907
17908 CHECK(cons->IsExternal());
17909 CHECK_EQ(resource, cons->GetExternalStringResource());
17910 String::Encoding encoding;
17911 CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
17912 CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
17913}
17914
17915
17916TEST(ExternalizeOldSpaceOneByteCons) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017917 v8::Isolate* isolate = CcTest::isolate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017918 LocalContext env;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017919 v8::HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017920 v8::Local<v8::String> cons =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017921 CompileRun("'Romeo Montague ' + 'Juliet Capulet'")
17922 ->ToString(env.local())
17923 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017924 CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
17925 CcTest::heap()->CollectAllAvailableGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017926 CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017927
17928 TestOneByteResource* resource =
17929 new TestOneByteResource(i::StrDup("Romeo Montague Juliet Capulet"));
17930 cons->MakeExternal(resource);
17931
17932 CHECK(cons->IsExternalOneByte());
17933 CHECK_EQ(resource, cons->GetExternalOneByteStringResource());
17934 String::Encoding encoding;
17935 CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
17936 CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
17937}
17938
17939
17940TEST(VisitExternalStrings) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017941 v8::Isolate* isolate = CcTest::isolate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017942 LocalContext env;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017943 v8::HandleScope scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017944 const char* string = "Some string";
17945 uint16_t* two_byte_string = AsciiToTwoByteString(string);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017946 TestResource* resource[4];
17947 resource[0] = new TestResource(two_byte_string);
17948 v8::Local<v8::String> string0 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017949 v8::String::NewExternalTwoByte(env->GetIsolate(), resource[0])
17950 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017951 resource[1] = new TestResource(two_byte_string, NULL, false);
17952 v8::Local<v8::String> string1 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017953 v8::String::NewExternalTwoByte(env->GetIsolate(), resource[1])
17954 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017955
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017956 // Externalized symbol.
17957 resource[2] = new TestResource(two_byte_string, NULL, false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017958 v8::Local<v8::String> string2 =
17959 v8::String::NewFromUtf8(env->GetIsolate(), string,
17960 v8::NewStringType::kInternalized)
17961 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017962 CHECK(string2->MakeExternal(resource[2]));
17963
17964 // Symbolized External.
17965 resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
17966 v8::Local<v8::String> string3 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017967 v8::String::NewExternalTwoByte(env->GetIsolate(), resource[3])
17968 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017969 CcTest::heap()->CollectAllAvailableGarbage(); // Tenure string.
17970 // Turn into a symbol.
17971 i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
17972 CHECK(!CcTest::i_isolate()->factory()->InternalizeString(
17973 string3_i).is_null());
17974 CHECK(string3_i->IsInternalizedString());
17975
17976 // We need to add usages for string* to avoid warnings in GCC 4.7
17977 CHECK(string0->IsExternal());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017978 CHECK(string1->IsExternal());
17979 CHECK(string2->IsExternal());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017980 CHECK(string3->IsExternal());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017981
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017982 VisitorImpl visitor(resource);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017983 isolate->VisitExternalResources(&visitor);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017984 visitor.CheckVisitedResources();
17985}
17986
17987
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017988TEST(ExternalStringCollectedAtTearDown) {
17989 int destroyed = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017990 v8::Isolate::CreateParams create_params;
17991 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
17992 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017993 { v8::Isolate::Scope isolate_scope(isolate);
17994 v8::HandleScope handle_scope(isolate);
17995 const char* s = "One string to test them all, one string to find them.";
17996 TestOneByteResource* inscription =
17997 new TestOneByteResource(i::StrDup(s), &destroyed);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017998 v8::Local<v8::String> ring =
17999 v8::String::NewExternalOneByte(isolate, inscription).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018000 // Ring is still alive. Orcs are roaming freely across our lands.
18001 CHECK_EQ(0, destroyed);
18002 USE(ring);
18003 }
18004
18005 isolate->Dispose();
18006 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
18007 CHECK_EQ(1, destroyed);
18008}
18009
18010
18011TEST(ExternalInternalizedStringCollectedAtTearDown) {
18012 int destroyed = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018013 v8::Isolate::CreateParams create_params;
18014 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
18015 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018016 { v8::Isolate::Scope isolate_scope(isolate);
18017 LocalContext env(isolate);
18018 v8::HandleScope handle_scope(isolate);
18019 CompileRun("var ring = 'One string to test them all';");
18020 const char* s = "One string to test them all";
18021 TestOneByteResource* inscription =
18022 new TestOneByteResource(i::StrDup(s), &destroyed);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018023 v8::Local<v8::String> ring =
18024 CompileRun("ring")->ToString(env.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018025 CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
18026 ring->MakeExternal(inscription);
18027 // Ring is still alive. Orcs are roaming freely across our lands.
18028 CHECK_EQ(0, destroyed);
18029 USE(ring);
18030 }
18031
18032 isolate->Dispose();
18033 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
18034 CHECK_EQ(1, destroyed);
18035}
18036
18037
18038TEST(ExternalInternalizedStringCollectedAtGC) {
18039 int destroyed = 0;
18040 { LocalContext env;
18041 v8::HandleScope handle_scope(env->GetIsolate());
18042 CompileRun("var ring = 'One string to test them all';");
18043 const char* s = "One string to test them all";
18044 TestOneByteResource* inscription =
18045 new TestOneByteResource(i::StrDup(s), &destroyed);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018046 v8::Local<v8::String> ring = CompileRun("ring").As<v8::String>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018047 CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
18048 ring->MakeExternal(inscription);
18049 // Ring is still alive. Orcs are roaming freely across our lands.
18050 CHECK_EQ(0, destroyed);
18051 USE(ring);
18052 }
18053
18054 // Garbage collector deals swift blows to evil.
18055 CcTest::i_isolate()->compilation_cache()->Clear();
18056 CcTest::heap()->CollectAllAvailableGarbage();
18057
18058 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
18059 CHECK_EQ(1, destroyed);
18060}
18061
18062
Steve Blockd0582a62009-12-15 09:54:21 +000018063static double DoubleFromBits(uint64_t value) {
18064 double target;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018065 i::MemCopy(&target, &value, sizeof(target));
Steve Blockd0582a62009-12-15 09:54:21 +000018066 return target;
18067}
18068
18069
18070static uint64_t DoubleToBits(double value) {
18071 uint64_t target;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018072 i::MemCopy(&target, &value, sizeof(target));
Steve Blockd0582a62009-12-15 09:54:21 +000018073 return target;
18074}
18075
18076
18077static double DoubleToDateTime(double input) {
18078 double date_limit = 864e13;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018079 if (std::isnan(input) || input < -date_limit || input > date_limit) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018080 return std::numeric_limits<double>::quiet_NaN();
Steve Blockd0582a62009-12-15 09:54:21 +000018081 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018082 return (input < 0) ? -(std::floor(-input)) : std::floor(input);
Steve Blockd0582a62009-12-15 09:54:21 +000018083}
18084
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018085
Steve Blockd0582a62009-12-15 09:54:21 +000018086// We don't have a consistent way to write 64-bit constants syntactically, so we
18087// split them into two 32-bit constants and combine them programmatically.
18088static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
18089 return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
18090}
18091
18092
18093THREADED_TEST(QuietSignalingNaNs) {
Steve Blockd0582a62009-12-15 09:54:21 +000018094 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018095 v8::Isolate* isolate = context->GetIsolate();
18096 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018097 v8::TryCatch try_catch(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018098
18099 // Special double values.
18100 double snan = DoubleFromBits(0x7ff00000, 0x00000001);
18101 double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
18102 double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
18103 double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
18104 double min_normal = DoubleFromBits(0x00100000, 0x00000000);
18105 double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
18106 double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
18107
18108 // Date values are capped at +/-100000000 days (times 864e5 ms per day)
18109 // on either side of the epoch.
18110 double date_limit = 864e13;
18111
18112 double test_values[] = {
18113 snan,
18114 qnan,
18115 infinity,
18116 max_normal,
18117 date_limit + 1,
18118 date_limit,
18119 min_normal,
18120 max_denormal,
18121 min_denormal,
18122 0,
18123 -0,
18124 -min_denormal,
18125 -max_denormal,
18126 -min_normal,
18127 -date_limit,
18128 -date_limit - 1,
18129 -max_normal,
18130 -infinity,
18131 -qnan,
18132 -snan
18133 };
18134 int num_test_values = 20;
18135
18136 for (int i = 0; i < num_test_values; i++) {
18137 double test_value = test_values[i];
18138
18139 // Check that Number::New preserves non-NaNs and quiets SNaNs.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018140 v8::Local<v8::Value> number = v8::Number::New(isolate, test_value);
18141 double stored_number = number->NumberValue(context.local()).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018142 if (!std::isnan(test_value)) {
Steve Blockd0582a62009-12-15 09:54:21 +000018143 CHECK_EQ(test_value, stored_number);
18144 } else {
18145 uint64_t stored_bits = DoubleToBits(stored_number);
18146 // Check if quiet nan (bits 51..62 all set).
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018147#if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018148 !defined(_MIPS_ARCH_MIPS64R6) && !defined(_MIPS_ARCH_MIPS32R6) && \
18149 !defined(USE_SIMULATOR)
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018150 // Most significant fraction bit for quiet nan is set to 0
18151 // on MIPS architecture. Allowed by IEEE-754.
18152 CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
18153#else
Steve Blockd0582a62009-12-15 09:54:21 +000018154 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018155#endif
Steve Blockd0582a62009-12-15 09:54:21 +000018156 }
18157
18158 // Check that Date::New preserves non-NaNs in the date range and
18159 // quiets SNaNs.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018160 v8::Local<v8::Value> date =
18161 v8::Date::New(context.local(), test_value).ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +000018162 double expected_stored_date = DoubleToDateTime(test_value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018163 double stored_date = date->NumberValue(context.local()).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018164 if (!std::isnan(expected_stored_date)) {
Steve Blockd0582a62009-12-15 09:54:21 +000018165 CHECK_EQ(expected_stored_date, stored_date);
18166 } else {
18167 uint64_t stored_bits = DoubleToBits(stored_date);
18168 // Check if quiet nan (bits 51..62 all set).
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018169#if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018170 !defined(_MIPS_ARCH_MIPS64R6) && !defined(_MIPS_ARCH_MIPS32R6) && \
18171 !defined(USE_SIMULATOR)
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018172 // Most significant fraction bit for quiet nan is set to 0
18173 // on MIPS architecture. Allowed by IEEE-754.
18174 CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
18175#else
Steve Blockd0582a62009-12-15 09:54:21 +000018176 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018177#endif
Steve Blockd0582a62009-12-15 09:54:21 +000018178 }
18179 }
18180}
18181
18182
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018183static void SpaghettiIncident(
18184 const v8::FunctionCallbackInfo<v8::Value>& args) {
18185 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018186 v8::TryCatch tc(args.GetIsolate());
18187 v8::MaybeLocal<v8::String> str(
18188 args[0]->ToString(args.GetIsolate()->GetCurrentContext()));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018189 USE(str);
Steve Blockd0582a62009-12-15 09:54:21 +000018190 if (tc.HasCaught())
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018191 tc.ReThrow();
Steve Blockd0582a62009-12-15 09:54:21 +000018192}
18193
18194
18195// Test that an exception can be propagated down through a spaghetti
18196// stack using ReThrow.
18197THREADED_TEST(SpaghettiStackReThrow) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018198 v8::Isolate* isolate = CcTest::isolate();
18199 v8::HandleScope scope(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018200 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018201 context->Global()
18202 ->Set(context.local(), v8_str("s"),
18203 v8::FunctionTemplate::New(isolate, SpaghettiIncident)
18204 ->GetFunction(context.local())
18205 .ToLocalChecked())
18206 .FromJust();
18207 v8::TryCatch try_catch(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018208 CompileRun(
18209 "var i = 0;"
18210 "var o = {"
18211 " toString: function () {"
18212 " if (i == 10) {"
18213 " throw 'Hey!';"
18214 " } else {"
18215 " i++;"
18216 " return s(o);"
18217 " }"
18218 " }"
18219 "};"
18220 "s(o);");
18221 CHECK(try_catch.HasCaught());
18222 v8::String::Utf8Value value(try_catch.Exception());
18223 CHECK_EQ(0, strcmp(*value, "Hey!"));
18224}
18225
18226
Steve Blockd0582a62009-12-15 09:54:21 +000018227TEST(Regress528) {
18228 v8::V8::Initialize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018229 v8::Isolate* isolate = CcTest::isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018230 i::FLAG_retain_maps_for_n_gc = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018231 v8::HandleScope scope(isolate);
18232 v8::Local<Context> other_context;
Steve Blockd0582a62009-12-15 09:54:21 +000018233 int gc_count;
18234
18235 // Create a context used to keep the code from aging in the compilation
18236 // cache.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018237 other_context = Context::New(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018238
18239 // Context-dependent context data creates reference from the compilation
18240 // cache to the global object.
18241 const char* source_simple = "1";
Steve Blockd0582a62009-12-15 09:54:21 +000018242 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018243 v8::HandleScope scope(isolate);
18244 v8::Local<Context> context = Context::New(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018245
18246 context->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018247 Local<v8::String> obj = v8_str("");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018248 context->SetEmbedderData(0, obj);
Steve Blockd0582a62009-12-15 09:54:21 +000018249 CompileRun(source_simple);
18250 context->Exit();
18251 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018252 isolate->ContextDisposedNotification();
Steve Blockd0582a62009-12-15 09:54:21 +000018253 for (gc_count = 1; gc_count < 10; gc_count++) {
18254 other_context->Enter();
18255 CompileRun(source_simple);
18256 other_context->Exit();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018257 CcTest::heap()->CollectAllGarbage();
Steve Blockd0582a62009-12-15 09:54:21 +000018258 if (GetGlobalObjectsCount() == 1) break;
18259 }
18260 CHECK_GE(2, gc_count);
18261 CHECK_EQ(1, GetGlobalObjectsCount());
18262
18263 // Eval in a function creates reference from the compilation cache to the
18264 // global object.
18265 const char* source_eval = "function f(){eval('1')}; f()";
Steve Blockd0582a62009-12-15 09:54:21 +000018266 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018267 v8::HandleScope scope(isolate);
18268 v8::Local<Context> context = Context::New(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018269
18270 context->Enter();
18271 CompileRun(source_eval);
18272 context->Exit();
18273 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018274 isolate->ContextDisposedNotification();
Steve Blockd0582a62009-12-15 09:54:21 +000018275 for (gc_count = 1; gc_count < 10; gc_count++) {
18276 other_context->Enter();
18277 CompileRun(source_eval);
18278 other_context->Exit();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018279 CcTest::heap()->CollectAllGarbage();
Steve Blockd0582a62009-12-15 09:54:21 +000018280 if (GetGlobalObjectsCount() == 1) break;
18281 }
18282 CHECK_GE(2, gc_count);
18283 CHECK_EQ(1, GetGlobalObjectsCount());
18284
18285 // Looking up the line number for an exception creates reference from the
18286 // compilation cache to the global object.
18287 const char* source_exception = "function f(){throw 1;} f()";
Steve Blockd0582a62009-12-15 09:54:21 +000018288 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018289 v8::HandleScope scope(isolate);
18290 v8::Local<Context> context = Context::New(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018291
18292 context->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018293 v8::TryCatch try_catch(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018294 CompileRun(source_exception);
18295 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018296 v8::Local<v8::Message> message = try_catch.Message();
Steve Blockd0582a62009-12-15 09:54:21 +000018297 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018298 CHECK_EQ(1, message->GetLineNumber(context).FromJust());
Steve Blockd0582a62009-12-15 09:54:21 +000018299 context->Exit();
18300 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018301 isolate->ContextDisposedNotification();
Steve Blockd0582a62009-12-15 09:54:21 +000018302 for (gc_count = 1; gc_count < 10; gc_count++) {
18303 other_context->Enter();
18304 CompileRun(source_exception);
18305 other_context->Exit();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018306 CcTest::heap()->CollectAllGarbage();
Steve Blockd0582a62009-12-15 09:54:21 +000018307 if (GetGlobalObjectsCount() == 1) break;
18308 }
18309 CHECK_GE(2, gc_count);
18310 CHECK_EQ(1, GetGlobalObjectsCount());
18311
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018312 isolate->ContextDisposedNotification();
Steve Block3ce2e202009-11-05 08:53:23 +000018313}
Andrei Popescu402d9372010-02-26 13:31:12 +000018314
18315
18316THREADED_TEST(ScriptOrigin) {
Andrei Popescu402d9372010-02-26 13:31:12 +000018317 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018318 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018319 v8::ScriptOrigin origin = v8::ScriptOrigin(
18320 v8_str("test"), v8::Integer::New(env->GetIsolate(), 1),
18321 v8::Integer::New(env->GetIsolate(), 1), v8::True(env->GetIsolate()),
18322 v8::Local<v8::Integer>(), v8::True(env->GetIsolate()),
18323 v8_str("http://sourceMapUrl"), v8::True(env->GetIsolate()));
18324 v8::Local<v8::String> script = v8_str("function f() {}\n\nfunction g() {}");
18325 v8::Script::Compile(env.local(), script, &origin)
18326 .ToLocalChecked()
18327 ->Run(env.local())
18328 .ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000018329 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018330 env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
Andrei Popescu402d9372010-02-26 13:31:12 +000018331 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018332 env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
Andrei Popescu402d9372010-02-26 13:31:12 +000018333
18334 v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018335 CHECK_EQ(0, strcmp("test",
18336 *v8::String::Utf8Value(script_origin_f.ResourceName())));
18337 CHECK_EQ(
18338 1,
18339 script_origin_f.ResourceLineOffset()->Int32Value(env.local()).FromJust());
18340 CHECK(script_origin_f.Options().IsSharedCrossOrigin());
18341 CHECK(script_origin_f.Options().IsEmbedderDebugScript());
18342 CHECK(script_origin_f.Options().IsOpaque());
18343 printf("is name = %d\n", script_origin_f.SourceMapUrl()->IsUndefined());
18344
18345 CHECK_EQ(0, strcmp("http://sourceMapUrl",
18346 *v8::String::Utf8Value(script_origin_f.SourceMapUrl())));
Andrei Popescu402d9372010-02-26 13:31:12 +000018347
18348 v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018349 CHECK_EQ(0, strcmp("test",
18350 *v8::String::Utf8Value(script_origin_g.ResourceName())));
18351 CHECK_EQ(
18352 1,
18353 script_origin_g.ResourceLineOffset()->Int32Value(env.local()).FromJust());
18354 CHECK(script_origin_g.Options().IsSharedCrossOrigin());
18355 CHECK(script_origin_g.Options().IsEmbedderDebugScript());
18356 CHECK(script_origin_g.Options().IsOpaque());
18357 CHECK_EQ(0, strcmp("http://sourceMapUrl",
18358 *v8::String::Utf8Value(script_origin_g.SourceMapUrl())));
Andrei Popescu402d9372010-02-26 13:31:12 +000018359}
18360
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018361
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018362THREADED_TEST(FunctionGetInferredName) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018363 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018364 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018365 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
18366 v8::Local<v8::String> script =
18367 v8_str("var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
18368 v8::Script::Compile(env.local(), script, &origin)
18369 .ToLocalChecked()
18370 ->Run(env.local())
18371 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018372 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018373 env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
18374 CHECK_EQ(0,
18375 strcmp("foo.bar.baz", *v8::String::Utf8Value(f->GetInferredName())));
18376}
18377
18378
18379THREADED_TEST(FunctionGetDebugName) {
18380 LocalContext env;
18381 v8::HandleScope scope(env->GetIsolate());
18382 const char* code =
18383 "var error = false;"
18384 "function a() { this.x = 1; };"
18385 "a.displayName = 'display_a';"
18386 "var b = (function() {"
18387 " var f = function() { this.x = 2; };"
18388 " f.displayName = 'display_b';"
18389 " return f;"
18390 "})();"
18391 "var c = function() {};"
18392 "c.__defineGetter__('displayName', function() {"
18393 " error = true;"
18394 " throw new Error();"
18395 "});"
18396 "function d() {};"
18397 "d.__defineGetter__('displayName', function() {"
18398 " error = true;"
18399 " return 'wrong_display_name';"
18400 "});"
18401 "function e() {};"
18402 "e.displayName = 'wrong_display_name';"
18403 "e.__defineSetter__('displayName', function() {"
18404 " error = true;"
18405 " throw new Error();"
18406 "});"
18407 "function f() {};"
18408 "f.displayName = { 'foo': 6, toString: function() {"
18409 " error = true;"
18410 " return 'wrong_display_name';"
18411 "}};"
18412 "var g = function() {"
18413 " arguments.callee.displayName = 'set_in_runtime';"
18414 "}; g();"
18415 "var h = function() {};"
18416 "h.displayName = 'displayName';"
18417 "Object.defineProperty(h, 'name', { value: 'function.name' });"
18418 "var i = function() {};"
18419 "i.displayName = 239;"
18420 "Object.defineProperty(i, 'name', { value: 'function.name' });"
18421 "var j = function() {};"
18422 "Object.defineProperty(j, 'name', { value: 'function.name' });"
18423 "var foo = { bar : { baz : function() {}}}; var k = foo.bar.baz;";
18424 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
18425 v8::Script::Compile(env.local(), v8_str(code), &origin)
18426 .ToLocalChecked()
18427 ->Run(env.local())
18428 .ToLocalChecked();
18429 v8::Local<v8::Value> error =
18430 env->Global()->Get(env.local(), v8_str("error")).ToLocalChecked();
18431 CHECK_EQ(false, error->BooleanValue(env.local()).FromJust());
18432 const char* functions[] = {"a", "display_a",
18433 "b", "display_b",
18434 "c", "c",
18435 "d", "d",
18436 "e", "e",
18437 "f", "f",
18438 "g", "set_in_runtime",
18439 "h", "displayName",
18440 "i", "function.name",
18441 "j", "function.name",
18442 "k", "foo.bar.baz"};
18443 for (size_t i = 0; i < sizeof(functions) / sizeof(functions[0]) / 2; ++i) {
18444 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
18445 env->Global()
18446 ->Get(env.local(),
18447 v8::String::NewFromUtf8(env->GetIsolate(), functions[i * 2],
18448 v8::NewStringType::kNormal)
18449 .ToLocalChecked())
18450 .ToLocalChecked());
18451 CHECK_EQ(0, strcmp(functions[i * 2 + 1],
18452 *v8::String::Utf8Value(f->GetDebugName())));
18453 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018454}
Andrei Popescu402d9372010-02-26 13:31:12 +000018455
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018456
18457THREADED_TEST(FunctionGetDisplayName) {
Andrei Popescu402d9372010-02-26 13:31:12 +000018458 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018459 v8::HandleScope scope(env->GetIsolate());
18460 const char* code = "var error = false;"
18461 "function a() { this.x = 1; };"
18462 "a.displayName = 'display_a';"
18463 "var b = (function() {"
18464 " var f = function() { this.x = 2; };"
18465 " f.displayName = 'display_b';"
18466 " return f;"
18467 "})();"
18468 "var c = function() {};"
18469 "c.__defineGetter__('displayName', function() {"
18470 " error = true;"
18471 " throw new Error();"
18472 "});"
18473 "function d() {};"
18474 "d.__defineGetter__('displayName', function() {"
18475 " error = true;"
18476 " return 'wrong_display_name';"
18477 "});"
18478 "function e() {};"
18479 "e.displayName = 'wrong_display_name';"
18480 "e.__defineSetter__('displayName', function() {"
18481 " error = true;"
18482 " throw new Error();"
18483 "});"
18484 "function f() {};"
18485 "f.displayName = { 'foo': 6, toString: function() {"
18486 " error = true;"
18487 " return 'wrong_display_name';"
18488 "}};"
18489 "var g = function() {"
18490 " arguments.callee.displayName = 'set_in_runtime';"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018491 "}; g();";
18492 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
18493 v8::Script::Compile(env.local(), v8_str(code), &origin)
18494 .ToLocalChecked()
18495 ->Run(env.local())
18496 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018497 v8::Local<v8::Value> error =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018498 env->Global()->Get(env.local(), v8_str("error")).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018499 v8::Local<v8::Function> a = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018500 env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018501 v8::Local<v8::Function> b = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018502 env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018503 v8::Local<v8::Function> c = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018504 env->Global()->Get(env.local(), v8_str("c")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018505 v8::Local<v8::Function> d = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018506 env->Global()->Get(env.local(), v8_str("d")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018507 v8::Local<v8::Function> e = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018508 env->Global()->Get(env.local(), v8_str("e")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018509 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018510 env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018511 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018512 env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
18513 CHECK_EQ(false, error->BooleanValue(env.local()).FromJust());
18514 CHECK_EQ(0, strcmp("display_a", *v8::String::Utf8Value(a->GetDisplayName())));
18515 CHECK_EQ(0, strcmp("display_b", *v8::String::Utf8Value(b->GetDisplayName())));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018516 CHECK(c->GetDisplayName()->IsUndefined());
18517 CHECK(d->GetDisplayName()->IsUndefined());
18518 CHECK(e->GetDisplayName()->IsUndefined());
18519 CHECK(f->GetDisplayName()->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018520 CHECK_EQ(
18521 0, strcmp("set_in_runtime", *v8::String::Utf8Value(g->GetDisplayName())));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018522}
18523
18524
18525THREADED_TEST(ScriptLineNumber) {
18526 LocalContext env;
18527 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018528 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
18529 v8::Local<v8::String> script = v8_str("function f() {}\n\nfunction g() {}");
18530 v8::Script::Compile(env.local(), script, &origin)
18531 .ToLocalChecked()
18532 ->Run(env.local())
18533 .ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000018534 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018535 env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
Andrei Popescu402d9372010-02-26 13:31:12 +000018536 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018537 env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
Andrei Popescu402d9372010-02-26 13:31:12 +000018538 CHECK_EQ(0, f->GetScriptLineNumber());
18539 CHECK_EQ(2, g->GetScriptLineNumber());
18540}
18541
18542
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018543THREADED_TEST(ScriptColumnNumber) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018544 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018545 v8::Isolate* isolate = env->GetIsolate();
18546 v8::HandleScope scope(isolate);
18547 v8::ScriptOrigin origin =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018548 v8::ScriptOrigin(v8_str("test"), v8::Integer::New(isolate, 3),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018549 v8::Integer::New(isolate, 2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018550 v8::Local<v8::String> script =
18551 v8_str("function foo() {}\n\n function bar() {}");
18552 v8::Script::Compile(env.local(), script, &origin)
18553 .ToLocalChecked()
18554 ->Run(env.local())
18555 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018556 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018557 env->Global()->Get(env.local(), v8_str("foo")).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018558 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018559 env->Global()->Get(env.local(), v8_str("bar")).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018560 CHECK_EQ(14, foo->GetScriptColumnNumber());
18561 CHECK_EQ(17, bar->GetScriptColumnNumber());
18562}
18563
18564
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018565THREADED_TEST(FunctionIsBuiltin) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018566 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018567 v8::Isolate* isolate = env->GetIsolate();
18568 v8::HandleScope scope(isolate);
18569 v8::Local<v8::Function> f;
18570 f = v8::Local<v8::Function>::Cast(CompileRun("Math.floor"));
18571 CHECK(f->IsBuiltin());
18572 f = v8::Local<v8::Function>::Cast(CompileRun("Object"));
18573 CHECK(f->IsBuiltin());
18574 f = v8::Local<v8::Function>::Cast(CompileRun("Object.__defineSetter__"));
18575 CHECK(f->IsBuiltin());
18576 f = v8::Local<v8::Function>::Cast(CompileRun("Array.prototype.toString"));
18577 CHECK(f->IsBuiltin());
18578 f = v8::Local<v8::Function>::Cast(CompileRun("function a() {}; a;"));
18579 CHECK(!f->IsBuiltin());
18580}
18581
18582
18583THREADED_TEST(FunctionGetScriptId) {
18584 LocalContext env;
18585 v8::Isolate* isolate = env->GetIsolate();
18586 v8::HandleScope scope(isolate);
18587 v8::ScriptOrigin origin =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018588 v8::ScriptOrigin(v8_str("test"), v8::Integer::New(isolate, 3),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018589 v8::Integer::New(isolate, 2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018590 v8::Local<v8::String> scriptSource =
18591 v8_str("function foo() {}\n\n function bar() {}");
18592 v8::Local<v8::Script> script(
18593 v8::Script::Compile(env.local(), scriptSource, &origin).ToLocalChecked());
18594 script->Run(env.local()).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018595 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018596 env->Global()->Get(env.local(), v8_str("foo")).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018597 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018598 env->Global()->Get(env.local(), v8_str("bar")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018599 CHECK_EQ(script->GetUnboundScript()->GetId(), foo->ScriptId());
18600 CHECK_EQ(script->GetUnboundScript()->GetId(), bar->ScriptId());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018601}
18602
18603
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018604THREADED_TEST(FunctionGetBoundFunction) {
18605 LocalContext env;
18606 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018607 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
18608 v8::Local<v8::String> script = v8_str(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018609 "var a = new Object();\n"
18610 "a.x = 1;\n"
18611 "function f () { return this.x };\n"
18612 "var g = f.bind(a);\n"
18613 "var b = g();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018614 v8::Script::Compile(env.local(), script, &origin)
18615 .ToLocalChecked()
18616 ->Run(env.local())
18617 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018618 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018619 env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018620 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018621 env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018622 CHECK(g->GetBoundFunction()->IsFunction());
18623 Local<v8::Function> original_function = Local<v8::Function>::Cast(
18624 g->GetBoundFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018625 CHECK(f->GetName()
18626 ->Equals(env.local(), original_function->GetName())
18627 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018628 CHECK_EQ(f->GetScriptLineNumber(), original_function->GetScriptLineNumber());
18629 CHECK_EQ(f->GetScriptColumnNumber(),
18630 original_function->GetScriptColumnNumber());
Andrei Popescu402d9372010-02-26 13:31:12 +000018631}
18632
18633
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018634static void GetterWhichReturns42(
18635 Local<String> name,
18636 const v8::PropertyCallbackInfo<v8::Value>& info) {
18637 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18638 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
18639 info.GetReturnValue().Set(v8_num(42));
18640}
18641
18642
18643static void SetterWhichSetsYOnThisTo23(
18644 Local<String> name,
18645 Local<Value> value,
18646 const v8::PropertyCallbackInfo<void>& info) {
18647 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18648 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018649 Local<Object>::Cast(info.This())
18650 ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
18651 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018652}
18653
18654
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018655void FooGetInterceptor(Local<Name> name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018656 const v8::PropertyCallbackInfo<v8::Value>& info) {
18657 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18658 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018659 if (!name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
18660 .FromJust()) {
18661 return;
18662 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018663 info.GetReturnValue().Set(v8_num(42));
18664}
18665
18666
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018667void FooSetInterceptor(Local<Name> name, Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018668 const v8::PropertyCallbackInfo<v8::Value>& info) {
18669 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18670 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018671 if (!name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
18672 .FromJust()) {
18673 return;
18674 }
18675 Local<Object>::Cast(info.This())
18676 ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
18677 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018678 info.GetReturnValue().Set(v8_num(23));
Andrei Popescu402d9372010-02-26 13:31:12 +000018679}
18680
18681
Steve Block6ded16b2010-05-10 14:33:55 +010018682TEST(SetterOnConstructorPrototype) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018683 v8::Isolate* isolate = CcTest::isolate();
18684 v8::HandleScope scope(isolate);
18685 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
18686 templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
Andrei Popescu402d9372010-02-26 13:31:12 +000018687 SetterWhichSetsYOnThisTo23);
18688 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018689 CHECK(context->Global()
18690 ->Set(context.local(), v8_str("P"),
18691 templ->NewInstance(context.local()).ToLocalChecked())
18692 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018693 CompileRun("function C1() {"
18694 " this.x = 23;"
18695 "};"
18696 "C1.prototype = P;"
18697 "function C2() {"
18698 " this.x = 23"
18699 "};"
18700 "C2.prototype = { };"
18701 "C2.prototype.__proto__ = P;");
18702
18703 v8::Local<v8::Script> script;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018704 script = v8_compile("new C1();");
Andrei Popescu402d9372010-02-26 13:31:12 +000018705 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018706 v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
18707 script->Run(context.local()).ToLocalChecked());
18708 CHECK_EQ(42, c1->Get(context.local(), v8_str("x"))
18709 .ToLocalChecked()
18710 ->Int32Value(context.local())
18711 .FromJust());
18712 CHECK_EQ(23, c1->Get(context.local(), v8_str("y"))
18713 .ToLocalChecked()
18714 ->Int32Value(context.local())
18715 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018716 }
18717
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018718 script = v8_compile("new C2();");
Andrei Popescu402d9372010-02-26 13:31:12 +000018719 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018720 v8::Local<v8::Object> c2 = v8::Local<v8::Object>::Cast(
18721 script->Run(context.local()).ToLocalChecked());
18722 CHECK_EQ(42, c2->Get(context.local(), v8_str("x"))
18723 .ToLocalChecked()
18724 ->Int32Value(context.local())
18725 .FromJust());
18726 CHECK_EQ(23, c2->Get(context.local(), v8_str("y"))
18727 .ToLocalChecked()
18728 ->Int32Value(context.local())
18729 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018730 }
18731}
18732
18733
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018734static void NamedPropertyGetterWhichReturns42(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018735 Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018736 info.GetReturnValue().Set(v8_num(42));
Andrei Popescu402d9372010-02-26 13:31:12 +000018737}
18738
18739
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018740static void NamedPropertySetterWhichSetsYOnThisTo23(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018741 Local<Name> name, Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018742 const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018743 if (name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("x"))
18744 .FromJust()) {
18745 Local<Object>::Cast(info.This())
18746 ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
18747 .FromJust();
Andrei Popescu402d9372010-02-26 13:31:12 +000018748 }
Andrei Popescu402d9372010-02-26 13:31:12 +000018749}
18750
18751
18752THREADED_TEST(InterceptorOnConstructorPrototype) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018753 v8::Isolate* isolate = CcTest::isolate();
18754 v8::HandleScope scope(isolate);
18755 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018756 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
18757 NamedPropertyGetterWhichReturns42,
18758 NamedPropertySetterWhichSetsYOnThisTo23));
Andrei Popescu402d9372010-02-26 13:31:12 +000018759 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018760 CHECK(context->Global()
18761 ->Set(context.local(), v8_str("P"),
18762 templ->NewInstance(context.local()).ToLocalChecked())
18763 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018764 CompileRun("function C1() {"
18765 " this.x = 23;"
18766 "};"
18767 "C1.prototype = P;"
18768 "function C2() {"
18769 " this.x = 23"
18770 "};"
18771 "C2.prototype = { };"
18772 "C2.prototype.__proto__ = P;");
18773
18774 v8::Local<v8::Script> script;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018775 script = v8_compile("new C1();");
Andrei Popescu402d9372010-02-26 13:31:12 +000018776 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018777 v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
18778 script->Run(context.local()).ToLocalChecked());
18779 CHECK_EQ(23, c1->Get(context.local(), v8_str("x"))
18780 .ToLocalChecked()
18781 ->Int32Value(context.local())
18782 .FromJust());
18783 CHECK_EQ(42, c1->Get(context.local(), v8_str("y"))
18784 .ToLocalChecked()
18785 ->Int32Value(context.local())
18786 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018787 }
18788
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018789 script = v8_compile("new C2();");
Andrei Popescu402d9372010-02-26 13:31:12 +000018790 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018791 v8::Local<v8::Object> c2 = v8::Local<v8::Object>::Cast(
18792 script->Run(context.local()).ToLocalChecked());
18793 CHECK_EQ(23, c2->Get(context.local(), v8_str("x"))
18794 .ToLocalChecked()
18795 ->Int32Value(context.local())
18796 .FromJust());
18797 CHECK_EQ(42, c2->Get(context.local(), v8_str("y"))
18798 .ToLocalChecked()
18799 ->Int32Value(context.local())
18800 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018801 }
18802}
Steve Block6ded16b2010-05-10 14:33:55 +010018803
18804
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018805TEST(Regress618) {
Steve Block6ded16b2010-05-10 14:33:55 +010018806 const char* source = "function C1() {"
18807 " this.x = 23;"
18808 "};"
18809 "C1.prototype = P;";
18810
Steve Block6ded16b2010-05-10 14:33:55 +010018811 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018812 v8::Isolate* isolate = context->GetIsolate();
18813 v8::HandleScope scope(isolate);
Steve Block6ded16b2010-05-10 14:33:55 +010018814 v8::Local<v8::Script> script;
18815
18816 // Use a simple object as prototype.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018817 v8::Local<v8::Object> prototype = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018818 prototype->Set(context.local(), v8_str("y"), v8_num(42)).FromJust();
18819 CHECK(context->Global()
18820 ->Set(context.local(), v8_str("P"), prototype)
18821 .FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +010018822
18823 // This compile will add the code to the compilation cache.
18824 CompileRun(source);
18825
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018826 script = v8_compile("new C1();");
Kristian Monsen0d5e1162010-09-30 15:31:59 +010018827 // Allow enough iterations for the inobject slack tracking logic
18828 // to finalize instance size and install the fast construct stub.
18829 for (int i = 0; i < 256; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018830 v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
18831 script->Run(context.local()).ToLocalChecked());
18832 CHECK_EQ(23, c1->Get(context.local(), v8_str("x"))
18833 .ToLocalChecked()
18834 ->Int32Value(context.local())
18835 .FromJust());
18836 CHECK_EQ(42, c1->Get(context.local(), v8_str("y"))
18837 .ToLocalChecked()
18838 ->Int32Value(context.local())
18839 .FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +010018840 }
18841
18842 // Use an API object with accessors as prototype.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018843 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
18844 templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
Steve Block6ded16b2010-05-10 14:33:55 +010018845 SetterWhichSetsYOnThisTo23);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018846 CHECK(context->Global()
18847 ->Set(context.local(), v8_str("P"),
18848 templ->NewInstance(context.local()).ToLocalChecked())
18849 .FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +010018850
18851 // This compile will get the code from the compilation cache.
18852 CompileRun(source);
18853
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018854 script = v8_compile("new C1();");
Steve Block6ded16b2010-05-10 14:33:55 +010018855 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018856 v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
18857 script->Run(context.local()).ToLocalChecked());
18858 CHECK_EQ(42, c1->Get(context.local(), v8_str("x"))
18859 .ToLocalChecked()
18860 ->Int32Value(context.local())
18861 .FromJust());
18862 CHECK_EQ(23, c1->Get(context.local(), v8_str("y"))
18863 .ToLocalChecked()
18864 ->Int32Value(context.local())
18865 .FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +010018866 }
18867}
18868
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018869v8::Isolate* gc_callbacks_isolate = NULL;
Steve Block6ded16b2010-05-10 14:33:55 +010018870int prologue_call_count = 0;
18871int epilogue_call_count = 0;
18872int prologue_call_count_second = 0;
18873int epilogue_call_count_second = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018874int prologue_call_count_alloc = 0;
18875int epilogue_call_count_alloc = 0;
Steve Block6ded16b2010-05-10 14:33:55 +010018876
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018877void PrologueCallback(v8::Isolate* isolate,
18878 v8::GCType,
18879 v8::GCCallbackFlags flags) {
18880 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18881 CHECK_EQ(gc_callbacks_isolate, isolate);
18882 ++prologue_call_count;
18883}
18884
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018885void EpilogueCallback(v8::Isolate* isolate,
18886 v8::GCType,
18887 v8::GCCallbackFlags flags) {
18888 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18889 CHECK_EQ(gc_callbacks_isolate, isolate);
18890 ++epilogue_call_count;
18891}
18892
18893
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018894void PrologueCallbackSecond(v8::Isolate* isolate,
18895 v8::GCType,
18896 v8::GCCallbackFlags flags) {
18897 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18898 CHECK_EQ(gc_callbacks_isolate, isolate);
18899 ++prologue_call_count_second;
18900}
18901
18902
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018903void EpilogueCallbackSecond(v8::Isolate* isolate,
18904 v8::GCType,
18905 v8::GCCallbackFlags flags) {
18906 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18907 CHECK_EQ(gc_callbacks_isolate, isolate);
18908 ++epilogue_call_count_second;
18909}
18910
18911
18912void PrologueCallbackAlloc(v8::Isolate* isolate,
18913 v8::GCType,
18914 v8::GCCallbackFlags flags) {
18915 v8::HandleScope scope(isolate);
18916
18917 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18918 CHECK_EQ(gc_callbacks_isolate, isolate);
18919 ++prologue_call_count_alloc;
18920
18921 // Simulate full heap to see if we will reenter this callback
18922 SimulateFullSpace(CcTest::heap()->new_space());
18923
18924 Local<Object> obj = Object::New(isolate);
18925 CHECK(!obj.IsEmpty());
18926
18927 CcTest::heap()->CollectAllGarbage(
18928 i::Heap::kAbortIncrementalMarkingMask);
18929}
18930
18931
18932void EpilogueCallbackAlloc(v8::Isolate* isolate,
18933 v8::GCType,
18934 v8::GCCallbackFlags flags) {
18935 v8::HandleScope scope(isolate);
18936
18937 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18938 CHECK_EQ(gc_callbacks_isolate, isolate);
18939 ++epilogue_call_count_alloc;
18940
18941 // Simulate full heap to see if we will reenter this callback
18942 SimulateFullSpace(CcTest::heap()->new_space());
18943
18944 Local<Object> obj = Object::New(isolate);
18945 CHECK(!obj.IsEmpty());
18946
18947 CcTest::heap()->CollectAllGarbage(
18948 i::Heap::kAbortIncrementalMarkingMask);
18949}
18950
18951
18952TEST(GCCallbacksOld) {
Steve Block6ded16b2010-05-10 14:33:55 +010018953 LocalContext context;
18954
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018955 gc_callbacks_isolate = context->GetIsolate();
18956
18957 context->GetIsolate()->AddGCPrologueCallback(PrologueCallback);
18958 context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallback);
Steve Block6ded16b2010-05-10 14:33:55 +010018959 CHECK_EQ(0, prologue_call_count);
18960 CHECK_EQ(0, epilogue_call_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018961 CcTest::heap()->CollectAllGarbage();
Steve Block6ded16b2010-05-10 14:33:55 +010018962 CHECK_EQ(1, prologue_call_count);
18963 CHECK_EQ(1, epilogue_call_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018964 context->GetIsolate()->AddGCPrologueCallback(PrologueCallbackSecond);
18965 context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallbackSecond);
18966 CcTest::heap()->CollectAllGarbage();
Steve Block6ded16b2010-05-10 14:33:55 +010018967 CHECK_EQ(2, prologue_call_count);
18968 CHECK_EQ(2, epilogue_call_count);
18969 CHECK_EQ(1, prologue_call_count_second);
18970 CHECK_EQ(1, epilogue_call_count_second);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018971 context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallback);
18972 context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallback);
18973 CcTest::heap()->CollectAllGarbage();
Steve Block6ded16b2010-05-10 14:33:55 +010018974 CHECK_EQ(2, prologue_call_count);
18975 CHECK_EQ(2, epilogue_call_count);
18976 CHECK_EQ(2, prologue_call_count_second);
18977 CHECK_EQ(2, epilogue_call_count_second);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018978 context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallbackSecond);
18979 context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
18980 CcTest::heap()->CollectAllGarbage();
Steve Block6ded16b2010-05-10 14:33:55 +010018981 CHECK_EQ(2, prologue_call_count);
18982 CHECK_EQ(2, epilogue_call_count);
18983 CHECK_EQ(2, prologue_call_count_second);
18984 CHECK_EQ(2, epilogue_call_count_second);
18985}
Kristian Monsen25f61362010-05-21 11:50:48 +010018986
18987
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018988TEST(GCCallbacks) {
18989 LocalContext context;
18990 v8::Isolate* isolate = context->GetIsolate();
18991 gc_callbacks_isolate = isolate;
18992 isolate->AddGCPrologueCallback(PrologueCallback);
18993 isolate->AddGCEpilogueCallback(EpilogueCallback);
18994 CHECK_EQ(0, prologue_call_count);
18995 CHECK_EQ(0, epilogue_call_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018996 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018997 CHECK_EQ(1, prologue_call_count);
18998 CHECK_EQ(1, epilogue_call_count);
18999 isolate->AddGCPrologueCallback(PrologueCallbackSecond);
19000 isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019001 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019002 CHECK_EQ(2, prologue_call_count);
19003 CHECK_EQ(2, epilogue_call_count);
19004 CHECK_EQ(1, prologue_call_count_second);
19005 CHECK_EQ(1, epilogue_call_count_second);
19006 isolate->RemoveGCPrologueCallback(PrologueCallback);
19007 isolate->RemoveGCEpilogueCallback(EpilogueCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019008 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019009 CHECK_EQ(2, prologue_call_count);
19010 CHECK_EQ(2, epilogue_call_count);
19011 CHECK_EQ(2, prologue_call_count_second);
19012 CHECK_EQ(2, epilogue_call_count_second);
19013 isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
19014 isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019015 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019016 CHECK_EQ(2, prologue_call_count);
19017 CHECK_EQ(2, epilogue_call_count);
19018 CHECK_EQ(2, prologue_call_count_second);
19019 CHECK_EQ(2, epilogue_call_count_second);
19020
19021 CHECK_EQ(0, prologue_call_count_alloc);
19022 CHECK_EQ(0, epilogue_call_count_alloc);
19023 isolate->AddGCPrologueCallback(PrologueCallbackAlloc);
19024 isolate->AddGCEpilogueCallback(EpilogueCallbackAlloc);
19025 CcTest::heap()->CollectAllGarbage(
19026 i::Heap::kAbortIncrementalMarkingMask);
19027 CHECK_EQ(1, prologue_call_count_alloc);
19028 CHECK_EQ(1, epilogue_call_count_alloc);
19029 isolate->RemoveGCPrologueCallback(PrologueCallbackAlloc);
19030 isolate->RemoveGCEpilogueCallback(EpilogueCallbackAlloc);
19031}
19032
19033
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019034THREADED_TEST(TwoByteStringInOneByteCons) {
Steve Block8defd9f2010-07-08 12:39:36 +010019035 // See Chromium issue 47824.
Steve Block8defd9f2010-07-08 12:39:36 +010019036 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019037 v8::HandleScope scope(context->GetIsolate());
19038
Steve Block8defd9f2010-07-08 12:39:36 +010019039 const char* init_code =
19040 "var str1 = 'abelspendabel';"
19041 "var str2 = str1 + str1 + str1;"
19042 "str2;";
19043 Local<Value> result = CompileRun(init_code);
19044
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019045 Local<Value> indexof = CompileRun("str2.indexOf('els')");
19046 Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
19047
Steve Block8defd9f2010-07-08 12:39:36 +010019048 CHECK(result->IsString());
19049 i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
19050 int length = string->length();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019051 CHECK(string->IsOneByteRepresentation());
Steve Block8defd9f2010-07-08 12:39:36 +010019052
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019053 i::Handle<i::String> flat_string = i::String::Flatten(string);
Steve Block8defd9f2010-07-08 12:39:36 +010019054
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019055 CHECK(string->IsOneByteRepresentation());
19056 CHECK(flat_string->IsOneByteRepresentation());
Steve Block8defd9f2010-07-08 12:39:36 +010019057
19058 // Create external resource.
19059 uint16_t* uc16_buffer = new uint16_t[length + 1];
19060
19061 i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
19062 uc16_buffer[length] = 0;
19063
19064 TestResource resource(uc16_buffer);
19065
19066 flat_string->MakeExternal(&resource);
19067
19068 CHECK(flat_string->IsTwoByteRepresentation());
19069
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019070 // If the cons string has been short-circuited, skip the following checks.
19071 if (!string.is_identical_to(flat_string)) {
19072 // At this point, we should have a Cons string which is flat and one-byte,
19073 // with a first half that is a two-byte string (although it only contains
19074 // one-byte characters). This is a valid sequence of steps, and it can
19075 // happen in real pages.
19076 CHECK(string->IsOneByteRepresentation());
19077 i::ConsString* cons = i::ConsString::cast(*string);
19078 CHECK_EQ(0, cons->second()->length());
19079 CHECK(cons->first()->IsTwoByteRepresentation());
19080 }
Steve Block8defd9f2010-07-08 12:39:36 +010019081
19082 // Check that some string operations work.
19083
19084 // Atom RegExp.
19085 Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019086 CHECK_EQ(6, reresult->Int32Value(context.local()).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +010019087
19088 // Nonatom RegExp.
19089 reresult = CompileRun("str2.match(/abe./g).length;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019090 CHECK_EQ(6, reresult->Int32Value(context.local()).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +010019091
19092 reresult = CompileRun("str2.search(/bel/g);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019093 CHECK_EQ(1, reresult->Int32Value(context.local()).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +010019094
19095 reresult = CompileRun("str2.search(/be./g);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019096 CHECK_EQ(1, reresult->Int32Value(context.local()).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +010019097
19098 ExpectTrue("/bel/g.test(str2);");
19099
19100 ExpectTrue("/be./g.test(str2);");
19101
19102 reresult = CompileRun("/bel/g.exec(str2);");
19103 CHECK(!reresult->IsNull());
19104
19105 reresult = CompileRun("/be./g.exec(str2);");
19106 CHECK(!reresult->IsNull());
19107
19108 ExpectString("str2.substring(2, 10);", "elspenda");
19109
19110 ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
19111
19112 ExpectString("str2.charAt(2);", "e");
19113
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019114 ExpectObject("str2.indexOf('els');", indexof);
19115
19116 ExpectObject("str2.lastIndexOf('dab');", lastindexof);
19117
Steve Block8defd9f2010-07-08 12:39:36 +010019118 reresult = CompileRun("str2.charCodeAt(2);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019119 CHECK_EQ(static_cast<int32_t>('e'),
19120 reresult->Int32Value(context.local()).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +010019121}
Iain Merrick75681382010-08-19 15:07:18 +010019122
19123
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019124TEST(ContainsOnlyOneByte) {
19125 v8::V8::Initialize();
19126 v8::Isolate* isolate = CcTest::isolate();
19127 v8::HandleScope scope(isolate);
19128 // Make a buffer long enough that it won't automatically be converted.
19129 const int length = 512;
19130 // Ensure word aligned assignment.
19131 const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019132 v8::base::SmartArrayPointer<uintptr_t> aligned_contents(
19133 new uintptr_t[aligned_length]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019134 uint16_t* string_contents =
19135 reinterpret_cast<uint16_t*>(aligned_contents.get());
19136 // Set to contain only one byte.
19137 for (int i = 0; i < length-1; i++) {
19138 string_contents[i] = 0x41;
19139 }
19140 string_contents[length-1] = 0;
19141 // Simple case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019142 Local<String> string =
19143 String::NewExternalTwoByte(isolate,
19144 new TestResource(string_contents, NULL, false))
19145 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019146 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
19147 // Counter example.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019148 string = String::NewFromTwoByte(isolate, string_contents,
19149 v8::NewStringType::kNormal)
19150 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019151 CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
19152 // Test left right and balanced cons strings.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019153 Local<String> base = v8_str("a");
19154 Local<String> left = base;
19155 Local<String> right = base;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019156 for (int i = 0; i < 1000; i++) {
19157 left = String::Concat(base, left);
19158 right = String::Concat(right, base);
19159 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019160 Local<String> balanced = String::Concat(left, base);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019161 balanced = String::Concat(balanced, right);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019162 Local<String> cons_strings[] = {left, balanced, right};
19163 Local<String> two_byte =
19164 String::NewExternalTwoByte(isolate,
19165 new TestResource(string_contents, NULL, false))
19166 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019167 USE(two_byte); USE(cons_strings);
19168 for (size_t i = 0; i < arraysize(cons_strings); i++) {
19169 // Base assumptions.
19170 string = cons_strings[i];
19171 CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
19172 // Test left and right concatentation.
19173 string = String::Concat(two_byte, cons_strings[i]);
19174 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
19175 string = String::Concat(cons_strings[i], two_byte);
19176 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
19177 }
19178 // Set bits in different positions
19179 // for strings of different lengths and alignments.
19180 for (int alignment = 0; alignment < 7; alignment++) {
19181 for (int size = 2; alignment + size < length; size *= 2) {
19182 int zero_offset = size + alignment;
19183 string_contents[zero_offset] = 0;
19184 for (int i = 0; i < size; i++) {
19185 int shift = 8 + (i % 7);
19186 string_contents[alignment + i] = 1 << shift;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019187 string = String::NewExternalTwoByte(
19188 isolate,
19189 new TestResource(string_contents + alignment, NULL, false))
19190 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019191 CHECK_EQ(size, string->Length());
19192 CHECK(!string->ContainsOnlyOneByte());
19193 string_contents[alignment + i] = 0x41;
19194 }
19195 string_contents[zero_offset] = 0x41;
19196 }
19197 }
19198}
19199
19200
Iain Merrick75681382010-08-19 15:07:18 +010019201// Failed access check callback that performs a GC on each invocation.
19202void FailedAccessCheckCallbackGC(Local<v8::Object> target,
19203 v8::AccessType type,
19204 Local<v8::Value> data) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019205 CcTest::heap()->CollectAllGarbage();
19206 CcTest::isolate()->ThrowException(
19207 v8::Exception::Error(v8_str("cross context")));
Iain Merrick75681382010-08-19 15:07:18 +010019208}
19209
19210
19211TEST(GCInFailedAccessCheckCallback) {
19212 // Install a failed access check callback that performs a GC on each
19213 // invocation. Then force the callback to be called from va
19214
19215 v8::V8::Initialize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019216 v8::Isolate* isolate = CcTest::isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019217
19218 isolate->SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
19219
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019220 v8::HandleScope scope(isolate);
Iain Merrick75681382010-08-19 15:07:18 +010019221
19222 // Create an ObjectTemplate for global objects and install access
19223 // check callbacks that will block access.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019224 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019225 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019226 global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Iain Merrick75681382010-08-19 15:07:18 +010019227
19228 // Create a context and set an x property on it's global object.
19229 LocalContext context0(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019230 CHECK(context0->Global()
19231 ->Set(context0.local(), v8_str("x"), v8_num(42))
19232 .FromJust());
19233 v8::Local<v8::Object> global0 = context0->Global();
Iain Merrick75681382010-08-19 15:07:18 +010019234
19235 // Create a context with a different security token so that the
19236 // failed access check callback will be called on each access.
19237 LocalContext context1(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019238 CHECK(context1->Global()
19239 ->Set(context1.local(), v8_str("other"), global0)
19240 .FromJust());
19241
19242 v8::TryCatch try_catch(isolate);
Iain Merrick75681382010-08-19 15:07:18 +010019243
19244 // Get property with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019245 CHECK(CompileRun("other.x").IsEmpty());
19246 CHECK(try_catch.HasCaught());
19247 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019248
19249 // Get element with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019250 CHECK(CompileRun("other[0]").IsEmpty());
19251 CHECK(try_catch.HasCaught());
19252 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019253
19254 // Set property with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019255 CHECK(CompileRun("other.x = new Object()").IsEmpty());
19256 CHECK(try_catch.HasCaught());
19257 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019258
19259 // Set element with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019260 CHECK(CompileRun("other[0] = new Object()").IsEmpty());
19261 CHECK(try_catch.HasCaught());
19262 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019263
19264 // Get property attribute with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019265 CHECK(CompileRun("\'x\' in other").IsEmpty());
19266 CHECK(try_catch.HasCaught());
19267 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019268
19269 // Get property attribute for element with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019270 CHECK(CompileRun("0 in other").IsEmpty());
19271 CHECK(try_catch.HasCaught());
19272 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019273
19274 // Delete property.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019275 CHECK(CompileRun("delete other.x").IsEmpty());
19276 CHECK(try_catch.HasCaught());
19277 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019278
19279 // Delete element.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019280 CHECK(global0->Delete(context1.local(), 0).IsNothing());
19281 CHECK(try_catch.HasCaught());
19282 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019283
19284 // DefineAccessor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019285 CHECK(global0->SetAccessor(context1.local(), v8_str("x"), GetXValue, NULL,
19286 v8_str("x"))
19287 .IsNothing());
19288 CHECK(try_catch.HasCaught());
19289 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019290
19291 // Define JavaScript accessor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019292 CHECK(CompileRun(
19293 "Object.prototype.__defineGetter__.call("
19294 " other, \'x\', function() { return 42; })").IsEmpty());
19295 CHECK(try_catch.HasCaught());
19296 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019297
19298 // LookupAccessor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019299 CHECK(CompileRun(
19300 "Object.prototype.__lookupGetter__.call("
19301 " other, \'x\')").IsEmpty());
19302 CHECK(try_catch.HasCaught());
19303 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019304
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019305 // HasOwnElement.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019306 CHECK(CompileRun(
19307 "Object.prototype.hasOwnProperty.call("
19308 "other, \'0\')").IsEmpty());
19309 CHECK(try_catch.HasCaught());
19310 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019311
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019312 CHECK(global0->HasRealIndexedProperty(context1.local(), 0).IsNothing());
19313 CHECK(try_catch.HasCaught());
19314 try_catch.Reset();
19315
19316 CHECK(
19317 global0->HasRealNamedProperty(context1.local(), v8_str("x")).IsNothing());
19318 CHECK(try_catch.HasCaught());
19319 try_catch.Reset();
19320
19321 CHECK(global0->HasRealNamedCallbackProperty(context1.local(), v8_str("x"))
19322 .IsNothing());
19323 CHECK(try_catch.HasCaught());
19324 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019325
19326 // Reset the failed access check callback so it does not influence
19327 // the other tests.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019328 isolate->SetFailedAccessCheckCallbackFunction(NULL);
Iain Merrick75681382010-08-19 15:07:18 +010019329}
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019330
Steve Block44f0eee2011-05-26 01:26:41 +010019331
19332TEST(IsolateNewDispose) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019333 v8::Isolate* current_isolate = CcTest::isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019334 v8::Isolate::CreateParams create_params;
19335 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19336 v8::Isolate* isolate = v8::Isolate::New(create_params);
Steve Block44f0eee2011-05-26 01:26:41 +010019337 CHECK(isolate != NULL);
Steve Block44f0eee2011-05-26 01:26:41 +010019338 CHECK(current_isolate != isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019339 CHECK(current_isolate == CcTest::isolate());
Steve Block44f0eee2011-05-26 01:26:41 +010019340
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019341 isolate->SetFatalErrorHandler(StoringErrorCallback);
Steve Block44f0eee2011-05-26 01:26:41 +010019342 last_location = last_message = NULL;
19343 isolate->Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019344 CHECK(!last_location);
19345 CHECK(!last_message);
Steve Block44f0eee2011-05-26 01:26:41 +010019346}
19347
Steve Block44f0eee2011-05-26 01:26:41 +010019348
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019349UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019350 v8::Isolate::CreateParams create_params;
19351 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19352 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019353 {
19354 v8::Isolate::Scope i_scope(isolate);
19355 v8::HandleScope scope(isolate);
19356 LocalContext context(isolate);
19357 // Run something in this isolate.
19358 ExpectTrue("true");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019359 isolate->SetFatalErrorHandler(StoringErrorCallback);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019360 last_location = last_message = NULL;
19361 // Still entered, should fail.
19362 isolate->Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019363 CHECK(last_location);
19364 CHECK(last_message);
Steve Block44f0eee2011-05-26 01:26:41 +010019365 }
Steve Block44f0eee2011-05-26 01:26:41 +010019366 isolate->Dispose();
Steve Block44f0eee2011-05-26 01:26:41 +010019367}
19368
Steve Block44f0eee2011-05-26 01:26:41 +010019369
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019370static void BreakArrayGuarantees(const char* script) {
19371 v8::Isolate::CreateParams create_params;
19372 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19373 v8::Isolate* isolate1 = v8::Isolate::New(create_params);
19374 isolate1->Enter();
19375 v8::Persistent<v8::Context> context1;
19376 {
19377 v8::HandleScope scope(isolate1);
19378 context1.Reset(isolate1, Context::New(isolate1));
19379 }
19380
19381 {
19382 v8::HandleScope scope(isolate1);
19383 v8::Local<v8::Context> context =
19384 v8::Local<v8::Context>::New(isolate1, context1);
19385 v8::Context::Scope context_scope(context);
19386 v8::internal::Isolate* i_isolate =
19387 reinterpret_cast<v8::internal::Isolate*>(isolate1);
19388 CHECK_EQ(true, i_isolate->IsFastArrayConstructorPrototypeChainIntact());
19389 // Run something in new isolate.
19390 CompileRun(script);
19391 CHECK_EQ(false, i_isolate->IsFastArrayConstructorPrototypeChainIntact());
19392 }
19393 isolate1->Exit();
19394 isolate1->Dispose();
19395}
19396
19397
19398TEST(VerifyArrayPrototypeGuarantees) {
19399 // Break fast array hole handling by element changes.
19400 BreakArrayGuarantees("[].__proto__[1] = 3;");
19401 BreakArrayGuarantees("Object.prototype[3] = 'three';");
19402 BreakArrayGuarantees("Array.prototype.push(1);");
19403 BreakArrayGuarantees("Array.prototype.unshift(1);");
19404 // Break fast array hole handling by changing length.
19405 BreakArrayGuarantees("Array.prototype.length = 30;");
19406 // Break fast array hole handling by prototype structure changes.
19407 BreakArrayGuarantees("[].__proto__.__proto__ = { funny: true };");
19408 // By sending elements to dictionary mode.
19409 BreakArrayGuarantees(
19410 "Object.defineProperty(Array.prototype, 0, {"
19411 " get: function() { return 3; }});");
19412 BreakArrayGuarantees(
19413 "Object.defineProperty(Object.prototype, 0, {"
19414 " get: function() { return 3; }});");
19415}
19416
19417
Steve Block44f0eee2011-05-26 01:26:41 +010019418TEST(RunTwoIsolatesOnSingleThread) {
19419 // Run isolate 1.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019420 v8::Isolate::CreateParams create_params;
19421 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19422 v8::Isolate* isolate1 = v8::Isolate::New(create_params);
Steve Block44f0eee2011-05-26 01:26:41 +010019423 isolate1->Enter();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019424 v8::Persistent<v8::Context> context1;
19425 {
19426 v8::HandleScope scope(isolate1);
19427 context1.Reset(isolate1, Context::New(isolate1));
19428 }
Steve Block44f0eee2011-05-26 01:26:41 +010019429
19430 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019431 v8::HandleScope scope(isolate1);
19432 v8::Local<v8::Context> context =
19433 v8::Local<v8::Context>::New(isolate1, context1);
19434 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019435 // Run something in new isolate.
19436 CompileRun("var foo = 'isolate 1';");
19437 ExpectString("function f() { return foo; }; f()", "isolate 1");
19438 }
19439
19440 // Run isolate 2.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019441 v8::Isolate* isolate2 = v8::Isolate::New(create_params);
Steve Block44f0eee2011-05-26 01:26:41 +010019442 v8::Persistent<v8::Context> context2;
19443
19444 {
19445 v8::Isolate::Scope iscope(isolate2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019446 v8::HandleScope scope(isolate2);
19447 context2.Reset(isolate2, Context::New(isolate2));
19448 v8::Local<v8::Context> context =
19449 v8::Local<v8::Context>::New(isolate2, context2);
19450 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019451
19452 // Run something in new isolate.
19453 CompileRun("var foo = 'isolate 2';");
19454 ExpectString("function f() { return foo; }; f()", "isolate 2");
19455 }
19456
19457 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019458 v8::HandleScope scope(isolate1);
19459 v8::Local<v8::Context> context =
19460 v8::Local<v8::Context>::New(isolate1, context1);
19461 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019462 // Now again in isolate 1
19463 ExpectString("function f() { return foo; }; f()", "isolate 1");
19464 }
19465
19466 isolate1->Exit();
19467
19468 // Run some stuff in default isolate.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019469 v8::Persistent<v8::Context> context_default;
19470 {
19471 v8::Isolate* isolate = CcTest::isolate();
19472 v8::Isolate::Scope iscope(isolate);
19473 v8::HandleScope scope(isolate);
19474 context_default.Reset(isolate, Context::New(isolate));
19475 }
Steve Block44f0eee2011-05-26 01:26:41 +010019476
19477 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019478 v8::HandleScope scope(CcTest::isolate());
19479 v8::Local<v8::Context> context =
19480 v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
19481 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019482 // Variables in other isolates should be not available, verify there
19483 // is an exception.
19484 ExpectTrue("function f() {"
19485 " try {"
19486 " foo;"
19487 " return false;"
19488 " } catch(e) {"
19489 " return true;"
19490 " }"
19491 "};"
19492 "var isDefaultIsolate = true;"
19493 "f()");
19494 }
19495
19496 isolate1->Enter();
19497
19498 {
19499 v8::Isolate::Scope iscope(isolate2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019500 v8::HandleScope scope(isolate2);
19501 v8::Local<v8::Context> context =
19502 v8::Local<v8::Context>::New(isolate2, context2);
19503 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019504 ExpectString("function f() { return foo; }; f()", "isolate 2");
19505 }
19506
19507 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019508 v8::HandleScope scope(v8::Isolate::GetCurrent());
19509 v8::Local<v8::Context> context =
19510 v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
19511 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019512 ExpectString("function f() { return foo; }; f()", "isolate 1");
19513 }
19514
19515 {
19516 v8::Isolate::Scope iscope(isolate2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019517 context2.Reset();
Steve Block44f0eee2011-05-26 01:26:41 +010019518 }
19519
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019520 context1.Reset();
Steve Block44f0eee2011-05-26 01:26:41 +010019521 isolate1->Exit();
19522
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019523 isolate2->SetFatalErrorHandler(StoringErrorCallback);
Steve Block44f0eee2011-05-26 01:26:41 +010019524 last_location = last_message = NULL;
19525
19526 isolate1->Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019527 CHECK(!last_location);
19528 CHECK(!last_message);
Steve Block44f0eee2011-05-26 01:26:41 +010019529
19530 isolate2->Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019531 CHECK(!last_location);
19532 CHECK(!last_message);
Steve Block44f0eee2011-05-26 01:26:41 +010019533
19534 // Check that default isolate still runs.
19535 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019536 v8::HandleScope scope(CcTest::isolate());
19537 v8::Local<v8::Context> context =
19538 v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
19539 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019540 ExpectTrue("function f() { return isDefaultIsolate; }; f()");
19541 }
19542}
19543
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019544
Steve Block44f0eee2011-05-26 01:26:41 +010019545static int CalcFibonacci(v8::Isolate* isolate, int limit) {
19546 v8::Isolate::Scope isolate_scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019547 v8::HandleScope scope(isolate);
19548 LocalContext context(isolate);
Steve Block44f0eee2011-05-26 01:26:41 +010019549 i::ScopedVector<char> code(1024);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019550 i::SNPrintF(code, "function fib(n) {"
19551 " if (n <= 2) return 1;"
19552 " return fib(n-1) + fib(n-2);"
19553 "}"
19554 "fib(%d)", limit);
Steve Block44f0eee2011-05-26 01:26:41 +010019555 Local<Value> value = CompileRun(code.start());
19556 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019557 return static_cast<int>(value->NumberValue(context.local()).FromJust());
Steve Block44f0eee2011-05-26 01:26:41 +010019558}
19559
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019560class IsolateThread : public v8::base::Thread {
Steve Block44f0eee2011-05-26 01:26:41 +010019561 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019562 explicit IsolateThread(int fib_limit)
19563 : Thread(Options("IsolateThread")), fib_limit_(fib_limit), result_(0) {}
Steve Block44f0eee2011-05-26 01:26:41 +010019564
19565 void Run() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019566 v8::Isolate::CreateParams create_params;
19567 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19568 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019569 result_ = CalcFibonacci(isolate, fib_limit_);
19570 isolate->Dispose();
Steve Block44f0eee2011-05-26 01:26:41 +010019571 }
19572
19573 int result() { return result_; }
19574
19575 private:
Steve Block44f0eee2011-05-26 01:26:41 +010019576 int fib_limit_;
19577 int result_;
19578};
19579
Steve Block44f0eee2011-05-26 01:26:41 +010019580
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019581TEST(MultipleIsolatesOnIndividualThreads) {
19582 IsolateThread thread1(21);
19583 IsolateThread thread2(12);
Steve Block44f0eee2011-05-26 01:26:41 +010019584
19585 // Compute some fibonacci numbers on 3 threads in 3 isolates.
19586 thread1.Start();
19587 thread2.Start();
19588
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019589 int result1 = CalcFibonacci(CcTest::isolate(), 21);
19590 int result2 = CalcFibonacci(CcTest::isolate(), 12);
Steve Block44f0eee2011-05-26 01:26:41 +010019591
19592 thread1.Join();
19593 thread2.Join();
19594
19595 // Compare results. The actual fibonacci numbers for 12 and 21 are taken
19596 // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
19597 CHECK_EQ(result1, 10946);
19598 CHECK_EQ(result2, 144);
19599 CHECK_EQ(result1, thread1.result());
19600 CHECK_EQ(result2, thread2.result());
Steve Block44f0eee2011-05-26 01:26:41 +010019601}
19602
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019603
Ben Murdoch257744e2011-11-30 15:57:28 +000019604TEST(IsolateDifferentContexts) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019605 v8::Isolate::CreateParams create_params;
19606 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19607 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019608 Local<v8::Context> context;
Ben Murdoch257744e2011-11-30 15:57:28 +000019609 {
19610 v8::Isolate::Scope isolate_scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019611 v8::HandleScope handle_scope(isolate);
19612 context = v8::Context::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000019613 v8::Context::Scope context_scope(context);
19614 Local<Value> v = CompileRun("2");
19615 CHECK(v->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019616 CHECK_EQ(2, static_cast<int>(v->NumberValue(context).FromJust()));
Ben Murdoch257744e2011-11-30 15:57:28 +000019617 }
19618 {
19619 v8::Isolate::Scope isolate_scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019620 v8::HandleScope handle_scope(isolate);
19621 context = v8::Context::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000019622 v8::Context::Scope context_scope(context);
19623 Local<Value> v = CompileRun("22");
19624 CHECK(v->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019625 CHECK_EQ(22, static_cast<int>(v->NumberValue(context).FromJust()));
Ben Murdoch257744e2011-11-30 15:57:28 +000019626 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019627 isolate->Dispose();
Ben Murdoch257744e2011-11-30 15:57:28 +000019628}
Steve Block44f0eee2011-05-26 01:26:41 +010019629
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019630class InitDefaultIsolateThread : public v8::base::Thread {
Steve Block44f0eee2011-05-26 01:26:41 +010019631 public:
19632 enum TestCase {
Steve Block44f0eee2011-05-26 01:26:41 +010019633 SetResourceConstraints,
19634 SetFatalHandler,
19635 SetCounterFunction,
19636 SetCreateHistogramFunction,
19637 SetAddHistogramSampleFunction
19638 };
19639
19640 explicit InitDefaultIsolateThread(TestCase testCase)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019641 : Thread(Options("InitDefaultIsolateThread")),
Steve Block44f0eee2011-05-26 01:26:41 +010019642 testCase_(testCase),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019643 result_(false) {}
Steve Block44f0eee2011-05-26 01:26:41 +010019644
19645 void Run() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019646 v8::Isolate::CreateParams create_params;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019647 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19648 const intptr_t pageSizeMult =
19649 v8::internal::Page::kPageSize / v8::internal::MB;
Steve Block44f0eee2011-05-26 01:26:41 +010019650 switch (testCase_) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019651 case SetResourceConstraints: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019652 create_params.constraints.set_max_semi_space_size(1 * pageSizeMult);
19653 create_params.constraints.set_max_old_space_size(4 * pageSizeMult);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019654 break;
19655 }
19656 default:
19657 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019658 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019659 v8::Isolate* isolate = v8::Isolate::New(create_params);
19660 isolate->Enter();
19661 switch (testCase_) {
19662 case SetResourceConstraints:
19663 // Already handled in pre-Isolate-creation block.
19664 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019665
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019666 case SetFatalHandler:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019667 isolate->SetFatalErrorHandler(NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019668 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019669
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019670 case SetCounterFunction:
19671 CcTest::isolate()->SetCounterFunction(NULL);
19672 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019673
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019674 case SetCreateHistogramFunction:
19675 CcTest::isolate()->SetCreateHistogramFunction(NULL);
19676 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019677
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019678 case SetAddHistogramSampleFunction:
19679 CcTest::isolate()->SetAddHistogramSampleFunction(NULL);
19680 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019681 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019682 isolate->Exit();
19683 isolate->Dispose();
Steve Block44f0eee2011-05-26 01:26:41 +010019684 result_ = true;
19685 }
19686
19687 bool result() { return result_; }
19688
19689 private:
19690 TestCase testCase_;
19691 bool result_;
19692};
19693
19694
19695static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
19696 InitDefaultIsolateThread thread(testCase);
19697 thread.Start();
19698 thread.Join();
19699 CHECK_EQ(thread.result(), true);
19700}
19701
Steve Block44f0eee2011-05-26 01:26:41 +010019702
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019703TEST(InitializeDefaultIsolateOnSecondaryThread1) {
Steve Block44f0eee2011-05-26 01:26:41 +010019704 InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
19705}
19706
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019707
19708TEST(InitializeDefaultIsolateOnSecondaryThread2) {
Steve Block44f0eee2011-05-26 01:26:41 +010019709 InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
19710}
19711
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019712
19713TEST(InitializeDefaultIsolateOnSecondaryThread3) {
Steve Block44f0eee2011-05-26 01:26:41 +010019714 InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
19715}
19716
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019717
19718TEST(InitializeDefaultIsolateOnSecondaryThread4) {
Steve Block44f0eee2011-05-26 01:26:41 +010019719 InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
19720}
19721
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019722
19723TEST(InitializeDefaultIsolateOnSecondaryThread5) {
Steve Block44f0eee2011-05-26 01:26:41 +010019724 InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
19725}
19726
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019727
19728TEST(StringCheckMultipleContexts) {
19729 const char* code =
19730 "(function() { return \"a\".charAt(0); })()";
19731
19732 {
19733 // Run the code twice in the first context to initialize the call IC.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019734 LocalContext context1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019735 v8::HandleScope scope(context1->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019736 ExpectString(code, "a");
19737 ExpectString(code, "a");
19738 }
19739
19740 {
19741 // Change the String.prototype in the second context and check
19742 // that the right function gets called.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019743 LocalContext context2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019744 v8::HandleScope scope(context2->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019745 CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
19746 ExpectString(code, "not a");
19747 }
19748}
19749
19750
19751TEST(NumberCheckMultipleContexts) {
19752 const char* code =
19753 "(function() { return (42).toString(); })()";
19754
19755 {
19756 // Run the code twice in the first context to initialize the call IC.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019757 LocalContext context1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019758 v8::HandleScope scope(context1->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019759 ExpectString(code, "42");
19760 ExpectString(code, "42");
19761 }
19762
19763 {
19764 // Change the Number.prototype in the second context and check
19765 // that the right function gets called.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019766 LocalContext context2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019767 v8::HandleScope scope(context2->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019768 CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
19769 ExpectString(code, "not 42");
19770 }
19771}
19772
19773
19774TEST(BooleanCheckMultipleContexts) {
19775 const char* code =
19776 "(function() { return true.toString(); })()";
19777
19778 {
19779 // Run the code twice in the first context to initialize the call IC.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019780 LocalContext context1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019781 v8::HandleScope scope(context1->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019782 ExpectString(code, "true");
19783 ExpectString(code, "true");
19784 }
19785
19786 {
19787 // Change the Boolean.prototype in the second context and check
19788 // that the right function gets called.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019789 LocalContext context2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019790 v8::HandleScope scope(context2->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019791 CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
19792 ExpectString(code, "");
19793 }
19794}
Ben Murdochf87a2032010-10-22 12:50:53 +010019795
19796
19797TEST(DontDeleteCellLoadIC) {
19798 const char* function_code =
19799 "function readCell() { while (true) { return cell; } }";
19800
19801 {
19802 // Run the code twice in the first context to initialize the load
19803 // IC for a don't delete cell.
Ben Murdochf87a2032010-10-22 12:50:53 +010019804 LocalContext context1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019805 v8::HandleScope scope(context1->GetIsolate());
Ben Murdochf87a2032010-10-22 12:50:53 +010019806 CompileRun("var cell = \"first\";");
19807 ExpectBoolean("delete cell", false);
19808 CompileRun(function_code);
19809 ExpectString("readCell()", "first");
19810 ExpectString("readCell()", "first");
19811 }
19812
19813 {
19814 // Use a deletable cell in the second context.
Ben Murdochf87a2032010-10-22 12:50:53 +010019815 LocalContext context2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019816 v8::HandleScope scope(context2->GetIsolate());
Ben Murdochf87a2032010-10-22 12:50:53 +010019817 CompileRun("cell = \"second\";");
19818 CompileRun(function_code);
19819 ExpectString("readCell()", "second");
19820 ExpectBoolean("delete cell", true);
19821 ExpectString("(function() {"
19822 " try {"
19823 " return readCell();"
19824 " } catch(e) {"
19825 " return e.toString();"
19826 " }"
19827 "})()",
19828 "ReferenceError: cell is not defined");
19829 CompileRun("cell = \"new_second\";");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019830 CcTest::heap()->CollectAllGarbage();
Ben Murdochf87a2032010-10-22 12:50:53 +010019831 ExpectString("readCell()", "new_second");
19832 ExpectString("readCell()", "new_second");
19833 }
19834}
19835
19836
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019837class Visitor42 : public v8::PersistentHandleVisitor {
19838 public:
19839 explicit Visitor42(v8::Persistent<v8::Object>* object)
19840 : counter_(0), object_(object) { }
19841
19842 virtual void VisitPersistentHandle(Persistent<Value>* value,
19843 uint16_t class_id) {
19844 if (class_id != 42) return;
19845 CHECK_EQ(42, value->WrapperClassId());
19846 v8::Isolate* isolate = CcTest::isolate();
19847 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019848 v8::Local<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
19849 v8::Local<v8::Value> object = v8::Local<v8::Object>::New(isolate, *object_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019850 CHECK(handle->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019851 CHECK(Local<Object>::Cast(handle)
19852 ->Equals(isolate->GetCurrentContext(), object)
19853 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019854 ++counter_;
19855 }
19856
19857 int counter_;
19858 v8::Persistent<v8::Object>* object_;
19859};
19860
19861
19862TEST(PersistentHandleVisitor) {
Ben Murdochf87a2032010-10-22 12:50:53 +010019863 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019864 v8::Isolate* isolate = context->GetIsolate();
19865 v8::HandleScope scope(isolate);
19866 v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
19867 CHECK_EQ(0, object.WrapperClassId());
19868 object.SetWrapperClassId(42);
19869 CHECK_EQ(42, object.WrapperClassId());
19870
19871 Visitor42 visitor(&object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019872 isolate->VisitHandlesWithClassIds(&visitor);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019873 CHECK_EQ(1, visitor.counter_);
19874
19875 object.Reset();
19876}
19877
19878
19879TEST(WrapperClassId) {
19880 LocalContext context;
19881 v8::Isolate* isolate = context->GetIsolate();
19882 v8::HandleScope scope(isolate);
19883 v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
19884 CHECK_EQ(0, object.WrapperClassId());
19885 object.SetWrapperClassId(65535);
19886 CHECK_EQ(65535, object.WrapperClassId());
19887 object.Reset();
19888}
19889
19890
19891TEST(PersistentHandleInNewSpaceVisitor) {
19892 LocalContext context;
19893 v8::Isolate* isolate = context->GetIsolate();
19894 v8::HandleScope scope(isolate);
19895 v8::Persistent<v8::Object> object1(isolate, v8::Object::New(isolate));
19896 CHECK_EQ(0, object1.WrapperClassId());
19897 object1.SetWrapperClassId(42);
19898 CHECK_EQ(42, object1.WrapperClassId());
19899
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019900 CcTest::heap()->CollectAllGarbage();
19901 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019902
19903 v8::Persistent<v8::Object> object2(isolate, v8::Object::New(isolate));
19904 CHECK_EQ(0, object2.WrapperClassId());
19905 object2.SetWrapperClassId(42);
19906 CHECK_EQ(42, object2.WrapperClassId());
19907
19908 Visitor42 visitor(&object2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019909 isolate->VisitHandlesForPartialDependence(&visitor);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019910 CHECK_EQ(1, visitor.counter_);
19911
19912 object1.Reset();
19913 object2.Reset();
19914}
19915
19916
19917TEST(RegExp) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019918 i::FLAG_harmony_regexps = true;
19919 i::FLAG_harmony_unicode_regexps = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019920 LocalContext context;
19921 v8::HandleScope scope(context->GetIsolate());
Ben Murdochf87a2032010-10-22 12:50:53 +010019922
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019923 v8::Local<v8::RegExp> re =
19924 v8::RegExp::New(context.local(), v8_str("foo"), v8::RegExp::kNone)
19925 .ToLocalChecked();
Ben Murdochf87a2032010-10-22 12:50:53 +010019926 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019927 CHECK(re->GetSource()->Equals(context.local(), v8_str("foo")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019928 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
Ben Murdochf87a2032010-10-22 12:50:53 +010019929
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019930 re = v8::RegExp::New(context.local(), v8_str("bar"),
Ben Murdochf87a2032010-10-22 12:50:53 +010019931 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019932 v8::RegExp::kGlobal))
19933 .ToLocalChecked();
Ben Murdochf87a2032010-10-22 12:50:53 +010019934 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019935 CHECK(re->GetSource()->Equals(context.local(), v8_str("bar")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019936 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
19937 static_cast<int>(re->GetFlags()));
Ben Murdochf87a2032010-10-22 12:50:53 +010019938
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019939 re = v8::RegExp::New(context.local(), v8_str("baz"),
Ben Murdochf87a2032010-10-22 12:50:53 +010019940 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019941 v8::RegExp::kMultiline))
19942 .ToLocalChecked();
Ben Murdochf87a2032010-10-22 12:50:53 +010019943 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019944 CHECK(re->GetSource()->Equals(context.local(), v8_str("baz")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019945 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
19946 static_cast<int>(re->GetFlags()));
Ben Murdochf87a2032010-10-22 12:50:53 +010019947
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019948 re = v8::RegExp::New(context.local(), v8_str("baz"),
19949 static_cast<v8::RegExp::Flags>(v8::RegExp::kUnicode |
19950 v8::RegExp::kSticky))
19951 .ToLocalChecked();
19952 CHECK(re->IsRegExp());
19953 CHECK(re->GetSource()->Equals(context.local(), v8_str("baz")).FromJust());
19954 CHECK_EQ(v8::RegExp::kUnicode | v8::RegExp::kSticky,
19955 static_cast<int>(re->GetFlags()));
19956
Ben Murdochf87a2032010-10-22 12:50:53 +010019957 re = CompileRun("/quux/").As<v8::RegExp>();
19958 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019959 CHECK(re->GetSource()->Equals(context.local(), v8_str("quux")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019960 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
Ben Murdochf87a2032010-10-22 12:50:53 +010019961
19962 re = CompileRun("/quux/gm").As<v8::RegExp>();
19963 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019964 CHECK(re->GetSource()->Equals(context.local(), v8_str("quux")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019965 CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
19966 static_cast<int>(re->GetFlags()));
Ben Murdochf87a2032010-10-22 12:50:53 +010019967
19968 // Override the RegExp constructor and check the API constructor
19969 // still works.
19970 CompileRun("RegExp = function() {}");
19971
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019972 re = v8::RegExp::New(context.local(), v8_str("foobar"), v8::RegExp::kNone)
19973 .ToLocalChecked();
Ben Murdochf87a2032010-10-22 12:50:53 +010019974 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019975 CHECK(re->GetSource()->Equals(context.local(), v8_str("foobar")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019976 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
Ben Murdochf87a2032010-10-22 12:50:53 +010019977
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019978 re = v8::RegExp::New(context.local(), v8_str("foobarbaz"),
Ben Murdochf87a2032010-10-22 12:50:53 +010019979 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019980 v8::RegExp::kMultiline))
19981 .ToLocalChecked();
Ben Murdochf87a2032010-10-22 12:50:53 +010019982 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019983 CHECK(
19984 re->GetSource()->Equals(context.local(), v8_str("foobarbaz")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019985 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
19986 static_cast<int>(re->GetFlags()));
Ben Murdochf87a2032010-10-22 12:50:53 +010019987
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019988 CHECK(context->Global()->Set(context.local(), v8_str("re"), re).FromJust());
Ben Murdochf87a2032010-10-22 12:50:53 +010019989 ExpectTrue("re.test('FoobarbaZ')");
19990
Ben Murdoch257744e2011-11-30 15:57:28 +000019991 // RegExps are objects on which you can set properties.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019992 re->Set(context.local(), v8_str("property"),
19993 v8::Integer::New(context->GetIsolate(), 32))
19994 .FromJust();
19995 v8::Local<v8::Value> value(CompileRun("re.property"));
19996 CHECK_EQ(32, value->Int32Value(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000019997
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019998 v8::TryCatch try_catch(context->GetIsolate());
19999 CHECK(v8::RegExp::New(context.local(), v8_str("foo["), v8::RegExp::kNone)
20000 .IsEmpty());
Ben Murdochf87a2032010-10-22 12:50:53 +010020001 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020002 CHECK(context->Global()
20003 ->Set(context.local(), v8_str("ex"), try_catch.Exception())
20004 .FromJust());
Ben Murdochf87a2032010-10-22 12:50:53 +010020005 ExpectTrue("ex instanceof SyntaxError");
20006}
20007
20008
Steve Block1e0659c2011-05-24 12:43:12 +010020009THREADED_TEST(Equals) {
Steve Block1e0659c2011-05-24 12:43:12 +010020010 LocalContext localContext;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020011 v8::HandleScope handleScope(localContext->GetIsolate());
Steve Block1e0659c2011-05-24 12:43:12 +010020012
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020013 v8::Local<v8::Object> globalProxy = localContext->Global();
20014 v8::Local<Value> global = globalProxy->GetPrototype();
Steve Block1e0659c2011-05-24 12:43:12 +010020015
20016 CHECK(global->StrictEquals(global));
20017 CHECK(!global->StrictEquals(globalProxy));
20018 CHECK(!globalProxy->StrictEquals(global));
20019 CHECK(globalProxy->StrictEquals(globalProxy));
20020
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020021 CHECK(global->Equals(localContext.local(), global).FromJust());
20022 CHECK(!global->Equals(localContext.local(), globalProxy).FromJust());
20023 CHECK(!globalProxy->Equals(localContext.local(), global).FromJust());
20024 CHECK(globalProxy->Equals(localContext.local(), globalProxy).FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +010020025}
20026
20027
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020028static void Getter(v8::Local<v8::Name> property,
20029 const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020030 info.GetReturnValue().Set(v8_str("42!"));
Ben Murdochf87a2032010-10-22 12:50:53 +010020031}
20032
20033
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020034static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020035 v8::Local<v8::Array> result = v8::Array::New(info.GetIsolate());
20036 result->Set(info.GetIsolate()->GetCurrentContext(), 0,
20037 v8_str("universalAnswer"))
20038 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020039 info.GetReturnValue().Set(result);
Ben Murdochf87a2032010-10-22 12:50:53 +010020040}
20041
20042
20043TEST(NamedEnumeratorAndForIn) {
Ben Murdochf87a2032010-10-22 12:50:53 +010020044 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020045 v8::Isolate* isolate = context->GetIsolate();
20046 v8::HandleScope handle_scope(isolate);
Ben Murdochf87a2032010-10-22 12:50:53 +010020047 v8::Context::Scope context_scope(context.local());
20048
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020049 v8::Local<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020050 tmpl->SetHandler(v8::NamedPropertyHandlerConfiguration(Getter, NULL, NULL,
20051 NULL, Enumerator));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020052 CHECK(context->Global()
20053 ->Set(context.local(), v8_str("o"),
20054 tmpl->NewInstance(context.local()).ToLocalChecked())
20055 .FromJust());
20056 v8::Local<v8::Array> result = v8::Local<v8::Array>::Cast(
20057 CompileRun("var result = []; for (var k in o) result.push(k); result"));
20058 CHECK_EQ(1u, result->Length());
20059 CHECK(v8_str("universalAnswer")
20060 ->Equals(context.local(),
20061 result->Get(context.local(), 0).ToLocalChecked())
20062 .FromJust());
Ben Murdochf87a2032010-10-22 12:50:53 +010020063}
Steve Block1e0659c2011-05-24 12:43:12 +010020064
20065
20066TEST(DefinePropertyPostDetach) {
Steve Block1e0659c2011-05-24 12:43:12 +010020067 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020068 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020069 v8::Local<v8::Object> proxy = context->Global();
20070 v8::Local<v8::Function> define_property =
20071 CompileRun(
20072 "(function() {"
20073 " Object.defineProperty("
20074 " this,"
20075 " 1,"
20076 " { configurable: true, enumerable: true, value: 3 });"
20077 "})")
20078 .As<Function>();
Steve Block1e0659c2011-05-24 12:43:12 +010020079 context->DetachGlobal();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020080 CHECK(define_property->Call(context.local(), proxy, 0, NULL).IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +010020081}
Ben Murdoch8b112d22011-06-08 16:22:53 +010020082
20083
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020084static void InstallContextId(v8::Local<Context> context, int id) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010020085 Context::Scope scope(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020086 CHECK(CompileRun("Object.prototype")
20087 .As<Object>()
20088 ->Set(context, v8_str("context_id"),
20089 v8::Integer::New(context->GetIsolate(), id))
20090 .FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010020091}
20092
20093
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020094static void CheckContextId(v8::Local<Object> object, int expected) {
20095 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
20096 CHECK_EQ(expected, object->Get(context, v8_str("context_id"))
20097 .ToLocalChecked()
20098 ->Int32Value(context)
20099 .FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010020100}
20101
20102
20103THREADED_TEST(CreationContext) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020104 v8::Isolate* isolate = CcTest::isolate();
20105 HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020106 Local<Context> context1 = Context::New(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +010020107 InstallContextId(context1, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020108 Local<Context> context2 = Context::New(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +010020109 InstallContextId(context2, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020110 Local<Context> context3 = Context::New(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +010020111 InstallContextId(context3, 3);
20112
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020113 Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +010020114
20115 Local<Object> object1;
20116 Local<Function> func1;
20117 {
20118 Context::Scope scope(context1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020119 object1 = Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020120 func1 = tmpl->GetFunction(context1).ToLocalChecked();
Ben Murdoch8b112d22011-06-08 16:22:53 +010020121 }
20122
20123 Local<Object> object2;
20124 Local<Function> func2;
20125 {
20126 Context::Scope scope(context2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020127 object2 = Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020128 func2 = tmpl->GetFunction(context2).ToLocalChecked();
Ben Murdoch8b112d22011-06-08 16:22:53 +010020129 }
20130
20131 Local<Object> instance1;
20132 Local<Object> instance2;
20133
20134 {
20135 Context::Scope scope(context3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020136 instance1 = func1->NewInstance(context3).ToLocalChecked();
20137 instance2 = func2->NewInstance(context3).ToLocalChecked();
Ben Murdoch8b112d22011-06-08 16:22:53 +010020138 }
20139
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020140 {
20141 Local<Context> other_context = Context::New(isolate);
20142 Context::Scope scope(other_context);
20143 CHECK(object1->CreationContext() == context1);
20144 CheckContextId(object1, 1);
20145 CHECK(func1->CreationContext() == context1);
20146 CheckContextId(func1, 1);
20147 CHECK(instance1->CreationContext() == context1);
20148 CheckContextId(instance1, 1);
20149 CHECK(object2->CreationContext() == context2);
20150 CheckContextId(object2, 2);
20151 CHECK(func2->CreationContext() == context2);
20152 CheckContextId(func2, 2);
20153 CHECK(instance2->CreationContext() == context2);
20154 CheckContextId(instance2, 2);
20155 }
Ben Murdoch8b112d22011-06-08 16:22:53 +010020156
20157 {
20158 Context::Scope scope(context1);
20159 CHECK(object1->CreationContext() == context1);
20160 CheckContextId(object1, 1);
20161 CHECK(func1->CreationContext() == context1);
20162 CheckContextId(func1, 1);
20163 CHECK(instance1->CreationContext() == context1);
20164 CheckContextId(instance1, 1);
20165 CHECK(object2->CreationContext() == context2);
20166 CheckContextId(object2, 2);
20167 CHECK(func2->CreationContext() == context2);
20168 CheckContextId(func2, 2);
20169 CHECK(instance2->CreationContext() == context2);
20170 CheckContextId(instance2, 2);
20171 }
20172
20173 {
20174 Context::Scope scope(context2);
20175 CHECK(object1->CreationContext() == context1);
20176 CheckContextId(object1, 1);
20177 CHECK(func1->CreationContext() == context1);
20178 CheckContextId(func1, 1);
20179 CHECK(instance1->CreationContext() == context1);
20180 CheckContextId(instance1, 1);
20181 CHECK(object2->CreationContext() == context2);
20182 CheckContextId(object2, 2);
20183 CHECK(func2->CreationContext() == context2);
20184 CheckContextId(func2, 2);
20185 CHECK(instance2->CreationContext() == context2);
20186 CheckContextId(instance2, 2);
20187 }
Ben Murdoch8b112d22011-06-08 16:22:53 +010020188}
Ben Murdoch257744e2011-11-30 15:57:28 +000020189
20190
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020191THREADED_TEST(CreationContextOfJsFunction) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020192 HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020193 Local<Context> context = Context::New(CcTest::isolate());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020194 InstallContextId(context, 1);
20195
20196 Local<Object> function;
20197 {
20198 Context::Scope scope(context);
20199 function = CompileRun("function foo() {}; foo").As<Object>();
20200 }
20201
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020202 Local<Context> other_context = Context::New(CcTest::isolate());
20203 Context::Scope scope(other_context);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020204 CHECK(function->CreationContext() == context);
20205 CheckContextId(function, 1);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020206}
20207
20208
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020209THREADED_TEST(CreationContextOfJsBoundFunction) {
20210 HandleScope handle_scope(CcTest::isolate());
20211 Local<Context> context1 = Context::New(CcTest::isolate());
20212 InstallContextId(context1, 1);
20213 Local<Context> context2 = Context::New(CcTest::isolate());
20214 InstallContextId(context2, 2);
20215
20216 Local<Function> target_function;
20217 {
20218 Context::Scope scope(context1);
20219 target_function = CompileRun("function foo() {}; foo").As<Function>();
20220 }
20221
20222 Local<Function> bound_function1, bound_function2;
20223 {
20224 Context::Scope scope(context2);
20225 CHECK(context2->Global()
20226 ->Set(context2, v8_str("foo"), target_function)
20227 .FromJust());
20228 bound_function1 = CompileRun("foo.bind(1)").As<Function>();
20229 bound_function2 =
20230 CompileRun("Function.prototype.bind.call(foo, 2)").As<Function>();
20231 }
20232
20233 Local<Context> other_context = Context::New(CcTest::isolate());
20234 Context::Scope scope(other_context);
20235 CHECK(bound_function1->CreationContext() == context1);
20236 CheckContextId(bound_function1, 1);
Ben Murdoch097c5b22016-05-18 11:27:45 +010020237 CHECK(bound_function2->CreationContext() == context1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020238 CheckContextId(bound_function2, 1);
20239}
20240
20241
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020242void HasOwnPropertyIndexedPropertyGetter(
20243 uint32_t index,
20244 const v8::PropertyCallbackInfo<v8::Value>& info) {
20245 if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
Ben Murdoch257744e2011-11-30 15:57:28 +000020246}
20247
20248
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020249void HasOwnPropertyNamedPropertyGetter(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020250 Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020251 if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
20252 .FromJust()) {
20253 info.GetReturnValue().Set(v8_str("yes"));
20254 }
Ben Murdoch257744e2011-11-30 15:57:28 +000020255}
20256
20257
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020258void HasOwnPropertyIndexedPropertyQuery(
20259 uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
20260 if (index == 42) info.GetReturnValue().Set(1);
Ben Murdoch257744e2011-11-30 15:57:28 +000020261}
20262
20263
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020264void HasOwnPropertyNamedPropertyQuery(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020265 Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020266 if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
20267 .FromJust()) {
20268 info.GetReturnValue().Set(1);
20269 }
Ben Murdoch257744e2011-11-30 15:57:28 +000020270}
20271
20272
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020273void HasOwnPropertyNamedPropertyQuery2(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020274 Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020275 if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("bar"))
20276 .FromJust()) {
20277 info.GetReturnValue().Set(1);
20278 }
Ben Murdoch257744e2011-11-30 15:57:28 +000020279}
20280
20281
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020282void HasOwnPropertyAccessorGetter(
20283 Local<String> property,
20284 const v8::PropertyCallbackInfo<v8::Value>& info) {
20285 info.GetReturnValue().Set(v8_str("yes"));
Ben Murdoch257744e2011-11-30 15:57:28 +000020286}
20287
20288
20289TEST(HasOwnProperty) {
Ben Murdoch257744e2011-11-30 15:57:28 +000020290 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020291 v8::Isolate* isolate = env->GetIsolate();
20292 v8::HandleScope scope(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000020293 { // Check normal properties and defined getters.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020294 Local<Value> value = CompileRun(
Ben Murdoch257744e2011-11-30 15:57:28 +000020295 "function Foo() {"
20296 " this.foo = 11;"
20297 " this.__defineGetter__('baz', function() { return 1; });"
20298 "};"
20299 "function Bar() { "
20300 " this.bar = 13;"
20301 " this.__defineGetter__('bla', function() { return 2; });"
20302 "};"
20303 "Bar.prototype = new Foo();"
20304 "new Bar();");
20305 CHECK(value->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020306 Local<Object> object = value->ToObject(env.local()).ToLocalChecked();
20307 CHECK(object->Has(env.local(), v8_str("foo")).FromJust());
20308 CHECK(!object->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
20309 CHECK(object->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
20310 CHECK(object->Has(env.local(), v8_str("baz")).FromJust());
20311 CHECK(!object->HasOwnProperty(env.local(), v8_str("baz")).FromJust());
20312 CHECK(object->HasOwnProperty(env.local(), v8_str("bla")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020313 }
20314 { // Check named getter interceptors.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020315 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020316 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
20317 HasOwnPropertyNamedPropertyGetter));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020318 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
20319 CHECK(!instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
20320 CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
20321 CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020322 }
20323 { // Check indexed getter interceptors.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020324 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020325 templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
20326 HasOwnPropertyIndexedPropertyGetter));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020327 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
20328 CHECK(instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
20329 CHECK(!instance->HasOwnProperty(env.local(), v8_str("43")).FromJust());
20330 CHECK(!instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020331 }
20332 { // Check named query interceptors.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020333 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020334 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
20335 0, 0, HasOwnPropertyNamedPropertyQuery));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020336 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
20337 CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
20338 CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020339 }
20340 { // Check indexed query interceptors.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020341 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020342 templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
20343 0, 0, HasOwnPropertyIndexedPropertyQuery));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020344 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
20345 CHECK(instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
20346 CHECK(!instance->HasOwnProperty(env.local(), v8_str("41")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020347 }
20348 { // Check callbacks.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020349 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000020350 templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020351 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
20352 CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
20353 CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020354 }
20355 { // Check that query wins on disagreement.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020356 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020357 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
20358 HasOwnPropertyNamedPropertyGetter, 0,
20359 HasOwnPropertyNamedPropertyQuery2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020360 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
20361 CHECK(!instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
20362 CHECK(instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020363 }
20364}
20365
20366
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020367TEST(IndexedInterceptorWithStringProto) {
20368 v8::Isolate* isolate = CcTest::isolate();
20369 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020370 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020371 templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
20372 NULL, NULL, HasOwnPropertyIndexedPropertyQuery));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020373 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020374 CHECK(context->Global()
20375 ->Set(context.local(), v8_str("obj"),
20376 templ->NewInstance(context.local()).ToLocalChecked())
20377 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020378 CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
20379 // These should be intercepted.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020380 CHECK(CompileRun("42 in obj")->BooleanValue(context.local()).FromJust());
20381 CHECK(CompileRun("'42' in obj")->BooleanValue(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020382 // These should fall through to the String prototype.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020383 CHECK(CompileRun("0 in obj")->BooleanValue(context.local()).FromJust());
20384 CHECK(CompileRun("'0' in obj")->BooleanValue(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020385 // And these should both fail.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020386 CHECK(!CompileRun("32 in obj")->BooleanValue(context.local()).FromJust());
20387 CHECK(!CompileRun("'32' in obj")->BooleanValue(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020388}
20389
20390
Ben Murdoch257744e2011-11-30 15:57:28 +000020391void CheckCodeGenerationAllowed() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020392 Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
20393 Local<Value> result = CompileRun("eval('42')");
20394 CHECK_EQ(42, result->Int32Value(context).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020395 result = CompileRun("(function(e) { return e('42'); })(eval)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020396 CHECK_EQ(42, result->Int32Value(context).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020397 result = CompileRun("var f = new Function('return 42'); f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020398 CHECK_EQ(42, result->Int32Value(context).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020399}
20400
20401
20402void CheckCodeGenerationDisallowed() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020403 TryCatch try_catch(CcTest::isolate());
Ben Murdoch257744e2011-11-30 15:57:28 +000020404
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020405 Local<Value> result = CompileRun("eval('42')");
Ben Murdoch257744e2011-11-30 15:57:28 +000020406 CHECK(result.IsEmpty());
20407 CHECK(try_catch.HasCaught());
20408 try_catch.Reset();
20409
20410 result = CompileRun("(function(e) { return e('42'); })(eval)");
20411 CHECK(result.IsEmpty());
20412 CHECK(try_catch.HasCaught());
20413 try_catch.Reset();
20414
20415 result = CompileRun("var f = new Function('return 42'); f()");
20416 CHECK(result.IsEmpty());
20417 CHECK(try_catch.HasCaught());
20418}
20419
20420
20421bool CodeGenerationAllowed(Local<Context> context) {
20422 ApiTestFuzzer::Fuzz();
20423 return true;
20424}
20425
20426
20427bool CodeGenerationDisallowed(Local<Context> context) {
20428 ApiTestFuzzer::Fuzz();
20429 return false;
20430}
20431
20432
20433THREADED_TEST(AllowCodeGenFromStrings) {
Ben Murdoch257744e2011-11-30 15:57:28 +000020434 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020435 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch257744e2011-11-30 15:57:28 +000020436
20437 // eval and the Function constructor allowed by default.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020438 CHECK(context->IsCodeGenerationFromStringsAllowed());
Ben Murdoch257744e2011-11-30 15:57:28 +000020439 CheckCodeGenerationAllowed();
20440
20441 // Disallow eval and the Function constructor.
20442 context->AllowCodeGenerationFromStrings(false);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020443 CHECK(!context->IsCodeGenerationFromStringsAllowed());
Ben Murdoch257744e2011-11-30 15:57:28 +000020444 CheckCodeGenerationDisallowed();
20445
20446 // Allow again.
20447 context->AllowCodeGenerationFromStrings(true);
20448 CheckCodeGenerationAllowed();
20449
20450 // Disallow but setting a global callback that will allow the calls.
20451 context->AllowCodeGenerationFromStrings(false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020452 context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
20453 &CodeGenerationAllowed);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020454 CHECK(!context->IsCodeGenerationFromStringsAllowed());
Ben Murdoch257744e2011-11-30 15:57:28 +000020455 CheckCodeGenerationAllowed();
20456
20457 // Set a callback that disallows the code generation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020458 context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
20459 &CodeGenerationDisallowed);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020460 CHECK(!context->IsCodeGenerationFromStringsAllowed());
Ben Murdoch257744e2011-11-30 15:57:28 +000020461 CheckCodeGenerationDisallowed();
20462}
20463
20464
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020465TEST(SetErrorMessageForCodeGenFromStrings) {
20466 LocalContext context;
20467 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020468 TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020469
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020470 Local<String> message = v8_str("Message");
20471 Local<String> expected_message = v8_str("Uncaught EvalError: Message");
20472 context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
20473 &CodeGenerationDisallowed);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020474 context->AllowCodeGenerationFromStrings(false);
20475 context->SetErrorMessageForCodeGenerationFromStrings(message);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020476 Local<Value> result = CompileRun("eval('42')");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020477 CHECK(result.IsEmpty());
20478 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020479 Local<String> actual_message = try_catch.Message()->Get();
20480 CHECK(expected_message->Equals(context.local(), actual_message).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020481}
20482
20483
20484static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch257744e2011-11-30 15:57:28 +000020485}
20486
20487
20488THREADED_TEST(CallAPIFunctionOnNonObject) {
Ben Murdoch257744e2011-11-30 15:57:28 +000020489 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020490 v8::Isolate* isolate = context->GetIsolate();
20491 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020492 Local<FunctionTemplate> templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020493 v8::FunctionTemplate::New(isolate, NonObjectThis);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020494 Local<Function> function =
20495 templ->GetFunction(context.local()).ToLocalChecked();
20496 CHECK(context->Global()
20497 ->Set(context.local(), v8_str("f"), function)
20498 .FromJust());
20499 TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000020500 CompileRun("f.call(2)");
20501}
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020502
20503
20504// Regression test for issue 1470.
20505THREADED_TEST(ReadOnlyIndexedProperties) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020506 v8::Isolate* isolate = CcTest::isolate();
20507 v8::HandleScope scope(isolate);
20508 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020509
20510 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020511 Local<v8::Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
20512 CHECK(context->Global()->Set(context.local(), v8_str("obj"), obj).FromJust());
20513 obj->DefineOwnProperty(context.local(), v8_str("1"), v8_str("DONT_CHANGE"),
20514 v8::ReadOnly)
20515 .FromJust();
20516 obj->Set(context.local(), v8_str("1"), v8_str("foobar")).FromJust();
20517 CHECK(v8_str("DONT_CHANGE")
20518 ->Equals(context.local(),
20519 obj->Get(context.local(), v8_str("1")).ToLocalChecked())
20520 .FromJust());
20521 obj->DefineOwnProperty(context.local(), v8_str("2"), v8_str("DONT_CHANGE"),
20522 v8::ReadOnly)
20523 .FromJust();
20524 obj->Set(context.local(), v8_num(2), v8_str("foobar")).FromJust();
20525 CHECK(v8_str("DONT_CHANGE")
20526 ->Equals(context.local(),
20527 obj->Get(context.local(), v8_num(2)).ToLocalChecked())
20528 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020529
20530 // Test non-smi case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020531 obj->DefineOwnProperty(context.local(), v8_str("2000000000"),
20532 v8_str("DONT_CHANGE"), v8::ReadOnly)
20533 .FromJust();
20534 obj->Set(context.local(), v8_str("2000000000"), v8_str("foobar")).FromJust();
20535 CHECK(v8_str("DONT_CHANGE")
20536 ->Equals(context.local(),
20537 obj->Get(context.local(), v8_str("2000000000"))
20538 .ToLocalChecked())
20539 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020540}
20541
20542
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020543static int CountLiveMapsInMapCache(i::Context* context) {
20544 i::FixedArray* map_cache = i::FixedArray::cast(context->map_cache());
20545 int length = map_cache->length();
20546 int count = 0;
20547 for (int i = 0; i < length; i++) {
20548 i::Object* value = map_cache->get(i);
20549 if (value->IsWeakCell() && !i::WeakCell::cast(value)->cleared()) count++;
20550 }
20551 return count;
20552}
20553
20554
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020555THREADED_TEST(Regress1516) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020556 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020557 v8::HandleScope scope(context->GetIsolate());
20558
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020559 // Object with 20 properties is not a common case, so it should be removed
20560 // from the cache after GC.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020561 { v8::HandleScope temp_scope(context->GetIsolate());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020562 CompileRun(
20563 "({"
20564 "'a00': 0, 'a01': 0, 'a02': 0, 'a03': 0, 'a04': 0, "
20565 "'a05': 0, 'a06': 0, 'a07': 0, 'a08': 0, 'a09': 0, "
20566 "'a10': 0, 'a11': 0, 'a12': 0, 'a13': 0, 'a14': 0, "
20567 "'a15': 0, 'a16': 0, 'a17': 0, 'a18': 0, 'a19': 0, "
20568 "})");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020569 }
20570
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020571 int elements = CountLiveMapsInMapCache(CcTest::i_isolate()->context());
20572 CHECK_LE(1, elements);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020573
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020574 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020575
20576 CHECK_GT(elements, CountLiveMapsInMapCache(CcTest::i_isolate()->context()));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020577}
20578
20579
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020580THREADED_TEST(Regress93759) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020581 v8::Isolate* isolate = CcTest::isolate();
20582 HandleScope scope(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020583
20584 // Template for object with security check.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020585 Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020586 no_proto_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020587
20588 // Templates for objects with hidden prototypes and possibly security check.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020589 Local<FunctionTemplate> hidden_proto_template =
20590 v8::FunctionTemplate::New(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020591 hidden_proto_template->SetHiddenPrototype(true);
20592
20593 Local<FunctionTemplate> protected_hidden_proto_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020594 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020595 protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallback(
20596 AccessAlwaysBlocked);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020597 protected_hidden_proto_template->SetHiddenPrototype(true);
20598
20599 // Context for "foreign" objects used in test.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020600 Local<Context> context = v8::Context::New(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020601 context->Enter();
20602
20603 // Plain object, no security check.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020604 Local<Object> simple_object = Object::New(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020605
20606 // Object with explicit security check.
20607 Local<Object> protected_object =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020608 no_proto_template->NewInstance(context).ToLocalChecked();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020609
20610 // JSGlobalProxy object, always have security check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020611 Local<Object> proxy_object = context->Global();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020612
20613 // Global object, the prototype of proxy_object. No security checks.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020614 Local<Object> global_object =
20615 proxy_object->GetPrototype()->ToObject(context).ToLocalChecked();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020616
20617 // Hidden prototype without security check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020618 Local<Object> hidden_prototype = hidden_proto_template->GetFunction(context)
20619 .ToLocalChecked()
20620 ->NewInstance(context)
20621 .ToLocalChecked();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020622 Local<Object> object_with_hidden =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020623 Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020624 object_with_hidden->SetPrototype(context, hidden_prototype).FromJust();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020625
20626 context->Exit();
20627
Ben Murdoch097c5b22016-05-18 11:27:45 +010020628 LocalContext context2;
20629 v8::Local<v8::Object> global = context2->Global();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020630
Ben Murdoch097c5b22016-05-18 11:27:45 +010020631 // Setup global variables.
20632 CHECK(global->Set(context2.local(), v8_str("simple"), simple_object)
20633 .FromJust());
20634 CHECK(global->Set(context2.local(), v8_str("protected"), protected_object)
20635 .FromJust());
20636 CHECK(global->Set(context2.local(), v8_str("global"), global_object)
20637 .FromJust());
20638 CHECK(
20639 global->Set(context2.local(), v8_str("proxy"), proxy_object).FromJust());
20640 CHECK(global->Set(context2.local(), v8_str("hidden"), object_with_hidden)
20641 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020642
20643 Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020644 CHECK(result1->Equals(context2.local(), simple_object->GetPrototype())
20645 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020646
20647 Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020648 CHECK(result2->IsNull());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020649
20650 Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020651 CHECK(result3->Equals(context2.local(), global_object->GetPrototype())
20652 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020653
20654 Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020655 CHECK(result4->IsNull());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020656
20657 Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020658 CHECK(result5->Equals(context2.local(), object_with_hidden->GetPrototype()
20659 ->ToObject(context2.local())
20660 .ToLocalChecked()
20661 ->GetPrototype())
20662 .FromJust());
Ben Murdoch5710cea2012-05-21 14:52:42 +010020663}
20664
20665
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020666static void TestReceiver(Local<Value> expected_result,
20667 Local<Value> expected_receiver,
20668 const char* code) {
20669 Local<Value> result = CompileRun(code);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020670 Local<Context> context = CcTest::isolate()->GetCurrentContext();
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020671 CHECK(result->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020672 CHECK(expected_receiver
20673 ->Equals(context,
20674 result.As<v8::Object>()->Get(context, 1).ToLocalChecked())
20675 .FromJust());
20676 CHECK(expected_result
20677 ->Equals(context,
20678 result.As<v8::Object>()->Get(context, 0).ToLocalChecked())
20679 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020680}
20681
20682
20683THREADED_TEST(ForeignFunctionReceiver) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020684 v8::Isolate* isolate = CcTest::isolate();
20685 HandleScope scope(isolate);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020686
20687 // Create two contexts with different "id" properties ('i' and 'o').
20688 // Call a function both from its own context and from a the foreign
20689 // context, and see what "this" is bound to (returning both "this"
20690 // and "this.id" for comparison).
20691
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020692 Local<Context> foreign_context = v8::Context::New(isolate);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020693 foreign_context->Enter();
20694 Local<Value> foreign_function =
20695 CompileRun("function func() { return { 0: this.id, "
20696 " 1: this, "
20697 " toString: function() { "
20698 " return this[0];"
20699 " }"
20700 " };"
20701 "}"
20702 "var id = 'i';"
20703 "func;");
20704 CHECK(foreign_function->IsFunction());
20705 foreign_context->Exit();
20706
20707 LocalContext context;
20708
20709 Local<String> password = v8_str("Password");
20710 // Don't get hit by security checks when accessing foreign_context's
20711 // global receiver (aka. global proxy).
20712 context->SetSecurityToken(password);
20713 foreign_context->SetSecurityToken(password);
20714
20715 Local<String> i = v8_str("i");
20716 Local<String> o = v8_str("o");
20717 Local<String> id = v8_str("id");
20718
20719 CompileRun("function ownfunc() { return { 0: this.id, "
20720 " 1: this, "
20721 " toString: function() { "
20722 " return this[0];"
20723 " }"
20724 " };"
20725 "}"
20726 "var id = 'o';"
20727 "ownfunc");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020728 CHECK(context->Global()
20729 ->Set(context.local(), v8_str("func"), foreign_function)
20730 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020731
20732 // Sanity check the contexts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020733 CHECK(
20734 i->Equals(
20735 context.local(),
20736 foreign_context->Global()->Get(context.local(), id).ToLocalChecked())
20737 .FromJust());
20738 CHECK(o->Equals(context.local(),
20739 context->Global()->Get(context.local(), id).ToLocalChecked())
20740 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020741
20742 // Checking local function's receiver.
20743 // Calling function using its call/apply methods.
20744 TestReceiver(o, context->Global(), "ownfunc.call()");
20745 TestReceiver(o, context->Global(), "ownfunc.apply()");
20746 // Making calls through built-in functions.
20747 TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020748 CHECK(
20749 o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/,ownfunc)[1]"))
20750 .FromJust());
20751 CHECK(
20752 o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]"))
20753 .FromJust());
20754 CHECK(
20755 o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]"))
20756 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020757 // Calling with environment record as base.
20758 TestReceiver(o, context->Global(), "ownfunc()");
20759 // Calling with no base.
20760 TestReceiver(o, context->Global(), "(1,ownfunc)()");
20761
20762 // Checking foreign function return value.
20763 // Calling function using its call/apply methods.
20764 TestReceiver(i, foreign_context->Global(), "func.call()");
20765 TestReceiver(i, foreign_context->Global(), "func.apply()");
20766 // Calling function using another context's call/apply methods.
20767 TestReceiver(i, foreign_context->Global(),
20768 "Function.prototype.call.call(func)");
20769 TestReceiver(i, foreign_context->Global(),
20770 "Function.prototype.call.apply(func)");
20771 TestReceiver(i, foreign_context->Global(),
20772 "Function.prototype.apply.call(func)");
20773 TestReceiver(i, foreign_context->Global(),
20774 "Function.prototype.apply.apply(func)");
20775 // Making calls through built-in functions.
20776 TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
20777 // ToString(func()) is func()[0], i.e., the returned this.id.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020778 CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/,func)[1]"))
20779 .FromJust());
20780 CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,func)[1]"))
20781 .FromJust());
20782 CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,func)[3]"))
20783 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020784
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020785 // Calling with environment record as base.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020786 TestReceiver(i, foreign_context->Global(), "func()");
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020787 // Calling with no base.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020788 TestReceiver(i, foreign_context->Global(), "(1,func)()");
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020789}
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020790
20791
20792uint8_t callback_fired = 0;
Ben Murdoch097c5b22016-05-18 11:27:45 +010020793uint8_t before_call_entered_callback_count1 = 0;
20794uint8_t before_call_entered_callback_count2 = 0;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020795
20796
Ben Murdoch097c5b22016-05-18 11:27:45 +010020797void CallCompletedCallback1(v8::Isolate*) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020798 v8::base::OS::Print("Firing callback 1.\n");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020799 callback_fired ^= 1; // Toggle first bit.
20800}
20801
20802
Ben Murdoch097c5b22016-05-18 11:27:45 +010020803void CallCompletedCallback2(v8::Isolate*) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020804 v8::base::OS::Print("Firing callback 2.\n");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020805 callback_fired ^= 2; // Toggle second bit.
20806}
20807
20808
Ben Murdoch097c5b22016-05-18 11:27:45 +010020809void BeforeCallEnteredCallback1(v8::Isolate*) {
20810 v8::base::OS::Print("Firing before call entered callback 1.\n");
20811 before_call_entered_callback_count1++;
20812}
20813
20814
20815void BeforeCallEnteredCallback2(v8::Isolate*) {
20816 v8::base::OS::Print("Firing before call entered callback 2.\n");
20817 before_call_entered_callback_count2++;
20818}
20819
20820
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020821void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020822 int32_t level =
20823 args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020824 if (level < 3) {
20825 level++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020826 v8::base::OS::Print("Entering recursion level %d.\n", level);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020827 char script[64];
20828 i::Vector<char> script_vector(script, sizeof(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020829 i::SNPrintF(script_vector, "recursion(%d)", level);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020830 CompileRun(script_vector.start());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020831 v8::base::OS::Print("Leaving recursion level %d.\n", level);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020832 CHECK_EQ(0, callback_fired);
20833 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020834 v8::base::OS::Print("Recursion ends.\n");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020835 CHECK_EQ(0, callback_fired);
20836 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020837}
20838
20839
20840TEST(CallCompletedCallback) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020841 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020842 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020843 v8::Local<v8::FunctionTemplate> recursive_runtime =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020844 v8::FunctionTemplate::New(env->GetIsolate(), RecursiveCall);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020845 env->Global()
20846 ->Set(env.local(), v8_str("recursion"),
20847 recursive_runtime->GetFunction(env.local()).ToLocalChecked())
20848 .FromJust();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020849 // Adding the same callback a second time has no effect.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020850 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
20851 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
20852 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback2);
Ben Murdoch097c5b22016-05-18 11:27:45 +010020853 env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback1);
20854 env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback2);
20855 env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020856 v8::base::OS::Print("--- Script (1) ---\n");
Ben Murdoch097c5b22016-05-18 11:27:45 +010020857 callback_fired = 0;
20858 before_call_entered_callback_count1 = 0;
20859 before_call_entered_callback_count2 = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020860 Local<Script> script =
20861 v8::Script::Compile(env.local(), v8_str("recursion(0)")).ToLocalChecked();
20862 script->Run(env.local()).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020863 CHECK_EQ(3, callback_fired);
Ben Murdoch097c5b22016-05-18 11:27:45 +010020864 CHECK_EQ(4, before_call_entered_callback_count1);
20865 CHECK_EQ(4, before_call_entered_callback_count2);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020866
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020867 v8::base::OS::Print("\n--- Script (2) ---\n");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020868 callback_fired = 0;
Ben Murdoch097c5b22016-05-18 11:27:45 +010020869 before_call_entered_callback_count1 = 0;
20870 before_call_entered_callback_count2 = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020871 env->GetIsolate()->RemoveCallCompletedCallback(CallCompletedCallback1);
Ben Murdoch097c5b22016-05-18 11:27:45 +010020872 env->GetIsolate()->RemoveBeforeCallEnteredCallback(
20873 BeforeCallEnteredCallback1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020874 script->Run(env.local()).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020875 CHECK_EQ(2, callback_fired);
Ben Murdoch097c5b22016-05-18 11:27:45 +010020876 CHECK_EQ(0, before_call_entered_callback_count1);
20877 CHECK_EQ(4, before_call_entered_callback_count2);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020878
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020879 v8::base::OS::Print("\n--- Function ---\n");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020880 callback_fired = 0;
Ben Murdoch097c5b22016-05-18 11:27:45 +010020881 before_call_entered_callback_count1 = 0;
20882 before_call_entered_callback_count2 = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020883 Local<Function> recursive_function = Local<Function>::Cast(
20884 env->Global()->Get(env.local(), v8_str("recursion")).ToLocalChecked());
20885 v8::Local<Value> args[] = {v8_num(0)};
20886 recursive_function->Call(env.local(), env->Global(), 1, args)
20887 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020888 CHECK_EQ(2, callback_fired);
Ben Murdoch097c5b22016-05-18 11:27:45 +010020889 CHECK_EQ(0, before_call_entered_callback_count1);
20890 CHECK_EQ(4, before_call_entered_callback_count2);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020891}
20892
20893
Ben Murdoch097c5b22016-05-18 11:27:45 +010020894void CallCompletedCallbackNoException(v8::Isolate*) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020895 v8::HandleScope scope(CcTest::isolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020896 CompileRun("1+1;");
20897}
20898
20899
Ben Murdoch097c5b22016-05-18 11:27:45 +010020900void CallCompletedCallbackException(v8::Isolate*) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020901 v8::HandleScope scope(CcTest::isolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020902 CompileRun("throw 'second exception';");
20903}
20904
20905
20906TEST(CallCompletedCallbackOneException) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020907 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020908 v8::HandleScope scope(env->GetIsolate());
20909 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackNoException);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020910 CompileRun("throw 'exception';");
20911}
20912
20913
20914TEST(CallCompletedCallbackTwoExceptions) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020915 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020916 v8::HandleScope scope(env->GetIsolate());
20917 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackException);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020918 CompileRun("throw 'first exception';");
20919}
20920
20921
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020922static void MicrotaskOne(const v8::FunctionCallbackInfo<Value>& info) {
20923 v8::HandleScope scope(info.GetIsolate());
20924 CompileRun("ext1Calls++;");
20925}
20926
20927
20928static void MicrotaskTwo(const v8::FunctionCallbackInfo<Value>& info) {
20929 v8::HandleScope scope(info.GetIsolate());
20930 CompileRun("ext2Calls++;");
20931}
20932
20933
20934void* g_passed_to_three = NULL;
20935
20936
20937static void MicrotaskThree(void* data) {
20938 g_passed_to_three = data;
20939}
20940
20941
20942TEST(EnqueueMicrotask) {
20943 LocalContext env;
20944 v8::HandleScope scope(env->GetIsolate());
20945 CompileRun(
20946 "var ext1Calls = 0;"
20947 "var ext2Calls = 0;");
20948 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020949 CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20950 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020951
20952 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020953 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020954 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020955 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20956 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020957
20958 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020959 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020960 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020961 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020962 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020963 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20964 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020965
20966 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020967 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020968 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020969 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20970 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020971
20972 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020973 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20974 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020975
20976 g_passed_to_three = NULL;
20977 env->GetIsolate()->EnqueueMicrotask(MicrotaskThree);
20978 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020979 CHECK(!g_passed_to_three);
20980 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20981 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020982
20983 int dummy;
20984 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020985 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020986 env->GetIsolate()->EnqueueMicrotask(MicrotaskThree, &dummy);
20987 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020988 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020989 CompileRun("1+1;");
20990 CHECK_EQ(&dummy, g_passed_to_three);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020991 CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20992 CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020993 g_passed_to_three = NULL;
20994}
20995
20996
20997static void MicrotaskExceptionOne(
20998 const v8::FunctionCallbackInfo<Value>& info) {
20999 v8::HandleScope scope(info.GetIsolate());
21000 CompileRun("exception1Calls++;");
21001 info.GetIsolate()->ThrowException(
21002 v8::Exception::Error(v8_str("first")));
21003}
21004
21005
21006static void MicrotaskExceptionTwo(
21007 const v8::FunctionCallbackInfo<Value>& info) {
21008 v8::HandleScope scope(info.GetIsolate());
21009 CompileRun("exception2Calls++;");
21010 info.GetIsolate()->ThrowException(
21011 v8::Exception::Error(v8_str("second")));
21012}
21013
21014
21015TEST(RunMicrotasksIgnoresThrownExceptions) {
21016 LocalContext env;
21017 v8::Isolate* isolate = env->GetIsolate();
21018 v8::HandleScope scope(isolate);
21019 CompileRun(
21020 "var exception1Calls = 0;"
21021 "var exception2Calls = 0;");
21022 isolate->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021023 Function::New(env.local(), MicrotaskExceptionOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021024 isolate->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021025 Function::New(env.local(), MicrotaskExceptionTwo).ToLocalChecked());
21026 TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021027 CompileRun("1+1;");
21028 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021029 CHECK_EQ(1,
21030 CompileRun("exception1Calls")->Int32Value(env.local()).FromJust());
21031 CHECK_EQ(1,
21032 CompileRun("exception2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021033}
21034
21035
21036TEST(SetAutorunMicrotasks) {
21037 LocalContext env;
21038 v8::HandleScope scope(env->GetIsolate());
21039 CompileRun(
21040 "var ext1Calls = 0;"
21041 "var ext2Calls = 0;");
21042 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021043 CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21044 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021045
21046 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021047 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021048 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021049 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21050 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021051
21052 env->GetIsolate()->SetAutorunMicrotasks(false);
21053 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021054 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021055 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021056 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021057 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021058 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21059 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021060
21061 env->GetIsolate()->RunMicrotasks();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021062 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21063 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021064
21065 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021066 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021067 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021068 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21069 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021070
21071 env->GetIsolate()->RunMicrotasks();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021072 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21073 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021074
21075 env->GetIsolate()->SetAutorunMicrotasks(true);
21076 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021077 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021078 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021079 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21080 CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021081
21082 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021083 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021084 {
21085 v8::Isolate::SuppressMicrotaskExecutionScope scope(env->GetIsolate());
21086 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021087 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21088 CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021089 }
21090
21091 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021092 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21093 CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021094}
21095
21096
21097TEST(RunMicrotasksWithoutEnteringContext) {
21098 v8::Isolate* isolate = CcTest::isolate();
21099 HandleScope handle_scope(isolate);
21100 isolate->SetAutorunMicrotasks(false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021101 Local<Context> context = Context::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021102 {
21103 Context::Scope context_scope(context);
21104 CompileRun("var ext1Calls = 0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021105 isolate->EnqueueMicrotask(
21106 Function::New(context, MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021107 }
21108 isolate->RunMicrotasks();
21109 {
21110 Context::Scope context_scope(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021111 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021112 }
21113 isolate->SetAutorunMicrotasks(true);
21114}
21115
21116
21117static void DebugEventInObserver(const v8::Debug::EventDetails& event_details) {
21118 v8::DebugEvent event = event_details.GetEvent();
21119 if (event != v8::Break) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021120 Local<Object> exec_state = event_details.GetExecutionState();
21121 Local<Context> context = CcTest::isolate()->GetCurrentContext();
21122 Local<Value> break_id =
21123 exec_state->Get(context, v8_str("break_id")).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021124 CompileRun("function f(id) { new FrameDetails(id, 0); }");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021125 Local<Function> fun = Local<Function>::Cast(
21126 CcTest::global()->Get(context, v8_str("f")).ToLocalChecked());
21127 fun->Call(context, CcTest::global(), 1, &break_id).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021128}
21129
21130
21131TEST(Regress385349) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021132 i::FLAG_harmony_object_observe = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021133 i::FLAG_allow_natives_syntax = true;
21134 v8::Isolate* isolate = CcTest::isolate();
21135 HandleScope handle_scope(isolate);
21136 isolate->SetAutorunMicrotasks(false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021137 Local<Context> context = Context::New(isolate);
21138 v8::Debug::SetDebugEventListener(isolate, DebugEventInObserver);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021139 {
21140 Context::Scope context_scope(context);
21141 CompileRun("var obj = {};"
21142 "Object.observe(obj, function(changes) { debugger; });"
21143 "obj.a = 0;");
21144 }
21145 isolate->RunMicrotasks();
21146 isolate->SetAutorunMicrotasks(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021147 v8::Debug::SetDebugEventListener(isolate, nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021148}
21149
21150
Emily Bernierd0a1eb72015-03-24 16:35:39 -040021151#ifdef ENABLE_DISASSEMBLER
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021152static int probes_counter = 0;
21153static int misses_counter = 0;
21154static int updates_counter = 0;
21155
21156
21157static int* LookupCounter(const char* name) {
21158 if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
21159 return &probes_counter;
21160 } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
21161 return &misses_counter;
21162 } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
21163 return &updates_counter;
21164 }
21165 return NULL;
21166}
21167
21168
21169static const char* kMegamorphicTestProgram =
21170 "function ClassA() { };"
21171 "function ClassB() { };"
21172 "ClassA.prototype.foo = function() { };"
21173 "ClassB.prototype.foo = function() { };"
21174 "function fooify(obj) { obj.foo(); };"
21175 "var a = new ClassA();"
21176 "var b = new ClassB();"
21177 "for (var i = 0; i < 10000; i++) {"
21178 " fooify(a);"
21179 " fooify(b);"
21180 "}";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021181#endif
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021182
21183
21184static void StubCacheHelper(bool primary) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040021185#ifdef ENABLE_DISASSEMBLER
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021186 i::FLAG_native_code_counters = true;
21187 if (primary) {
21188 i::FLAG_test_primary_stub_cache = true;
21189 } else {
21190 i::FLAG_test_secondary_stub_cache = true;
21191 }
21192 i::FLAG_crankshaft = false;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021193 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021194 env->GetIsolate()->SetCounterFunction(LookupCounter);
21195 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021196 int initial_probes = probes_counter;
21197 int initial_misses = misses_counter;
21198 int initial_updates = updates_counter;
21199 CompileRun(kMegamorphicTestProgram);
21200 int probes = probes_counter - initial_probes;
21201 int misses = misses_counter - initial_misses;
21202 int updates = updates_counter - initial_updates;
21203 CHECK_LT(updates, 10);
21204 CHECK_LT(misses, 10);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021205 // TODO(verwaest): Update this test to overflow the degree of polymorphism
21206 // before megamorphism. The number of probes will only work once we teach the
21207 // serializer to embed references to counters in the stubs, given that the
21208 // megamorphic_stub_cache_probes is updated in a snapshot-generated stub.
21209 CHECK_GE(probes, 0);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021210#endif
21211}
21212
21213
21214TEST(SecondaryStubCache) {
21215 StubCacheHelper(true);
21216}
21217
21218
21219TEST(PrimaryStubCache) {
21220 StubCacheHelper(false);
21221}
21222
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021223
21224#ifdef DEBUG
21225static int cow_arrays_created_runtime = 0;
21226
21227
21228static int* LookupCounterCOWArrays(const char* name) {
21229 if (strcmp(name, "c:V8.COWArraysCreatedRuntime") == 0) {
21230 return &cow_arrays_created_runtime;
21231 }
21232 return NULL;
21233}
21234#endif
21235
21236
21237TEST(CheckCOWArraysCreatedRuntimeCounter) {
21238#ifdef DEBUG
21239 i::FLAG_native_code_counters = true;
21240 LocalContext env;
21241 env->GetIsolate()->SetCounterFunction(LookupCounterCOWArrays);
21242 v8::HandleScope scope(env->GetIsolate());
21243 int initial_cow_arrays = cow_arrays_created_runtime;
21244 CompileRun("var o = [1, 2, 3];");
21245 CHECK_EQ(1, cow_arrays_created_runtime - initial_cow_arrays);
21246 CompileRun("var o = {foo: [4, 5, 6], bar: [3, 0]};");
21247 CHECK_EQ(3, cow_arrays_created_runtime - initial_cow_arrays);
21248 CompileRun("var o = {foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'};");
21249 CHECK_EQ(4, cow_arrays_created_runtime - initial_cow_arrays);
21250#endif
21251}
21252
21253
21254TEST(StaticGetters) {
21255 LocalContext context;
21256 i::Factory* factory = CcTest::i_isolate()->factory();
21257 v8::Isolate* isolate = CcTest::isolate();
21258 v8::HandleScope scope(isolate);
21259 i::Handle<i::Object> undefined_value = factory->undefined_value();
21260 CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
21261 i::Handle<i::Object> null_value = factory->null_value();
21262 CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
21263 i::Handle<i::Object> true_value = factory->true_value();
21264 CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
21265 i::Handle<i::Object> false_value = factory->false_value();
21266 CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
21267}
21268
21269
21270UNINITIALIZED_TEST(IsolateEmbedderData) {
21271 CcTest::DisableAutomaticDispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021272 v8::Isolate::CreateParams create_params;
21273 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
21274 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021275 isolate->Enter();
21276 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
21277 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021278 CHECK(!isolate->GetData(slot));
21279 CHECK(!i_isolate->GetData(slot));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021280 }
21281 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
21282 void* data = reinterpret_cast<void*>(0xacce55ed + slot);
21283 isolate->SetData(slot, data);
21284 }
21285 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
21286 void* data = reinterpret_cast<void*>(0xacce55ed + slot);
21287 CHECK_EQ(data, isolate->GetData(slot));
21288 CHECK_EQ(data, i_isolate->GetData(slot));
21289 }
21290 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
21291 void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
21292 isolate->SetData(slot, data);
21293 }
21294 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
21295 void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
21296 CHECK_EQ(data, isolate->GetData(slot));
21297 CHECK_EQ(data, i_isolate->GetData(slot));
21298 }
21299 isolate->Exit();
21300 isolate->Dispose();
21301}
21302
21303
21304TEST(StringEmpty) {
21305 LocalContext context;
21306 i::Factory* factory = CcTest::i_isolate()->factory();
21307 v8::Isolate* isolate = CcTest::isolate();
21308 v8::HandleScope scope(isolate);
21309 i::Handle<i::Object> empty_string = factory->empty_string();
21310 CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
21311}
21312
21313
21314static int instance_checked_getter_count = 0;
21315static void InstanceCheckedGetter(
21316 Local<String> name,
21317 const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021318 CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
21319 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021320 instance_checked_getter_count++;
21321 info.GetReturnValue().Set(v8_num(11));
21322}
21323
21324
21325static int instance_checked_setter_count = 0;
21326static void InstanceCheckedSetter(Local<String> name,
21327 Local<Value> value,
21328 const v8::PropertyCallbackInfo<void>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021329 CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
21330 .FromJust());
21331 CHECK(value->Equals(info.GetIsolate()->GetCurrentContext(), v8_num(23))
21332 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021333 instance_checked_setter_count++;
21334}
21335
21336
21337static void CheckInstanceCheckedResult(int getters, int setters,
21338 bool expects_callbacks,
21339 TryCatch* try_catch) {
21340 if (expects_callbacks) {
21341 CHECK(!try_catch->HasCaught());
21342 CHECK_EQ(getters, instance_checked_getter_count);
21343 CHECK_EQ(setters, instance_checked_setter_count);
21344 } else {
21345 CHECK(try_catch->HasCaught());
21346 CHECK_EQ(0, instance_checked_getter_count);
21347 CHECK_EQ(0, instance_checked_setter_count);
21348 }
21349 try_catch->Reset();
21350}
21351
21352
21353static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
21354 instance_checked_getter_count = 0;
21355 instance_checked_setter_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021356 TryCatch try_catch(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021357
21358 // Test path through generic runtime code.
21359 CompileRun("obj.foo");
21360 CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
21361 CompileRun("obj.foo = 23");
21362 CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
21363
21364 // Test path through generated LoadIC and StoredIC.
21365 CompileRun("function test_get(o) { o.foo; }"
21366 "test_get(obj);");
21367 CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
21368 CompileRun("test_get(obj);");
21369 CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
21370 CompileRun("test_get(obj);");
21371 CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
21372 CompileRun("function test_set(o) { o.foo = 23; }"
21373 "test_set(obj);");
21374 CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
21375 CompileRun("test_set(obj);");
21376 CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
21377 CompileRun("test_set(obj);");
21378 CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
21379
21380 // Test path through optimized code.
21381 CompileRun("%OptimizeFunctionOnNextCall(test_get);"
21382 "test_get(obj);");
21383 CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
21384 CompileRun("%OptimizeFunctionOnNextCall(test_set);"
21385 "test_set(obj);");
21386 CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
21387
21388 // Cleanup so that closures start out fresh in next check.
21389 CompileRun("%DeoptimizeFunction(test_get);"
21390 "%ClearFunctionTypeFeedback(test_get);"
21391 "%DeoptimizeFunction(test_set);"
21392 "%ClearFunctionTypeFeedback(test_set);");
21393}
21394
21395
21396THREADED_TEST(InstanceCheckOnInstanceAccessor) {
21397 v8::internal::FLAG_allow_natives_syntax = true;
21398 LocalContext context;
21399 v8::HandleScope scope(context->GetIsolate());
21400
21401 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
21402 Local<ObjectTemplate> inst = templ->InstanceTemplate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021403 inst->SetAccessor(v8_str("foo"), InstanceCheckedGetter, InstanceCheckedSetter,
21404 Local<Value>(), v8::DEFAULT, v8::None,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021405 v8::AccessorSignature::New(context->GetIsolate(), templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021406 CHECK(context->Global()
21407 ->Set(context.local(), v8_str("f"),
21408 templ->GetFunction(context.local()).ToLocalChecked())
21409 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021410
21411 printf("Testing positive ...\n");
21412 CompileRun("var obj = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021413 CHECK(templ->HasInstance(
21414 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021415 CheckInstanceCheckedAccessors(true);
21416
21417 printf("Testing negative ...\n");
21418 CompileRun("var obj = {};"
21419 "obj.__proto__ = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021420 CHECK(!templ->HasInstance(
21421 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021422 CheckInstanceCheckedAccessors(false);
21423}
21424
21425
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021426static void EmptyInterceptorGetter(
21427 Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {}
21428
21429
21430static void EmptyInterceptorSetter(
21431 Local<String> name, Local<Value> value,
21432 const v8::PropertyCallbackInfo<v8::Value>& info) {}
21433
21434
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021435THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
21436 v8::internal::FLAG_allow_natives_syntax = true;
21437 LocalContext context;
21438 v8::HandleScope scope(context->GetIsolate());
21439
21440 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
21441 Local<ObjectTemplate> inst = templ->InstanceTemplate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021442 templ->InstanceTemplate()->SetNamedPropertyHandler(EmptyInterceptorGetter,
21443 EmptyInterceptorSetter);
21444 inst->SetAccessor(v8_str("foo"), InstanceCheckedGetter, InstanceCheckedSetter,
21445 Local<Value>(), v8::DEFAULT, v8::None,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021446 v8::AccessorSignature::New(context->GetIsolate(), templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021447 CHECK(context->Global()
21448 ->Set(context.local(), v8_str("f"),
21449 templ->GetFunction(context.local()).ToLocalChecked())
21450 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021451
21452 printf("Testing positive ...\n");
21453 CompileRun("var obj = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021454 CHECK(templ->HasInstance(
21455 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021456 CheckInstanceCheckedAccessors(true);
21457
21458 printf("Testing negative ...\n");
21459 CompileRun("var obj = {};"
21460 "obj.__proto__ = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021461 CHECK(!templ->HasInstance(
21462 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021463 CheckInstanceCheckedAccessors(false);
21464}
21465
21466
21467THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
21468 v8::internal::FLAG_allow_natives_syntax = true;
21469 LocalContext context;
21470 v8::HandleScope scope(context->GetIsolate());
21471
21472 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
21473 Local<ObjectTemplate> proto = templ->PrototypeTemplate();
21474 proto->SetAccessor(v8_str("foo"), InstanceCheckedGetter,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021475 InstanceCheckedSetter, Local<Value>(), v8::DEFAULT,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021476 v8::None,
21477 v8::AccessorSignature::New(context->GetIsolate(), templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021478 CHECK(context->Global()
21479 ->Set(context.local(), v8_str("f"),
21480 templ->GetFunction(context.local()).ToLocalChecked())
21481 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021482
21483 printf("Testing positive ...\n");
21484 CompileRun("var obj = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021485 CHECK(templ->HasInstance(
21486 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021487 CheckInstanceCheckedAccessors(true);
21488
21489 printf("Testing negative ...\n");
21490 CompileRun("var obj = {};"
21491 "obj.__proto__ = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021492 CHECK(!templ->HasInstance(
21493 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021494 CheckInstanceCheckedAccessors(false);
21495
21496 printf("Testing positive with modified prototype chain ...\n");
21497 CompileRun("var obj = new f();"
21498 "var pro = {};"
21499 "pro.__proto__ = obj.__proto__;"
21500 "obj.__proto__ = pro;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021501 CHECK(templ->HasInstance(
21502 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021503 CheckInstanceCheckedAccessors(true);
21504}
21505
21506
21507TEST(TryFinallyMessage) {
21508 LocalContext context;
21509 v8::HandleScope scope(context->GetIsolate());
21510 {
21511 // Test that the original error message is not lost if there is a
21512 // recursive call into Javascript is done in the finally block, e.g. to
21513 // initialize an IC. (crbug.com/129171)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021514 TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021515 const char* trigger_ic =
21516 "try { \n"
21517 " throw new Error('test'); \n"
21518 "} finally { \n"
21519 " var x = 0; \n"
21520 " x++; \n" // Trigger an IC initialization here.
21521 "} \n";
21522 CompileRun(trigger_ic);
21523 CHECK(try_catch.HasCaught());
21524 Local<Message> message = try_catch.Message();
21525 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021526 CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021527 }
21528
21529 {
21530 // Test that the original exception message is indeed overwritten if
21531 // a new error is thrown in the finally block.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021532 TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021533 const char* throw_again =
21534 "try { \n"
21535 " throw new Error('test'); \n"
21536 "} finally { \n"
21537 " var x = 0; \n"
21538 " x++; \n"
21539 " throw new Error('again'); \n" // This is the new uncaught error.
21540 "} \n";
21541 CompileRun(throw_again);
21542 CHECK(try_catch.HasCaught());
21543 Local<Message> message = try_catch.Message();
21544 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021545 CHECK_EQ(6, message->GetLineNumber(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021546 }
21547}
21548
21549
21550static void Helper137002(bool do_store,
21551 bool polymorphic,
21552 bool remove_accessor,
21553 bool interceptor) {
21554 LocalContext context;
21555 Local<ObjectTemplate> templ = ObjectTemplate::New(context->GetIsolate());
21556 if (interceptor) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040021557 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(FooGetInterceptor,
21558 FooSetInterceptor));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021559 } else {
21560 templ->SetAccessor(v8_str("foo"),
21561 GetterWhichReturns42,
21562 SetterWhichSetsYOnThisTo23);
21563 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021564 CHECK(context->Global()
21565 ->Set(context.local(), v8_str("obj"),
21566 templ->NewInstance(context.local()).ToLocalChecked())
21567 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021568
21569 // Turn monomorphic on slow object with native accessor, then turn
21570 // polymorphic, finally optimize to create negative lookup and fail.
21571 CompileRun(do_store ?
21572 "function f(x) { x.foo = void 0; }" :
21573 "function f(x) { return x.foo; }");
21574 CompileRun("obj.y = void 0;");
21575 if (!interceptor) {
21576 CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
21577 }
21578 CompileRun("obj.__proto__ = null;"
21579 "f(obj); f(obj); f(obj);");
21580 if (polymorphic) {
21581 CompileRun("f({});");
21582 }
21583 CompileRun("obj.y = void 0;"
21584 "%OptimizeFunctionOnNextCall(f);");
21585 if (remove_accessor) {
21586 CompileRun("delete obj.foo;");
21587 }
21588 CompileRun("var result = f(obj);");
21589 if (do_store) {
21590 CompileRun("result = obj.y;");
21591 }
21592 if (remove_accessor && !interceptor) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021593 CHECK(context->Global()
21594 ->Get(context.local(), v8_str("result"))
21595 .ToLocalChecked()
21596 ->IsUndefined());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021597 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021598 CHECK_EQ(do_store ? 23 : 42, context->Global()
21599 ->Get(context.local(), v8_str("result"))
21600 .ToLocalChecked()
21601 ->Int32Value(context.local())
21602 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021603 }
21604}
21605
21606
21607THREADED_TEST(Regress137002a) {
21608 i::FLAG_allow_natives_syntax = true;
21609 i::FLAG_compilation_cache = false;
21610 v8::HandleScope scope(CcTest::isolate());
21611 for (int i = 0; i < 16; i++) {
21612 Helper137002(i & 8, i & 4, i & 2, i & 1);
21613 }
21614}
21615
21616
21617THREADED_TEST(Regress137002b) {
21618 i::FLAG_allow_natives_syntax = true;
21619 LocalContext context;
21620 v8::Isolate* isolate = context->GetIsolate();
21621 v8::HandleScope scope(isolate);
21622 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
21623 templ->SetAccessor(v8_str("foo"),
21624 GetterWhichReturns42,
21625 SetterWhichSetsYOnThisTo23);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021626 CHECK(context->Global()
21627 ->Set(context.local(), v8_str("obj"),
21628 templ->NewInstance(context.local()).ToLocalChecked())
21629 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021630
21631 // Turn monomorphic on slow object with native accessor, then just
21632 // delete the property and fail.
21633 CompileRun("function load(x) { return x.foo; }"
21634 "function store(x) { x.foo = void 0; }"
21635 "function keyed_load(x, key) { return x[key]; }"
21636 // Second version of function has a different source (add void 0)
21637 // so that it does not share code with the first version. This
21638 // ensures that the ICs are monomorphic.
21639 "function load2(x) { void 0; return x.foo; }"
21640 "function store2(x) { void 0; x.foo = void 0; }"
21641 "function keyed_load2(x, key) { void 0; return x[key]; }"
21642
21643 "obj.y = void 0;"
21644 "obj.__proto__ = null;"
21645 "var subobj = {};"
21646 "subobj.y = void 0;"
21647 "subobj.__proto__ = obj;"
21648 "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
21649
21650 // Make the ICs monomorphic.
21651 "load(obj); load(obj);"
21652 "load2(subobj); load2(subobj);"
21653 "store(obj); store(obj);"
21654 "store2(subobj); store2(subobj);"
21655 "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
21656 "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
21657
21658 // Actually test the shiny new ICs and better not crash. This
21659 // serves as a regression test for issue 142088 as well.
21660 "load(obj);"
21661 "load2(subobj);"
21662 "store(obj);"
21663 "store2(subobj);"
21664 "keyed_load(obj, 'foo');"
21665 "keyed_load2(subobj, 'foo');"
21666
21667 // Delete the accessor. It better not be called any more now.
21668 "delete obj.foo;"
21669 "obj.y = void 0;"
21670 "subobj.y = void 0;"
21671
21672 "var load_result = load(obj);"
21673 "var load_result2 = load2(subobj);"
21674 "var keyed_load_result = keyed_load(obj, 'foo');"
21675 "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
21676 "store(obj);"
21677 "store2(subobj);"
21678 "var y_from_obj = obj.y;"
21679 "var y_from_subobj = subobj.y;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021680 CHECK(context->Global()
21681 ->Get(context.local(), v8_str("load_result"))
21682 .ToLocalChecked()
21683 ->IsUndefined());
21684 CHECK(context->Global()
21685 ->Get(context.local(), v8_str("load_result2"))
21686 .ToLocalChecked()
21687 ->IsUndefined());
21688 CHECK(context->Global()
21689 ->Get(context.local(), v8_str("keyed_load_result"))
21690 .ToLocalChecked()
21691 ->IsUndefined());
21692 CHECK(context->Global()
21693 ->Get(context.local(), v8_str("keyed_load_result2"))
21694 .ToLocalChecked()
21695 ->IsUndefined());
21696 CHECK(context->Global()
21697 ->Get(context.local(), v8_str("y_from_obj"))
21698 .ToLocalChecked()
21699 ->IsUndefined());
21700 CHECK(context->Global()
21701 ->Get(context.local(), v8_str("y_from_subobj"))
21702 .ToLocalChecked()
21703 ->IsUndefined());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021704}
21705
21706
21707THREADED_TEST(Regress142088) {
21708 i::FLAG_allow_natives_syntax = true;
21709 LocalContext context;
21710 v8::Isolate* isolate = context->GetIsolate();
21711 v8::HandleScope scope(isolate);
21712 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
21713 templ->SetAccessor(v8_str("foo"),
21714 GetterWhichReturns42,
21715 SetterWhichSetsYOnThisTo23);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021716 CHECK(context->Global()
21717 ->Set(context.local(), v8_str("obj"),
21718 templ->NewInstance(context.local()).ToLocalChecked())
21719 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021720
21721 CompileRun("function load(x) { return x.foo; }"
21722 "var o = Object.create(obj);"
21723 "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
21724 "load(o); load(o); load(o); load(o);");
21725}
21726
21727
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021728THREADED_TEST(Regress137496) {
21729 i::FLAG_expose_gc = true;
21730 LocalContext context;
21731 v8::HandleScope scope(context->GetIsolate());
21732
21733 // Compile a try-finally clause where the finally block causes a GC
21734 // while there still is a message pending for external reporting.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021735 TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021736 try_catch.SetVerbose(true);
21737 CompileRun("try { throw new Error(); } finally { gc(); }");
21738 CHECK(try_catch.HasCaught());
21739}
21740
21741
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021742THREADED_TEST(Regress157124) {
21743 LocalContext context;
21744 v8::Isolate* isolate = context->GetIsolate();
21745 v8::HandleScope scope(isolate);
21746 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021747 Local<Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021748 obj->GetIdentityHash();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021749 obj->DeletePrivate(context.local(),
21750 v8::Private::ForApi(isolate, v8_str("Bug")))
21751 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021752}
21753
21754
21755THREADED_TEST(Regress2535) {
21756 LocalContext context;
21757 v8::HandleScope scope(context->GetIsolate());
21758 Local<Value> set_value = CompileRun("new Set();");
21759 Local<Object> set_object(Local<Object>::Cast(set_value));
21760 CHECK_EQ(0, set_object->InternalFieldCount());
21761 Local<Value> map_value = CompileRun("new Map();");
21762 Local<Object> map_object(Local<Object>::Cast(map_value));
21763 CHECK_EQ(0, map_object->InternalFieldCount());
21764}
21765
21766
21767THREADED_TEST(Regress2746) {
21768 LocalContext context;
21769 v8::Isolate* isolate = context->GetIsolate();
21770 v8::HandleScope scope(isolate);
21771 Local<Object> obj = Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021772 Local<v8::Private> key = v8::Private::New(isolate, v8_str("key"));
21773 CHECK(
21774 obj->SetPrivate(context.local(), key, v8::Undefined(isolate)).FromJust());
21775 Local<Value> value = obj->GetPrivate(context.local(), key).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021776 CHECK(!value.IsEmpty());
21777 CHECK(value->IsUndefined());
21778}
21779
21780
21781THREADED_TEST(Regress260106) {
21782 LocalContext context;
21783 v8::Isolate* isolate = context->GetIsolate();
21784 v8::HandleScope scope(isolate);
21785 Local<FunctionTemplate> templ = FunctionTemplate::New(isolate,
21786 DummyCallHandler);
21787 CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021788 Local<Function> function =
21789 templ->GetFunction(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021790 CHECK(!function.IsEmpty());
21791 CHECK(function->IsFunction());
21792}
21793
21794
21795THREADED_TEST(JSONParseObject) {
21796 LocalContext context;
21797 HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021798 Local<Value> obj =
21799 v8::JSON::Parse(context->GetIsolate(), v8_str("{\"x\":42}"))
21800 .ToLocalChecked();
21801 Local<Object> global = context->Global();
21802 global->Set(context.local(), v8_str("obj"), obj).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021803 ExpectString("JSON.stringify(obj)", "{\"x\":42}");
21804}
21805
21806
21807THREADED_TEST(JSONParseNumber) {
21808 LocalContext context;
21809 HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021810 Local<Value> obj =
21811 v8::JSON::Parse(context->GetIsolate(), v8_str("42")).ToLocalChecked();
21812 Local<Object> global = context->Global();
21813 global->Set(context.local(), v8_str("obj"), obj).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021814 ExpectString("JSON.stringify(obj)", "42");
21815}
21816
21817
21818#if V8_OS_POSIX && !V8_OS_NACL
21819class ThreadInterruptTest {
21820 public:
21821 ThreadInterruptTest() : sem_(0), sem_value_(0) { }
21822 ~ThreadInterruptTest() {}
21823
21824 void RunTest() {
21825 InterruptThread i_thread(this);
21826 i_thread.Start();
21827
21828 sem_.Wait();
21829 CHECK_EQ(kExpectedValue, sem_value_);
21830 }
21831
21832 private:
21833 static const int kExpectedValue = 1;
21834
21835 class InterruptThread : public v8::base::Thread {
21836 public:
21837 explicit InterruptThread(ThreadInterruptTest* test)
21838 : Thread(Options("InterruptThread")), test_(test) {}
21839
21840 virtual void Run() {
21841 struct sigaction action;
21842
21843 // Ensure that we'll enter waiting condition
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021844 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021845
21846 // Setup signal handler
21847 memset(&action, 0, sizeof(action));
21848 action.sa_handler = SignalHandler;
21849 sigaction(SIGCHLD, &action, NULL);
21850
21851 // Send signal
21852 kill(getpid(), SIGCHLD);
21853
21854 // Ensure that if wait has returned because of error
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021855 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021856
21857 // Set value and signal semaphore
21858 test_->sem_value_ = 1;
21859 test_->sem_.Signal();
21860 }
21861
21862 static void SignalHandler(int signal) {
21863 }
21864
21865 private:
21866 ThreadInterruptTest* test_;
21867 };
21868
21869 v8::base::Semaphore sem_;
21870 volatile int sem_value_;
21871};
21872
21873
21874THREADED_TEST(SemaphoreInterruption) {
21875 ThreadInterruptTest().RunTest();
21876}
21877
21878
21879#endif // V8_OS_POSIX
21880
21881
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021882void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
21883 CHECK(false);
21884}
21885
21886
21887TEST(JSONStringifyAccessCheck) {
21888 v8::V8::Initialize();
21889 v8::Isolate* isolate = CcTest::isolate();
21890 v8::HandleScope scope(isolate);
21891
21892 // Create an ObjectTemplate for global objects and install access
21893 // check callbacks that will block access.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021894 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021895 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021896 global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021897
21898 // Create a context and set an x property on it's global object.
21899 LocalContext context0(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021900 v8::Local<v8::Object> global0 = context0->Global();
21901 global0->Set(context0.local(), v8_str("x"), v8_num(42)).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021902 ExpectString("JSON.stringify(this)", "{\"x\":42}");
21903
21904 for (int i = 0; i < 2; i++) {
21905 if (i == 1) {
21906 // Install a toJSON function on the second run.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021907 v8::Local<v8::FunctionTemplate> toJSON =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021908 v8::FunctionTemplate::New(isolate, UnreachableCallback);
21909
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021910 global0->Set(context0.local(), v8_str("toJSON"),
21911 toJSON->GetFunction(context0.local()).ToLocalChecked())
21912 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021913 }
21914 // Create a context with a different security token so that the
21915 // failed access check callback will be called on each access.
21916 LocalContext context1(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021917 CHECK(context1->Global()
21918 ->Set(context1.local(), v8_str("other"), global0)
21919 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021920
21921 CHECK(CompileRun("JSON.stringify(other)").IsEmpty());
21922 CHECK(CompileRun("JSON.stringify({ 'a' : other, 'b' : ['c'] })").IsEmpty());
21923 CHECK(CompileRun("JSON.stringify([other, 'b', 'c'])").IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021924 }
21925}
21926
21927
21928bool access_check_fail_thrown = false;
21929bool catch_callback_called = false;
21930
21931
21932// Failed access check callback that performs a GC on each invocation.
21933void FailedAccessCheckThrows(Local<v8::Object> target,
21934 v8::AccessType type,
21935 Local<v8::Value> data) {
21936 access_check_fail_thrown = true;
21937 i::PrintF("Access check failed. Error thrown.\n");
21938 CcTest::isolate()->ThrowException(
21939 v8::Exception::Error(v8_str("cross context")));
21940}
21941
21942
21943void CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
21944 for (int i = 0; i < args.Length(); i++) {
21945 i::PrintF("%s\n", *String::Utf8Value(args[i]));
21946 }
21947 catch_callback_called = true;
21948}
21949
21950
21951void HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021952 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
21953 CHECK(
21954 args[0]
21955 ->ToObject(context)
21956 .ToLocalChecked()
21957 ->HasOwnProperty(context, args[1]->ToString(context).ToLocalChecked())
21958 .IsNothing());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021959}
21960
21961
21962void CheckCorrectThrow(const char* script) {
21963 // Test that the script, when wrapped into a try-catch, triggers the catch
21964 // clause due to failed access check throwing an exception.
21965 // The subsequent try-catch should run without any exception.
21966 access_check_fail_thrown = false;
21967 catch_callback_called = false;
21968 i::ScopedVector<char> source(1024);
21969 i::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
21970 CompileRun(source.start());
21971 CHECK(access_check_fail_thrown);
21972 CHECK(catch_callback_called);
21973
21974 access_check_fail_thrown = false;
21975 catch_callback_called = false;
21976 CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
21977 CHECK(!access_check_fail_thrown);
21978 CHECK(!catch_callback_called);
21979}
21980
21981
21982TEST(AccessCheckThrows) {
21983 i::FLAG_allow_natives_syntax = true;
21984 v8::V8::Initialize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021985 v8::Isolate* isolate = CcTest::isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021986 isolate->SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021987 v8::HandleScope scope(isolate);
21988
21989 // Create an ObjectTemplate for global objects and install access
21990 // check callbacks that will block access.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021991 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021992 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021993 global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021994
21995 // Create a context and set an x property on it's global object.
21996 LocalContext context0(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021997 v8::Local<v8::Object> global0 = context0->Global();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021998
21999 // Create a context with a different security token so that the
22000 // failed access check callback will be called on each access.
22001 LocalContext context1(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022002 CHECK(context1->Global()
22003 ->Set(context1.local(), v8_str("other"), global0)
22004 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022005
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022006 v8::Local<v8::FunctionTemplate> catcher_fun =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022007 v8::FunctionTemplate::New(isolate, CatcherCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022008 CHECK(context1->Global()
22009 ->Set(context1.local(), v8_str("catcher"),
22010 catcher_fun->GetFunction(context1.local()).ToLocalChecked())
22011 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022012
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022013 v8::Local<v8::FunctionTemplate> has_own_property_fun =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022014 v8::FunctionTemplate::New(isolate, HasOwnPropertyCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022015 CHECK(context1->Global()
22016 ->Set(context1.local(), v8_str("has_own_property"),
22017 has_own_property_fun->GetFunction(context1.local())
22018 .ToLocalChecked())
22019 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022020
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022021 {
22022 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022023 access_check_fail_thrown = false;
22024 CompileRun("other.x;");
22025 CHECK(access_check_fail_thrown);
22026 CHECK(try_catch.HasCaught());
22027 }
22028
22029 CheckCorrectThrow("other.x");
22030 CheckCorrectThrow("other[1]");
22031 CheckCorrectThrow("JSON.stringify(other)");
22032 CheckCorrectThrow("has_own_property(other, 'x')");
22033 CheckCorrectThrow("%GetProperty(other, 'x')");
22034 CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 0)");
22035 CheckCorrectThrow("%AddNamedProperty(other, 'x', 'foo', 1)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022036 CheckCorrectThrow("%DeleteProperty_Sloppy(other, 'x')");
22037 CheckCorrectThrow("%DeleteProperty_Strict(other, 'x')");
22038 CheckCorrectThrow("%DeleteProperty_Sloppy(other, '1')");
22039 CheckCorrectThrow("%DeleteProperty_Strict(other, '1')");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022040 CheckCorrectThrow("%HasOwnProperty(other, 'x')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022041 CheckCorrectThrow("%HasProperty('x', other)");
22042 CheckCorrectThrow("%PropertyIsEnumerable(other, 'x')");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022043 // PROPERTY_ATTRIBUTES_NONE = 0
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022044 CheckCorrectThrow("%DefineAccessorPropertyUnchecked("
22045 "other, 'x', null, null, 1)");
22046
22047 // Reset the failed access check callback so it does not influence
22048 // the other tests.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022049 isolate->SetFailedAccessCheckCallbackFunction(NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022050}
22051
22052
22053class RequestInterruptTestBase {
22054 public:
22055 RequestInterruptTestBase()
22056 : env_(),
22057 isolate_(env_->GetIsolate()),
22058 sem_(0),
22059 warmup_(20000),
22060 should_continue_(true) {
22061 }
22062
22063 virtual ~RequestInterruptTestBase() { }
22064
22065 virtual void StartInterruptThread() = 0;
22066
22067 virtual void TestBody() = 0;
22068
22069 void RunTest() {
22070 StartInterruptThread();
22071
22072 v8::HandleScope handle_scope(isolate_);
22073
22074 TestBody();
22075
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022076 // Verify we arrived here because interruptor was called
22077 // not due to a bug causing us to exit the loop too early.
22078 CHECK(!should_continue());
22079 }
22080
22081 void WakeUpInterruptor() {
22082 sem_.Signal();
22083 }
22084
22085 bool should_continue() const { return should_continue_; }
22086
22087 bool ShouldContinue() {
22088 if (warmup_ > 0) {
22089 if (--warmup_ == 0) {
22090 WakeUpInterruptor();
22091 }
22092 }
22093
22094 return should_continue_;
22095 }
22096
22097 static void ShouldContinueCallback(
22098 const v8::FunctionCallbackInfo<Value>& info) {
22099 RequestInterruptTestBase* test =
22100 reinterpret_cast<RequestInterruptTestBase*>(
22101 info.Data().As<v8::External>()->Value());
22102 info.GetReturnValue().Set(test->ShouldContinue());
22103 }
22104
22105 LocalContext env_;
22106 v8::Isolate* isolate_;
22107 v8::base::Semaphore sem_;
22108 int warmup_;
22109 bool should_continue_;
22110};
22111
22112
22113class RequestInterruptTestBaseWithSimpleInterrupt
22114 : public RequestInterruptTestBase {
22115 public:
22116 RequestInterruptTestBaseWithSimpleInterrupt() : i_thread(this) { }
22117
22118 virtual void StartInterruptThread() {
22119 i_thread.Start();
22120 }
22121
22122 private:
22123 class InterruptThread : public v8::base::Thread {
22124 public:
22125 explicit InterruptThread(RequestInterruptTestBase* test)
22126 : Thread(Options("RequestInterruptTest")), test_(test) {}
22127
22128 virtual void Run() {
22129 test_->sem_.Wait();
22130 test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
22131 }
22132
22133 static void OnInterrupt(v8::Isolate* isolate, void* data) {
22134 reinterpret_cast<RequestInterruptTestBase*>(data)->
22135 should_continue_ = false;
22136 }
22137
22138 private:
22139 RequestInterruptTestBase* test_;
22140 };
22141
22142 InterruptThread i_thread;
22143};
22144
22145
22146class RequestInterruptTestWithFunctionCall
22147 : public RequestInterruptTestBaseWithSimpleInterrupt {
22148 public:
22149 virtual void TestBody() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022150 Local<Function> func = Function::New(env_.local(), ShouldContinueCallback,
22151 v8::External::New(isolate_, this))
22152 .ToLocalChecked();
22153 CHECK(env_->Global()
22154 ->Set(env_.local(), v8_str("ShouldContinue"), func)
22155 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022156
22157 CompileRun("while (ShouldContinue()) { }");
22158 }
22159};
22160
22161
22162class RequestInterruptTestWithMethodCall
22163 : public RequestInterruptTestBaseWithSimpleInterrupt {
22164 public:
22165 virtual void TestBody() {
22166 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
22167 v8::Local<v8::Template> proto = t->PrototypeTemplate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022168 proto->Set(v8_str("shouldContinue"),
Ben Murdoch097c5b22016-05-18 11:27:45 +010022169 FunctionTemplate::New(isolate_, ShouldContinueCallback,
22170 v8::External::New(isolate_, this)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022171 CHECK(env_->Global()
22172 ->Set(env_.local(), v8_str("Klass"),
22173 t->GetFunction(env_.local()).ToLocalChecked())
22174 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022175
22176 CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
22177 }
22178};
22179
22180
22181class RequestInterruptTestWithAccessor
22182 : public RequestInterruptTestBaseWithSimpleInterrupt {
22183 public:
22184 virtual void TestBody() {
22185 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
22186 v8::Local<v8::Template> proto = t->PrototypeTemplate();
22187 proto->SetAccessorProperty(v8_str("shouldContinue"), FunctionTemplate::New(
22188 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022189 CHECK(env_->Global()
22190 ->Set(env_.local(), v8_str("Klass"),
22191 t->GetFunction(env_.local()).ToLocalChecked())
22192 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022193
22194 CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
22195 }
22196};
22197
22198
22199class RequestInterruptTestWithNativeAccessor
22200 : public RequestInterruptTestBaseWithSimpleInterrupt {
22201 public:
22202 virtual void TestBody() {
22203 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
22204 t->InstanceTemplate()->SetNativeDataProperty(
22205 v8_str("shouldContinue"),
22206 &ShouldContinueNativeGetter,
22207 NULL,
22208 v8::External::New(isolate_, this));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022209 CHECK(env_->Global()
22210 ->Set(env_.local(), v8_str("Klass"),
22211 t->GetFunction(env_.local()).ToLocalChecked())
22212 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022213
22214 CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
22215 }
22216
22217 private:
22218 static void ShouldContinueNativeGetter(
22219 Local<String> property,
22220 const v8::PropertyCallbackInfo<v8::Value>& info) {
22221 RequestInterruptTestBase* test =
22222 reinterpret_cast<RequestInterruptTestBase*>(
22223 info.Data().As<v8::External>()->Value());
22224 info.GetReturnValue().Set(test->ShouldContinue());
22225 }
22226};
22227
22228
22229class RequestInterruptTestWithMethodCallAndInterceptor
22230 : public RequestInterruptTestBaseWithSimpleInterrupt {
22231 public:
22232 virtual void TestBody() {
22233 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
22234 v8::Local<v8::Template> proto = t->PrototypeTemplate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022235 proto->Set(v8_str("shouldContinue"),
Ben Murdoch097c5b22016-05-18 11:27:45 +010022236 FunctionTemplate::New(isolate_, ShouldContinueCallback,
22237 v8::External::New(isolate_, this)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022238 v8::Local<v8::ObjectTemplate> instance_template = t->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022239 instance_template->SetHandler(
22240 v8::NamedPropertyHandlerConfiguration(EmptyInterceptor));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022241
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022242 CHECK(env_->Global()
22243 ->Set(env_.local(), v8_str("Klass"),
22244 t->GetFunction(env_.local()).ToLocalChecked())
22245 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022246
22247 CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
22248 }
22249
22250 private:
22251 static void EmptyInterceptor(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022252 Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022253};
22254
22255
22256class RequestInterruptTestWithMathAbs
22257 : public RequestInterruptTestBaseWithSimpleInterrupt {
22258 public:
22259 virtual void TestBody() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022260 env_->Global()
22261 ->Set(env_.local(), v8_str("WakeUpInterruptor"),
22262 Function::New(env_.local(), WakeUpInterruptorCallback,
22263 v8::External::New(isolate_, this))
22264 .ToLocalChecked())
22265 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022266
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022267 env_->Global()
22268 ->Set(env_.local(), v8_str("ShouldContinue"),
22269 Function::New(env_.local(), ShouldContinueCallback,
22270 v8::External::New(isolate_, this))
22271 .ToLocalChecked())
22272 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022273
22274 i::FLAG_allow_natives_syntax = true;
22275 CompileRun("function loopish(o) {"
22276 " var pre = 10;"
22277 " while (o.abs(1) > 0) {"
22278 " if (o.abs(1) >= 0 && !ShouldContinue()) break;"
22279 " if (pre > 0) {"
22280 " if (--pre === 0) WakeUpInterruptor(o === Math);"
22281 " }"
22282 " }"
22283 "}"
22284 "var i = 50;"
22285 "var obj = {abs: function () { return i-- }, x: null};"
22286 "delete obj.x;"
22287 "loopish(obj);"
22288 "%OptimizeFunctionOnNextCall(loopish);"
22289 "loopish(Math);");
22290
22291 i::FLAG_allow_natives_syntax = false;
22292 }
22293
22294 private:
22295 static void WakeUpInterruptorCallback(
22296 const v8::FunctionCallbackInfo<Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022297 if (!info[0]
22298 ->BooleanValue(info.GetIsolate()->GetCurrentContext())
22299 .FromJust()) {
22300 return;
22301 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022302
22303 RequestInterruptTestBase* test =
22304 reinterpret_cast<RequestInterruptTestBase*>(
22305 info.Data().As<v8::External>()->Value());
22306 test->WakeUpInterruptor();
22307 }
22308
22309 static void ShouldContinueCallback(
22310 const v8::FunctionCallbackInfo<Value>& info) {
22311 RequestInterruptTestBase* test =
22312 reinterpret_cast<RequestInterruptTestBase*>(
22313 info.Data().As<v8::External>()->Value());
22314 info.GetReturnValue().Set(test->should_continue());
22315 }
22316};
22317
22318
22319TEST(RequestInterruptTestWithFunctionCall) {
22320 RequestInterruptTestWithFunctionCall().RunTest();
22321}
22322
22323
22324TEST(RequestInterruptTestWithMethodCall) {
22325 RequestInterruptTestWithMethodCall().RunTest();
22326}
22327
22328
22329TEST(RequestInterruptTestWithAccessor) {
22330 RequestInterruptTestWithAccessor().RunTest();
22331}
22332
22333
22334TEST(RequestInterruptTestWithNativeAccessor) {
22335 RequestInterruptTestWithNativeAccessor().RunTest();
22336}
22337
22338
22339TEST(RequestInterruptTestWithMethodCallAndInterceptor) {
22340 RequestInterruptTestWithMethodCallAndInterceptor().RunTest();
22341}
22342
22343
22344TEST(RequestInterruptTestWithMathAbs) {
22345 RequestInterruptTestWithMathAbs().RunTest();
22346}
22347
22348
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022349class RequestMultipleInterrupts : public RequestInterruptTestBase {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022350 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022351 RequestMultipleInterrupts() : i_thread(this), counter_(0) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022352
22353 virtual void StartInterruptThread() {
22354 i_thread.Start();
22355 }
22356
22357 virtual void TestBody() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022358 Local<Function> func = Function::New(env_.local(), ShouldContinueCallback,
22359 v8::External::New(isolate_, this))
22360 .ToLocalChecked();
22361 CHECK(env_->Global()
22362 ->Set(env_.local(), v8_str("ShouldContinue"), func)
22363 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022364
22365 CompileRun("while (ShouldContinue()) { }");
22366 }
22367
22368 private:
22369 class InterruptThread : public v8::base::Thread {
22370 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022371 enum { NUM_INTERRUPTS = 10 };
22372 explicit InterruptThread(RequestMultipleInterrupts* test)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022373 : Thread(Options("RequestInterruptTest")), test_(test) {}
22374
22375 virtual void Run() {
22376 test_->sem_.Wait();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022377 for (int i = 0; i < NUM_INTERRUPTS; i++) {
22378 test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
22379 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022380 }
22381
22382 static void OnInterrupt(v8::Isolate* isolate, void* data) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022383 RequestMultipleInterrupts* test =
22384 reinterpret_cast<RequestMultipleInterrupts*>(data);
22385 test->should_continue_ = ++test->counter_ < NUM_INTERRUPTS;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022386 }
22387
22388 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022389 RequestMultipleInterrupts* test_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022390 };
22391
22392 InterruptThread i_thread;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022393 int counter_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022394};
22395
22396
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022397TEST(RequestMultipleInterrupts) { RequestMultipleInterrupts().RunTest(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022398
22399
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022400static bool interrupt_was_called = false;
22401
22402
22403void SmallScriptsInterruptCallback(v8::Isolate* isolate, void* data) {
22404 interrupt_was_called = true;
22405}
22406
22407
22408TEST(RequestInterruptSmallScripts) {
22409 LocalContext env;
22410 v8::Isolate* isolate = CcTest::isolate();
22411 v8::HandleScope scope(isolate);
22412
22413 interrupt_was_called = false;
22414 isolate->RequestInterrupt(&SmallScriptsInterruptCallback, NULL);
22415 CompileRun("(function(x){return x;})(1);");
22416 CHECK(interrupt_was_called);
22417}
22418
22419
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022420static Local<Value> function_new_expected_env;
22421static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022422 CHECK(
22423 function_new_expected_env->Equals(info.GetIsolate()->GetCurrentContext(),
22424 info.Data())
22425 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022426 info.GetReturnValue().Set(17);
22427}
22428
22429
22430THREADED_TEST(FunctionNew) {
22431 LocalContext env;
22432 v8::Isolate* isolate = env->GetIsolate();
22433 v8::HandleScope scope(isolate);
22434 Local<Object> data = v8::Object::New(isolate);
22435 function_new_expected_env = data;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022436 Local<Function> func =
22437 Function::New(env.local(), FunctionNewCallback, data).ToLocalChecked();
22438 CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022439 Local<Value> result = CompileRun("func();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022440 CHECK(v8::Integer::New(isolate, 17)->Equals(env.local(), result).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022441 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022442 // Verify function not cached
22443 auto serial_number = handle(
22444 i::Smi::cast(i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*func))
22445 ->shared()
22446 ->get_api_func_data()
22447 ->serial_number()),
22448 i_isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +010022449 auto cache = i_isolate->template_instantiations_cache();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022450 CHECK(cache->Lookup(serial_number)->IsTheHole());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022451 // Verify that each Function::New creates a new function instance
22452 Local<Object> data2 = v8::Object::New(isolate);
22453 function_new_expected_env = data2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022454 Local<Function> func2 =
22455 Function::New(env.local(), FunctionNewCallback, data2).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022456 CHECK(!func2->IsNull());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022457 CHECK(!func->Equals(env.local(), func2).FromJust());
22458 CHECK(env->Global()->Set(env.local(), v8_str("func2"), func2).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022459 Local<Value> result2 = CompileRun("func2();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022460 CHECK(v8::Integer::New(isolate, 17)->Equals(env.local(), result2).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022461}
22462
22463
22464TEST(EscapeableHandleScope) {
22465 HandleScope outer_scope(CcTest::isolate());
22466 LocalContext context;
22467 const int runs = 10;
22468 Local<String> values[runs];
22469 for (int i = 0; i < runs; i++) {
22470 v8::EscapableHandleScope inner_scope(CcTest::isolate());
22471 Local<String> value;
22472 if (i != 0) value = v8_str("escape value");
22473 values[i] = inner_scope.Escape(value);
22474 }
22475 for (int i = 0; i < runs; i++) {
22476 Local<String> expected;
22477 if (i != 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022478 CHECK(v8_str("escape value")
22479 ->Equals(context.local(), values[i])
22480 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022481 } else {
22482 CHECK(values[i].IsEmpty());
22483 }
22484 }
22485}
22486
22487
22488static void SetterWhichExpectsThisAndHolderToDiffer(
22489 Local<String>, Local<Value>, const v8::PropertyCallbackInfo<void>& info) {
22490 CHECK(info.Holder() != info.This());
22491}
22492
22493
22494TEST(Regress239669) {
22495 LocalContext context;
22496 v8::Isolate* isolate = context->GetIsolate();
22497 v8::HandleScope scope(isolate);
22498 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
22499 templ->SetAccessor(v8_str("x"), 0, SetterWhichExpectsThisAndHolderToDiffer);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022500 CHECK(context->Global()
22501 ->Set(context.local(), v8_str("P"),
22502 templ->NewInstance(context.local()).ToLocalChecked())
22503 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022504 CompileRun(
22505 "function C1() {"
22506 " this.x = 23;"
22507 "};"
22508 "C1.prototype = P;"
22509 "for (var i = 0; i < 4; i++ ) {"
22510 " new C1();"
22511 "}");
22512}
22513
22514
22515class ApiCallOptimizationChecker {
22516 private:
22517 static Local<Object> data;
22518 static Local<Object> receiver;
22519 static Local<Object> holder;
22520 static Local<Object> callee;
22521 static int count;
22522
22523 static void OptimizationCallback(
22524 const v8::FunctionCallbackInfo<v8::Value>& info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022525 CHECK(data == info.Data());
22526 CHECK(receiver == info.This());
22527 if (info.Length() == 1) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022528 CHECK(v8_num(1)
22529 ->Equals(info.GetIsolate()->GetCurrentContext(), info[0])
22530 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022531 }
22532 CHECK(holder == info.Holder());
22533 count++;
22534 info.GetReturnValue().Set(v8_str("returned"));
22535 }
22536
22537 public:
22538 enum SignatureType {
22539 kNoSignature,
22540 kSignatureOnReceiver,
22541 kSignatureOnPrototype
22542 };
22543
22544 void RunAll() {
22545 SignatureType signature_types[] =
22546 {kNoSignature, kSignatureOnReceiver, kSignatureOnPrototype};
22547 for (unsigned i = 0; i < arraysize(signature_types); i++) {
22548 SignatureType signature_type = signature_types[i];
22549 for (int j = 0; j < 2; j++) {
22550 bool global = j == 0;
22551 int key = signature_type +
22552 arraysize(signature_types) * (global ? 1 : 0);
22553 Run(signature_type, global, key);
22554 }
22555 }
22556 }
22557
22558 void Run(SignatureType signature_type, bool global, int key) {
22559 v8::Isolate* isolate = CcTest::isolate();
22560 v8::HandleScope scope(isolate);
22561 // Build a template for signature checks.
22562 Local<v8::ObjectTemplate> signature_template;
22563 Local<v8::Signature> signature;
22564 {
22565 Local<v8::FunctionTemplate> parent_template =
22566 FunctionTemplate::New(isolate);
22567 parent_template->SetHiddenPrototype(true);
22568 Local<v8::FunctionTemplate> function_template
22569 = FunctionTemplate::New(isolate);
22570 function_template->Inherit(parent_template);
22571 switch (signature_type) {
22572 case kNoSignature:
22573 break;
22574 case kSignatureOnReceiver:
22575 signature = v8::Signature::New(isolate, function_template);
22576 break;
22577 case kSignatureOnPrototype:
22578 signature = v8::Signature::New(isolate, parent_template);
22579 break;
22580 }
22581 signature_template = function_template->InstanceTemplate();
22582 }
22583 // Global object must pass checks.
22584 Local<v8::Context> context =
22585 v8::Context::New(isolate, NULL, signature_template);
22586 v8::Context::Scope context_scope(context);
22587 // Install regular object that can pass signature checks.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022588 Local<Object> function_receiver =
22589 signature_template->NewInstance(context).ToLocalChecked();
22590 CHECK(context->Global()
22591 ->Set(context, v8_str("function_receiver"), function_receiver)
22592 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022593 // Get the holder objects.
22594 Local<Object> inner_global =
22595 Local<Object>::Cast(context->Global()->GetPrototype());
22596 // Install functions on hidden prototype object if there is one.
22597 data = Object::New(isolate);
22598 Local<FunctionTemplate> function_template = FunctionTemplate::New(
22599 isolate, OptimizationCallback, data, signature);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022600 Local<Function> function =
22601 function_template->GetFunction(context).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022602 Local<Object> global_holder = inner_global;
22603 Local<Object> function_holder = function_receiver;
22604 if (signature_type == kSignatureOnPrototype) {
22605 function_holder = Local<Object>::Cast(function_holder->GetPrototype());
22606 global_holder = Local<Object>::Cast(global_holder->GetPrototype());
22607 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022608 global_holder->Set(context, v8_str("g_f"), function).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022609 global_holder->SetAccessorProperty(v8_str("g_acc"), function, function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022610 function_holder->Set(context, v8_str("f"), function).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022611 function_holder->SetAccessorProperty(v8_str("acc"), function, function);
22612 // Initialize expected values.
22613 callee = function;
22614 count = 0;
22615 if (global) {
22616 receiver = context->Global();
22617 holder = inner_global;
22618 } else {
22619 holder = function_receiver;
22620 // If not using a signature, add something else to the prototype chain
22621 // to test the case that holder != receiver
22622 if (signature_type == kNoSignature) {
22623 receiver = Local<Object>::Cast(CompileRun(
22624 "var receiver_subclass = {};\n"
22625 "receiver_subclass.__proto__ = function_receiver;\n"
22626 "receiver_subclass"));
22627 } else {
22628 receiver = Local<Object>::Cast(CompileRun(
22629 "var receiver_subclass = function_receiver;\n"
22630 "receiver_subclass"));
22631 }
22632 }
22633 // With no signature, the holder is not set.
22634 if (signature_type == kNoSignature) holder = receiver;
22635 // build wrap_function
22636 i::ScopedVector<char> wrap_function(200);
22637 if (global) {
22638 i::SNPrintF(
22639 wrap_function,
22640 "function wrap_f_%d() { var f = g_f; return f(); }\n"
22641 "function wrap_get_%d() { return this.g_acc; }\n"
22642 "function wrap_set_%d() { return this.g_acc = 1; }\n",
22643 key, key, key);
22644 } else {
22645 i::SNPrintF(
22646 wrap_function,
22647 "function wrap_f_%d() { return receiver_subclass.f(); }\n"
22648 "function wrap_get_%d() { return receiver_subclass.acc; }\n"
22649 "function wrap_set_%d() { return receiver_subclass.acc = 1; }\n",
22650 key, key, key);
22651 }
22652 // build source string
22653 i::ScopedVector<char> source(1000);
22654 i::SNPrintF(
22655 source,
22656 "%s\n" // wrap functions
22657 "function wrap_f() { return wrap_f_%d(); }\n"
22658 "function wrap_get() { return wrap_get_%d(); }\n"
22659 "function wrap_set() { return wrap_set_%d(); }\n"
22660 "check = function(returned) {\n"
22661 " if (returned !== 'returned') { throw returned; }\n"
22662 "}\n"
22663 "\n"
22664 "check(wrap_f());\n"
22665 "check(wrap_f());\n"
22666 "%%OptimizeFunctionOnNextCall(wrap_f_%d);\n"
22667 "check(wrap_f());\n"
22668 "\n"
22669 "check(wrap_get());\n"
22670 "check(wrap_get());\n"
22671 "%%OptimizeFunctionOnNextCall(wrap_get_%d);\n"
22672 "check(wrap_get());\n"
22673 "\n"
22674 "check = function(returned) {\n"
22675 " if (returned !== 1) { throw returned; }\n"
22676 "}\n"
22677 "check(wrap_set());\n"
22678 "check(wrap_set());\n"
22679 "%%OptimizeFunctionOnNextCall(wrap_set_%d);\n"
22680 "check(wrap_set());\n",
22681 wrap_function.start(), key, key, key, key, key, key);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022682 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022683 CompileRun(source.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022684 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022685 CHECK_EQ(9, count);
22686 }
22687};
22688
22689
22690Local<Object> ApiCallOptimizationChecker::data;
22691Local<Object> ApiCallOptimizationChecker::receiver;
22692Local<Object> ApiCallOptimizationChecker::holder;
22693Local<Object> ApiCallOptimizationChecker::callee;
22694int ApiCallOptimizationChecker::count = 0;
22695
22696
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022697TEST(FunctionCallOptimization) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022698 i::FLAG_allow_natives_syntax = true;
22699 ApiCallOptimizationChecker checker;
22700 checker.RunAll();
22701}
22702
22703
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022704TEST(FunctionCallOptimizationMultipleArgs) {
22705 i::FLAG_allow_natives_syntax = true;
22706 LocalContext context;
22707 v8::Isolate* isolate = context->GetIsolate();
22708 v8::HandleScope scope(isolate);
22709 Local<Object> global = context->Global();
22710 Local<v8::Function> function =
22711 Function::New(context.local(), Returns42).ToLocalChecked();
22712 global->Set(context.local(), v8_str("x"), function).FromJust();
22713 CompileRun(
22714 "function x_wrap() {\n"
22715 " for (var i = 0; i < 5; i++) {\n"
22716 " x(1,2,3);\n"
22717 " }\n"
22718 "}\n"
22719 "x_wrap();\n"
22720 "%OptimizeFunctionOnNextCall(x_wrap);"
22721 "x_wrap();\n");
22722}
22723
22724
22725static void ReturnsSymbolCallback(
22726 const v8::FunctionCallbackInfo<v8::Value>& info) {
22727 info.GetReturnValue().Set(v8::Symbol::New(info.GetIsolate()));
22728}
22729
22730
22731TEST(ApiCallbackCanReturnSymbols) {
22732 i::FLAG_allow_natives_syntax = true;
22733 LocalContext context;
22734 v8::Isolate* isolate = context->GetIsolate();
22735 v8::HandleScope scope(isolate);
22736 Local<Object> global = context->Global();
22737 Local<v8::Function> function =
22738 Function::New(context.local(), ReturnsSymbolCallback).ToLocalChecked();
22739 global->Set(context.local(), v8_str("x"), function).FromJust();
22740 CompileRun(
22741 "function x_wrap() {\n"
22742 " for (var i = 0; i < 5; i++) {\n"
22743 " x();\n"
22744 " }\n"
22745 "}\n"
22746 "x_wrap();\n"
22747 "%OptimizeFunctionOnNextCall(x_wrap);"
22748 "x_wrap();\n");
22749}
22750
22751
22752TEST(EmptyApiCallback) {
22753 LocalContext context;
22754 auto isolate = context->GetIsolate();
22755 v8::HandleScope scope(isolate);
22756 auto global = context->Global();
22757 auto function = FunctionTemplate::New(isolate)
22758 ->GetFunction(context.local())
22759 .ToLocalChecked();
22760 global->Set(context.local(), v8_str("x"), function).FromJust();
22761
22762 auto result = CompileRun("x()");
22763 CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
22764
22765 result = CompileRun("x(1,2,3)");
22766 CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
22767
22768 result = CompileRun("x.call(undefined)");
22769 CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
22770
22771 result = CompileRun("x.call(null)");
22772 CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
22773
22774 result = CompileRun("7 + x.call(3) + 11");
22775 CHECK(result->IsInt32());
22776 CHECK_EQ(21, result->Int32Value(context.local()).FromJust());
22777
22778 result = CompileRun("7 + x.call(3, 101, 102, 103, 104) + 11");
22779 CHECK(result->IsInt32());
22780 CHECK_EQ(21, result->Int32Value(context.local()).FromJust());
22781
22782 result = CompileRun("var y = []; x.call(y)");
22783 CHECK(result->IsArray());
22784
22785 result = CompileRun("x.call(y, 1, 2, 3, 4)");
22786 CHECK(result->IsArray());
22787}
22788
22789
22790TEST(SimpleSignatureCheck) {
22791 LocalContext context;
22792 auto isolate = context->GetIsolate();
22793 v8::HandleScope scope(isolate);
22794 auto global = context->Global();
22795 auto sig_obj = FunctionTemplate::New(isolate);
22796 auto sig = v8::Signature::New(isolate, sig_obj);
22797 auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
22798 global->Set(context.local(), v8_str("sig_obj"),
22799 sig_obj->GetFunction(context.local()).ToLocalChecked())
22800 .FromJust();
22801 global->Set(context.local(), v8_str("x"),
22802 x->GetFunction(context.local()).ToLocalChecked())
22803 .FromJust();
22804 CompileRun("var s = new sig_obj();");
22805 {
22806 TryCatch try_catch(isolate);
22807 CompileRun("x()");
22808 CHECK(try_catch.HasCaught());
22809 }
22810 {
22811 TryCatch try_catch(isolate);
22812 CompileRun("x.call(1)");
22813 CHECK(try_catch.HasCaught());
22814 }
22815 {
22816 TryCatch try_catch(isolate);
22817 auto result = CompileRun("s.x = x; s.x()");
22818 CHECK(!try_catch.HasCaught());
22819 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
22820 }
22821 {
22822 TryCatch try_catch(isolate);
22823 auto result = CompileRun("x.call(s)");
22824 CHECK(!try_catch.HasCaught());
22825 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
22826 }
22827}
22828
22829
22830TEST(ChainSignatureCheck) {
22831 LocalContext context;
22832 auto isolate = context->GetIsolate();
22833 v8::HandleScope scope(isolate);
22834 auto global = context->Global();
22835 auto sig_obj = FunctionTemplate::New(isolate);
22836 auto sig = v8::Signature::New(isolate, sig_obj);
22837 for (int i = 0; i < 4; ++i) {
22838 auto temp = FunctionTemplate::New(isolate);
22839 temp->Inherit(sig_obj);
22840 sig_obj = temp;
22841 }
22842 auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
22843 global->Set(context.local(), v8_str("sig_obj"),
22844 sig_obj->GetFunction(context.local()).ToLocalChecked())
22845 .FromJust();
22846 global->Set(context.local(), v8_str("x"),
22847 x->GetFunction(context.local()).ToLocalChecked())
22848 .FromJust();
22849 CompileRun("var s = new sig_obj();");
22850 {
22851 TryCatch try_catch(isolate);
22852 CompileRun("x()");
22853 CHECK(try_catch.HasCaught());
22854 }
22855 {
22856 TryCatch try_catch(isolate);
22857 CompileRun("x.call(1)");
22858 CHECK(try_catch.HasCaught());
22859 }
22860 {
22861 TryCatch try_catch(isolate);
22862 auto result = CompileRun("s.x = x; s.x()");
22863 CHECK(!try_catch.HasCaught());
22864 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
22865 }
22866 {
22867 TryCatch try_catch(isolate);
22868 auto result = CompileRun("x.call(s)");
22869 CHECK(!try_catch.HasCaught());
22870 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
22871 }
22872}
22873
22874
22875TEST(PrototypeSignatureCheck) {
22876 LocalContext context;
22877 auto isolate = context->GetIsolate();
22878 v8::HandleScope scope(isolate);
22879 auto global = context->Global();
22880 auto sig_obj = FunctionTemplate::New(isolate);
22881 sig_obj->SetHiddenPrototype(true);
22882 auto sig = v8::Signature::New(isolate, sig_obj);
22883 auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
22884 global->Set(context.local(), v8_str("sig_obj"),
22885 sig_obj->GetFunction(context.local()).ToLocalChecked())
22886 .FromJust();
22887 global->Set(context.local(), v8_str("x"),
22888 x->GetFunction(context.local()).ToLocalChecked())
22889 .FromJust();
22890 CompileRun("s = {}; s.__proto__ = new sig_obj();");
22891 {
22892 TryCatch try_catch(isolate);
22893 CompileRun("x()");
22894 CHECK(try_catch.HasCaught());
22895 }
22896 {
22897 TryCatch try_catch(isolate);
22898 CompileRun("x.call(1)");
22899 CHECK(try_catch.HasCaught());
22900 }
22901 {
22902 TryCatch try_catch(isolate);
22903 auto result = CompileRun("s.x = x; s.x()");
22904 CHECK(!try_catch.HasCaught());
22905 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
22906 }
22907 {
22908 TryCatch try_catch(isolate);
22909 auto result = CompileRun("x.call(s)");
22910 CHECK(!try_catch.HasCaught());
22911 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
22912 }
22913}
22914
22915
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022916static const char* last_event_message;
22917static int last_event_status;
22918void StoringEventLoggerCallback(const char* message, int status) {
22919 last_event_message = message;
22920 last_event_status = status;
22921}
22922
22923
22924TEST(EventLogging) {
22925 v8::Isolate* isolate = CcTest::isolate();
22926 isolate->SetEventLogger(StoringEventLoggerCallback);
22927 v8::internal::HistogramTimer histogramTimer(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022928 "V8.Test", 0, 10000, v8::internal::HistogramTimer::MILLISECOND, 50,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022929 reinterpret_cast<v8::internal::Isolate*>(isolate));
22930 histogramTimer.Start();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022931 CHECK_EQ(0, strcmp("V8.Test", last_event_message));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022932 CHECK_EQ(0, last_event_status);
22933 histogramTimer.Stop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022934 CHECK_EQ(0, strcmp("V8.Test", last_event_message));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022935 CHECK_EQ(1, last_event_status);
22936}
22937
22938
22939TEST(Promises) {
22940 LocalContext context;
22941 v8::Isolate* isolate = context->GetIsolate();
22942 v8::HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022943
22944 // Creation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022945 Local<v8::Promise::Resolver> pr =
22946 v8::Promise::Resolver::New(context.local()).ToLocalChecked();
22947 Local<v8::Promise::Resolver> rr =
22948 v8::Promise::Resolver::New(context.local()).ToLocalChecked();
22949 Local<v8::Promise> p = pr->GetPromise();
22950 Local<v8::Promise> r = rr->GetPromise();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022951
22952 // IsPromise predicate.
22953 CHECK(p->IsPromise());
22954 CHECK(r->IsPromise());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022955 Local<Value> o = v8::Object::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022956 CHECK(!o->IsPromise());
22957
22958 // Resolution and rejection.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022959 pr->Resolve(context.local(), v8::Integer::New(isolate, 1)).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022960 CHECK(p->IsPromise());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022961 rr->Reject(context.local(), v8::Integer::New(isolate, 2)).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022962 CHECK(r->IsPromise());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022963}
22964
22965
22966TEST(PromiseThen) {
22967 LocalContext context;
22968 v8::Isolate* isolate = context->GetIsolate();
22969 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022970 Local<Object> global = context->Global();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022971
22972 // Creation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022973 Local<v8::Promise::Resolver> pr =
22974 v8::Promise::Resolver::New(context.local()).ToLocalChecked();
22975 Local<v8::Promise::Resolver> qr =
22976 v8::Promise::Resolver::New(context.local()).ToLocalChecked();
22977 Local<v8::Promise> p = pr->GetPromise();
22978 Local<v8::Promise> q = qr->GetPromise();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022979
22980 CHECK(p->IsPromise());
22981 CHECK(q->IsPromise());
22982
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022983 pr->Resolve(context.local(), v8::Integer::New(isolate, 1)).FromJust();
22984 qr->Resolve(context.local(), p).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022985
22986 // Chaining non-pending promises.
22987 CompileRun(
22988 "var x1 = 0;\n"
22989 "var x2 = 0;\n"
22990 "function f1(x) { x1 = x; return x+1 };\n"
22991 "function f2(x) { x2 = x; return x+1 };\n");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022992 Local<Function> f1 = Local<Function>::Cast(
22993 global->Get(context.local(), v8_str("f1")).ToLocalChecked());
22994 Local<Function> f2 = Local<Function>::Cast(
22995 global->Get(context.local(), v8_str("f2")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022996
22997 // Then
22998 CompileRun("x1 = x2 = 0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022999 q->Then(context.local(), f1).ToLocalChecked();
23000 CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
23001 .ToLocalChecked()
23002 ->Int32Value(context.local())
23003 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023004 isolate->RunMicrotasks();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023005 CHECK_EQ(1, global->Get(context.local(), v8_str("x1"))
23006 .ToLocalChecked()
23007 ->Int32Value(context.local())
23008 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023009
23010 // Then
23011 CompileRun("x1 = x2 = 0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023012 pr = v8::Promise::Resolver::New(context.local()).ToLocalChecked();
23013 qr = v8::Promise::Resolver::New(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023014
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023015 qr->Resolve(context.local(), pr).FromJust();
23016 qr->GetPromise()
23017 ->Then(context.local(), f1)
23018 .ToLocalChecked()
23019 ->Then(context.local(), f2)
23020 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023021
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023022 CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
23023 .ToLocalChecked()
23024 ->Int32Value(context.local())
23025 .FromJust());
23026 CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
23027 .ToLocalChecked()
23028 ->Int32Value(context.local())
23029 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023030 isolate->RunMicrotasks();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023031 CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
23032 .ToLocalChecked()
23033 ->Int32Value(context.local())
23034 .FromJust());
23035 CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
23036 .ToLocalChecked()
23037 ->Int32Value(context.local())
23038 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023039
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023040 pr->Resolve(context.local(), v8::Integer::New(isolate, 3)).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023041
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023042 CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
23043 .ToLocalChecked()
23044 ->Int32Value(context.local())
23045 .FromJust());
23046 CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
23047 .ToLocalChecked()
23048 ->Int32Value(context.local())
23049 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023050 isolate->RunMicrotasks();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023051 CHECK_EQ(3, global->Get(context.local(), v8_str("x1"))
23052 .ToLocalChecked()
23053 ->Int32Value(context.local())
23054 .FromJust());
23055 CHECK_EQ(4, global->Get(context.local(), v8_str("x2"))
23056 .ToLocalChecked()
23057 ->Int32Value(context.local())
23058 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023059}
23060
23061
23062TEST(DisallowJavascriptExecutionScope) {
23063 LocalContext context;
23064 v8::Isolate* isolate = context->GetIsolate();
23065 v8::HandleScope scope(isolate);
23066 v8::Isolate::DisallowJavascriptExecutionScope no_js(
23067 isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
23068 CompileRun("2+2");
23069}
23070
23071
23072TEST(AllowJavascriptExecutionScope) {
23073 LocalContext context;
23074 v8::Isolate* isolate = context->GetIsolate();
23075 v8::HandleScope scope(isolate);
23076 v8::Isolate::DisallowJavascriptExecutionScope no_js(
23077 isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
23078 v8::Isolate::DisallowJavascriptExecutionScope throw_js(
23079 isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
23080 { v8::Isolate::AllowJavascriptExecutionScope yes_js(isolate);
23081 CompileRun("1+1");
23082 }
23083}
23084
23085
23086TEST(ThrowOnJavascriptExecution) {
23087 LocalContext context;
23088 v8::Isolate* isolate = context->GetIsolate();
23089 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023090 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023091 v8::Isolate::DisallowJavascriptExecutionScope throw_js(
23092 isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
23093 CompileRun("1+1");
23094 CHECK(try_catch.HasCaught());
23095}
23096
23097
23098TEST(Regress354123) {
23099 LocalContext current;
23100 v8::Isolate* isolate = current->GetIsolate();
23101 v8::HandleScope scope(isolate);
23102
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023103 v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
23104 templ->SetAccessCheckCallback(AccessCounter);
23105 CHECK(current->Global()
23106 ->Set(current.local(), v8_str("friend"),
23107 templ->NewInstance(current.local()).ToLocalChecked())
23108 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023109
23110 // Test access using __proto__ from the prototype chain.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023111 access_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023112 CompileRun("friend.__proto__ = {};");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023113 CHECK_EQ(2, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023114 CompileRun("friend.__proto__;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023115 CHECK_EQ(4, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023116
23117 // Test access using __proto__ as a hijacked function (A).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023118 access_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023119 CompileRun("var p = Object.prototype;"
23120 "var f = Object.getOwnPropertyDescriptor(p, '__proto__').set;"
23121 "f.call(friend, {});");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023122 CHECK_EQ(1, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023123 CompileRun("var p = Object.prototype;"
23124 "var f = Object.getOwnPropertyDescriptor(p, '__proto__').get;"
23125 "f.call(friend);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023126 CHECK_EQ(2, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023127
23128 // Test access using __proto__ as a hijacked function (B).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023129 access_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023130 CompileRun("var f = Object.prototype.__lookupSetter__('__proto__');"
23131 "f.call(friend, {});");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023132 CHECK_EQ(1, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023133 CompileRun("var f = Object.prototype.__lookupGetter__('__proto__');"
23134 "f.call(friend);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023135 CHECK_EQ(2, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023136
23137 // Test access using Object.setPrototypeOf reflective method.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023138 access_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023139 CompileRun("Object.setPrototypeOf(friend, {});");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023140 CHECK_EQ(1, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023141 CompileRun("Object.getPrototypeOf(friend);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023142 CHECK_EQ(2, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023143}
23144
23145
23146TEST(CaptureStackTraceForStackOverflow) {
23147 v8::internal::FLAG_stack_size = 150;
23148 LocalContext current;
23149 v8::Isolate* isolate = current->GetIsolate();
23150 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023151 isolate->SetCaptureStackTraceForUncaughtExceptions(true, 10,
23152 v8::StackTrace::kDetailed);
23153 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023154 CompileRun("(function f(x) { f(x+1); })(0)");
23155 CHECK(try_catch.HasCaught());
23156}
23157
23158
23159TEST(ScriptNameAndLineNumber) {
23160 LocalContext env;
23161 v8::Isolate* isolate = env->GetIsolate();
23162 v8::HandleScope scope(isolate);
23163 const char* url = "http://www.foo.com/foo.js";
23164 v8::ScriptOrigin origin(v8_str(url), v8::Integer::New(isolate, 13));
23165 v8::ScriptCompiler::Source script_source(v8_str("var foo;"), origin);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023166 Local<Script> script =
23167 v8::ScriptCompiler::Compile(env.local(), &script_source).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023168 Local<Value> script_name = script->GetUnboundScript()->GetScriptName();
23169 CHECK(!script_name.IsEmpty());
23170 CHECK(script_name->IsString());
23171 String::Utf8Value utf8_name(script_name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023172 CHECK_EQ(0, strcmp(url, *utf8_name));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023173 int line_number = script->GetUnboundScript()->GetLineNumber(0);
23174 CHECK_EQ(13, line_number);
23175}
23176
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023177void CheckMagicComments(Local<Script> script, const char* expected_source_url,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023178 const char* expected_source_mapping_url) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023179 if (expected_source_url != NULL) {
23180 v8::String::Utf8Value url(script->GetUnboundScript()->GetSourceURL());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023181 CHECK_EQ(0, strcmp(expected_source_url, *url));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023182 } else {
23183 CHECK(script->GetUnboundScript()->GetSourceURL()->IsUndefined());
23184 }
23185 if (expected_source_mapping_url != NULL) {
23186 v8::String::Utf8Value url(
23187 script->GetUnboundScript()->GetSourceMappingURL());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023188 CHECK_EQ(0, strcmp(expected_source_mapping_url, *url));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023189 } else {
23190 CHECK(script->GetUnboundScript()->GetSourceMappingURL()->IsUndefined());
23191 }
23192}
23193
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023194void SourceURLHelper(const char* source, const char* expected_source_url,
23195 const char* expected_source_mapping_url) {
23196 Local<Script> script = v8_compile(source);
23197 CheckMagicComments(script, expected_source_url, expected_source_mapping_url);
23198}
23199
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023200
23201TEST(ScriptSourceURLAndSourceMappingURL) {
23202 LocalContext env;
23203 v8::Isolate* isolate = env->GetIsolate();
23204 v8::HandleScope scope(isolate);
23205 SourceURLHelper("function foo() {}\n"
23206 "//# sourceURL=bar1.js\n", "bar1.js", NULL);
23207 SourceURLHelper("function foo() {}\n"
23208 "//# sourceMappingURL=bar2.js\n", NULL, "bar2.js");
23209
23210 // Both sourceURL and sourceMappingURL.
23211 SourceURLHelper("function foo() {}\n"
23212 "//# sourceURL=bar3.js\n"
23213 "//# sourceMappingURL=bar4.js\n", "bar3.js", "bar4.js");
23214
23215 // Two source URLs; the first one is ignored.
23216 SourceURLHelper("function foo() {}\n"
23217 "//# sourceURL=ignoreme.js\n"
23218 "//# sourceURL=bar5.js\n", "bar5.js", NULL);
23219 SourceURLHelper("function foo() {}\n"
23220 "//# sourceMappingURL=ignoreme.js\n"
23221 "//# sourceMappingURL=bar6.js\n", NULL, "bar6.js");
23222
23223 // SourceURL or sourceMappingURL in the middle of the script.
23224 SourceURLHelper("function foo() {}\n"
23225 "//# sourceURL=bar7.js\n"
23226 "function baz() {}\n", "bar7.js", NULL);
23227 SourceURLHelper("function foo() {}\n"
23228 "//# sourceMappingURL=bar8.js\n"
23229 "function baz() {}\n", NULL, "bar8.js");
23230
23231 // Too much whitespace.
23232 SourceURLHelper("function foo() {}\n"
23233 "//# sourceURL=bar9.js\n"
23234 "//# sourceMappingURL=bar10.js\n", NULL, NULL);
23235 SourceURLHelper("function foo() {}\n"
23236 "//# sourceURL =bar11.js\n"
23237 "//# sourceMappingURL =bar12.js\n", NULL, NULL);
23238
23239 // Disallowed characters in value.
23240 SourceURLHelper("function foo() {}\n"
23241 "//# sourceURL=bar13 .js \n"
23242 "//# sourceMappingURL=bar14 .js \n",
23243 NULL, NULL);
23244 SourceURLHelper("function foo() {}\n"
23245 "//# sourceURL=bar15\t.js \n"
23246 "//# sourceMappingURL=bar16\t.js \n",
23247 NULL, NULL);
23248 SourceURLHelper("function foo() {}\n"
23249 "//# sourceURL=bar17'.js \n"
23250 "//# sourceMappingURL=bar18'.js \n",
23251 NULL, NULL);
23252 SourceURLHelper("function foo() {}\n"
23253 "//# sourceURL=bar19\".js \n"
23254 "//# sourceMappingURL=bar20\".js \n",
23255 NULL, NULL);
23256
23257 // Not too much whitespace.
23258 SourceURLHelper("function foo() {}\n"
23259 "//# sourceURL= bar21.js \n"
23260 "//# sourceMappingURL= bar22.js \n", "bar21.js", "bar22.js");
23261}
23262
23263
23264TEST(GetOwnPropertyDescriptor) {
23265 LocalContext env;
23266 v8::Isolate* isolate = env->GetIsolate();
23267 v8::HandleScope scope(isolate);
23268 CompileRun(
23269 "var x = { value : 13};"
23270 "Object.defineProperty(x, 'p0', {value : 12});"
23271 "Object.defineProperty(x, 'p1', {"
23272 " set : function(value) { this.value = value; },"
23273 " get : function() { return this.value; },"
23274 "});");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023275 Local<Object> x = Local<Object>::Cast(
23276 env->Global()->Get(env.local(), v8_str("x")).ToLocalChecked());
23277 Local<Value> desc =
23278 x->GetOwnPropertyDescriptor(env.local(), v8_str("no_prop"))
23279 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023280 CHECK(desc->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023281 desc =
23282 x->GetOwnPropertyDescriptor(env.local(), v8_str("p0")).ToLocalChecked();
23283 CHECK(v8_num(12)
23284 ->Equals(env.local(), Local<Object>::Cast(desc)
23285 ->Get(env.local(), v8_str("value"))
23286 .ToLocalChecked())
23287 .FromJust());
23288 desc =
23289 x->GetOwnPropertyDescriptor(env.local(), v8_str("p1")).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023290 Local<Function> set =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023291 Local<Function>::Cast(Local<Object>::Cast(desc)
23292 ->Get(env.local(), v8_str("set"))
23293 .ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023294 Local<Function> get =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023295 Local<Function>::Cast(Local<Object>::Cast(desc)
23296 ->Get(env.local(), v8_str("get"))
23297 .ToLocalChecked());
23298 CHECK(v8_num(13)
23299 ->Equals(env.local(),
23300 get->Call(env.local(), x, 0, NULL).ToLocalChecked())
23301 .FromJust());
23302 Local<Value> args[] = {v8_num(14)};
23303 set->Call(env.local(), x, 1, args).ToLocalChecked();
23304 CHECK(v8_num(14)
23305 ->Equals(env.local(),
23306 get->Call(env.local(), x, 0, NULL).ToLocalChecked())
23307 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023308}
23309
23310
23311TEST(Regress411877) {
23312 v8::Isolate* isolate = CcTest::isolate();
23313 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023314 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023315 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023316 object_template->SetAccessCheckCallback(AccessCounter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023317
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023318 v8::Local<Context> context = Context::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023319 v8::Context::Scope context_scope(context);
23320
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023321 CHECK(context->Global()
23322 ->Set(context, v8_str("o"),
23323 object_template->NewInstance(context).ToLocalChecked())
23324 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023325 CompileRun("Object.getOwnPropertyNames(o)");
23326}
23327
23328
23329TEST(GetHiddenPropertyTableAfterAccessCheck) {
23330 v8::Isolate* isolate = CcTest::isolate();
23331 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023332 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023333 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023334 object_template->SetAccessCheckCallback(AccessCounter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023335
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023336 v8::Local<Context> context = Context::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023337 v8::Context::Scope context_scope(context);
23338
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023339 v8::Local<v8::Object> obj =
23340 object_template->NewInstance(context).ToLocalChecked();
23341 obj->Set(context, v8_str("key"), v8_str("value")).FromJust();
23342 obj->Delete(context, v8_str("key")).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023343
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023344 obj->SetPrivate(context, v8::Private::New(isolate, v8_str("hidden key 2")),
23345 v8_str("hidden value 2"))
23346 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023347}
23348
23349
23350TEST(Regress411793) {
23351 v8::Isolate* isolate = CcTest::isolate();
23352 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023353 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023354 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023355 object_template->SetAccessCheckCallback(AccessCounter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023356
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023357 v8::Local<Context> context = Context::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023358 v8::Context::Scope context_scope(context);
23359
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023360 CHECK(context->Global()
23361 ->Set(context, v8_str("o"),
23362 object_template->NewInstance(context).ToLocalChecked())
23363 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023364 CompileRun(
23365 "Object.defineProperty(o, 'key', "
23366 " { get: function() {}, set: function() {} });");
23367}
23368
23369class TestSourceStream : public v8::ScriptCompiler::ExternalSourceStream {
23370 public:
23371 explicit TestSourceStream(const char** chunks) : chunks_(chunks), index_(0) {}
23372
23373 virtual size_t GetMoreData(const uint8_t** src) {
23374 // Unlike in real use cases, this function will never block.
23375 if (chunks_[index_] == NULL) {
23376 return 0;
23377 }
23378 // Copy the data, since the caller takes ownership of it.
23379 size_t len = strlen(chunks_[index_]);
23380 // We don't need to zero-terminate since we return the length.
23381 uint8_t* copy = new uint8_t[len];
23382 memcpy(copy, chunks_[index_], len);
23383 *src = copy;
23384 ++index_;
23385 return len;
23386 }
23387
23388 // Helper for constructing a string from chunks (the compilation needs it
23389 // too).
23390 static char* FullSourceString(const char** chunks) {
23391 size_t total_len = 0;
23392 for (size_t i = 0; chunks[i] != NULL; ++i) {
23393 total_len += strlen(chunks[i]);
23394 }
23395 char* full_string = new char[total_len + 1];
23396 size_t offset = 0;
23397 for (size_t i = 0; chunks[i] != NULL; ++i) {
23398 size_t len = strlen(chunks[i]);
23399 memcpy(full_string + offset, chunks[i], len);
23400 offset += len;
23401 }
23402 full_string[total_len] = 0;
23403 return full_string;
23404 }
23405
23406 private:
23407 const char** chunks_;
23408 unsigned index_;
23409};
23410
23411
23412// Helper function for running streaming tests.
23413void RunStreamingTest(const char** chunks,
23414 v8::ScriptCompiler::StreamedSource::Encoding encoding =
23415 v8::ScriptCompiler::StreamedSource::ONE_BYTE,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023416 bool expected_success = true,
23417 const char* expected_source_url = NULL,
23418 const char* expected_source_mapping_url = NULL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023419 LocalContext env;
23420 v8::Isolate* isolate = env->GetIsolate();
23421 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023422 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023423
23424 v8::ScriptCompiler::StreamedSource source(new TestSourceStream(chunks),
23425 encoding);
23426 v8::ScriptCompiler::ScriptStreamingTask* task =
23427 v8::ScriptCompiler::StartStreamingScript(isolate, &source);
23428
23429 // TestSourceStream::GetMoreData won't block, so it's OK to just run the
23430 // task here in the main thread.
23431 task->Run();
23432 delete task;
23433
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023434 // Possible errors are only produced while compiling.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023435 CHECK_EQ(false, try_catch.HasCaught());
23436
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023437 v8::ScriptOrigin origin(v8_str("http://foo.com"));
23438 char* full_source = TestSourceStream::FullSourceString(chunks);
23439 v8::MaybeLocal<Script> script = v8::ScriptCompiler::Compile(
23440 env.local(), &source, v8_str(full_source), origin);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023441 if (expected_success) {
23442 CHECK(!script.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023443 v8::Local<Value> result(
23444 script.ToLocalChecked()->Run(env.local()).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023445 // All scripts are supposed to return the fixed value 13 when ran.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023446 CHECK_EQ(13, result->Int32Value(env.local()).FromJust());
23447 CheckMagicComments(script.ToLocalChecked(), expected_source_url,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023448 expected_source_mapping_url);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023449 } else {
23450 CHECK(script.IsEmpty());
23451 CHECK(try_catch.HasCaught());
23452 }
23453 delete[] full_source;
23454}
23455
23456
23457TEST(StreamingSimpleScript) {
23458 // This script is unrealistically small, since no one chunk is enough to fill
23459 // the backing buffer of Scanner, let alone overflow it.
23460 const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
23461 NULL};
23462 RunStreamingTest(chunks);
23463}
23464
23465
23466TEST(StreamingBiggerScript) {
23467 const char* chunk1 =
23468 "function foo() {\n"
23469 " // Make this chunk sufficiently long so that it will overflow the\n"
23470 " // backing buffer of the Scanner.\n"
23471 " var i = 0;\n"
23472 " var result = 0;\n"
23473 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
23474 " result = 0;\n"
23475 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
23476 " result = 0;\n"
23477 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
23478 " result = 0;\n"
23479 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
23480 " return result;\n"
23481 "}\n";
23482 const char* chunks[] = {chunk1, "foo(); ", NULL};
23483 RunStreamingTest(chunks);
23484}
23485
23486
23487TEST(StreamingScriptWithParseError) {
23488 // Test that parse errors from streamed scripts are propagated correctly.
23489 {
23490 char chunk1[] =
23491 " // This will result in a parse error.\n"
23492 " var if else then foo";
23493 char chunk2[] = " 13\n";
23494 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23495
23496 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::ONE_BYTE,
23497 false);
23498 }
23499 // Test that the next script succeeds normally.
23500 {
23501 char chunk1[] =
23502 " // This will be parsed successfully.\n"
23503 " function foo() { return ";
23504 char chunk2[] = " 13; }\n";
23505 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23506
23507 RunStreamingTest(chunks);
23508 }
23509}
23510
23511
23512TEST(StreamingUtf8Script) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023513 // We'd want to write \uc481 instead of \xec\x92\x81, but Windows compilers
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023514 // don't like it.
23515 const char* chunk1 =
23516 "function foo() {\n"
23517 " // This function will contain an UTF-8 character which is not in\n"
23518 " // ASCII.\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023519 " var foob\xec\x92\x81r = 13;\n"
23520 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023521 "}\n";
23522 const char* chunks[] = {chunk1, "foo(); ", NULL};
23523 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23524}
23525
23526
23527TEST(StreamingUtf8ScriptWithSplitCharactersSanityCheck) {
23528 // A sanity check to prove that the approach of splitting UTF-8
23529 // characters is correct. Here is an UTF-8 character which will take three
23530 // bytes.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023531 const char* reference = "\xec\x92\x81";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023532 CHECK(3u == strlen(reference)); // NOLINT - no CHECK_EQ for unsigned.
23533
23534 char chunk1[] =
23535 "function foo() {\n"
23536 " // This function will contain an UTF-8 character which is not in\n"
23537 " // ASCII.\n"
23538 " var foob";
23539 char chunk2[] =
23540 "XXXr = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023541 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023542 "}\n";
23543 for (int i = 0; i < 3; ++i) {
23544 chunk2[i] = reference[i];
23545 }
23546 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23547 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23548}
23549
23550
23551TEST(StreamingUtf8ScriptWithSplitCharacters) {
23552 // Stream data where a multi-byte UTF-8 character is split between two data
23553 // chunks.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023554 const char* reference = "\xec\x92\x81";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023555 char chunk1[] =
23556 "function foo() {\n"
23557 " // This function will contain an UTF-8 character which is not in\n"
23558 " // ASCII.\n"
23559 " var foobX";
23560 char chunk2[] =
23561 "XXr = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023562 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023563 "}\n";
23564 chunk1[strlen(chunk1) - 1] = reference[0];
23565 chunk2[0] = reference[1];
23566 chunk2[1] = reference[2];
23567 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23568 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23569}
23570
23571
23572TEST(StreamingUtf8ScriptWithSplitCharactersValidEdgeCases) {
23573 // Tests edge cases which should still be decoded correctly.
23574
23575 // Case 1: a chunk contains only bytes for a split character (and no other
23576 // data). This kind of a chunk would be exceptionally small, but we should
23577 // still decode it correctly.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023578 const char* reference = "\xec\x92\x81";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023579 // The small chunk is at the beginning of the split character
23580 {
23581 char chunk1[] =
23582 "function foo() {\n"
23583 " // This function will contain an UTF-8 character which is not in\n"
23584 " // ASCII.\n"
23585 " var foob";
23586 char chunk2[] = "XX";
23587 char chunk3[] =
23588 "Xr = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023589 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023590 "}\n";
23591 chunk2[0] = reference[0];
23592 chunk2[1] = reference[1];
23593 chunk3[0] = reference[2];
23594 const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
23595 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23596 }
23597 // The small chunk is at the end of a character
23598 {
23599 char chunk1[] =
23600 "function foo() {\n"
23601 " // This function will contain an UTF-8 character which is not in\n"
23602 " // ASCII.\n"
23603 " var foobX";
23604 char chunk2[] = "XX";
23605 char chunk3[] =
23606 "r = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023607 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023608 "}\n";
23609 chunk1[strlen(chunk1) - 1] = reference[0];
23610 chunk2[0] = reference[1];
23611 chunk2[1] = reference[2];
23612 const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
23613 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23614 }
23615 // Case 2: the script ends with a multi-byte character. Make sure that it's
23616 // decoded correctly and not just ignored.
23617 {
23618 char chunk1[] =
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023619 "var foob\xec\x92\x81 = 13;\n"
23620 "foob\xec\x92\x81";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023621 const char* chunks[] = {chunk1, NULL};
23622 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23623 }
23624}
23625
23626
23627TEST(StreamingUtf8ScriptWithSplitCharactersInvalidEdgeCases) {
23628 // Test cases where a UTF-8 character is split over several chunks. Those
23629 // cases are not supported (the embedder should give the data in big enough
23630 // chunks), but we shouldn't crash, just produce a parse error.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023631 const char* reference = "\xec\x92\x81";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023632 char chunk1[] =
23633 "function foo() {\n"
23634 " // This function will contain an UTF-8 character which is not in\n"
23635 " // ASCII.\n"
23636 " var foobX";
23637 char chunk2[] = "X";
23638 char chunk3[] =
23639 "Xr = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023640 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023641 "}\n";
23642 chunk1[strlen(chunk1) - 1] = reference[0];
23643 chunk2[0] = reference[1];
23644 chunk3[0] = reference[2];
23645 const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
23646
23647 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
23648}
23649
23650
23651TEST(StreamingProducesParserCache) {
23652 i::FLAG_min_preparse_length = 0;
23653 const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
23654 NULL};
23655
23656 LocalContext env;
23657 v8::Isolate* isolate = env->GetIsolate();
23658 v8::HandleScope scope(isolate);
23659
23660 v8::ScriptCompiler::StreamedSource source(
23661 new TestSourceStream(chunks),
23662 v8::ScriptCompiler::StreamedSource::ONE_BYTE);
23663 v8::ScriptCompiler::ScriptStreamingTask* task =
23664 v8::ScriptCompiler::StartStreamingScript(
23665 isolate, &source, v8::ScriptCompiler::kProduceParserCache);
23666
23667 // TestSourceStream::GetMoreData won't block, so it's OK to just run the
23668 // task here in the main thread.
23669 task->Run();
23670 delete task;
23671
23672 const v8::ScriptCompiler::CachedData* cached_data = source.GetCachedData();
23673 CHECK(cached_data != NULL);
23674 CHECK(cached_data->data != NULL);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023675 CHECK(!cached_data->rejected);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023676 CHECK_GT(cached_data->length, 0);
23677}
23678
23679
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023680TEST(StreamingWithDebuggingEnabledLate) {
23681 // The streaming parser can only parse lazily, i.e. inner functions are not
23682 // fully parsed. However, we may compile inner functions eagerly when
23683 // debugging. Make sure that we can deal with this when turning on debugging
23684 // after streaming parser has already finished parsing.
23685 i::FLAG_min_preparse_length = 0;
23686 const char* chunks[] = {"with({x:1}) {",
23687 " var foo = function foo(y) {",
23688 " return x + y;",
23689 " };",
23690 " foo(2);",
23691 "}",
23692 NULL};
23693
23694 LocalContext env;
23695 v8::Isolate* isolate = env->GetIsolate();
23696 v8::HandleScope scope(isolate);
23697 v8::TryCatch try_catch(isolate);
23698
23699 v8::ScriptCompiler::StreamedSource source(
23700 new TestSourceStream(chunks),
23701 v8::ScriptCompiler::StreamedSource::ONE_BYTE);
23702 v8::ScriptCompiler::ScriptStreamingTask* task =
23703 v8::ScriptCompiler::StartStreamingScript(isolate, &source);
23704
23705 task->Run();
23706 delete task;
23707
23708 CHECK(!try_catch.HasCaught());
23709
23710 v8::ScriptOrigin origin(v8_str("http://foo.com"));
23711 char* full_source = TestSourceStream::FullSourceString(chunks);
23712
23713 EnableDebugger(isolate);
23714
23715 v8::Local<Script> script =
23716 v8::ScriptCompiler::Compile(env.local(), &source, v8_str(full_source),
23717 origin)
23718 .ToLocalChecked();
23719
23720 Maybe<uint32_t> result =
23721 script->Run(env.local()).ToLocalChecked()->Uint32Value(env.local());
23722 CHECK_EQ(3U, result.FromMaybe(0));
23723
23724 delete[] full_source;
23725
23726 DisableDebugger(isolate);
23727}
23728
23729
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023730TEST(StreamingScriptWithInvalidUtf8) {
23731 // Regression test for a crash: test that invalid UTF-8 bytes in the end of a
23732 // chunk don't produce a crash.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023733 const char* reference = "\xec\x92\x81\x80\x80";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023734 char chunk1[] =
23735 "function foo() {\n"
23736 " // This function will contain an UTF-8 character which is not in\n"
23737 " // ASCII.\n"
23738 " var foobXXXXX"; // Too many bytes which look like incomplete chars!
23739 char chunk2[] =
23740 "r = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023741 " return foob\xec\x92\x81\x80\x80r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023742 "}\n";
23743 for (int i = 0; i < 5; ++i) chunk1[strlen(chunk1) - 5 + i] = reference[i];
23744
23745 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23746 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
23747}
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023748
23749
23750TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit) {
23751 // Regression test: Stream data where there are several multi-byte UTF-8
23752 // characters in a sequence and one of them is split between two data chunks.
23753 const char* reference = "\xec\x92\x81";
23754 char chunk1[] =
23755 "function foo() {\n"
23756 " // This function will contain an UTF-8 character which is not in\n"
23757 " // ASCII.\n"
23758 " var foob\xec\x92\x81X";
23759 char chunk2[] =
23760 "XXr = 13;\n"
23761 " return foob\xec\x92\x81\xec\x92\x81r;\n"
23762 "}\n";
23763 chunk1[strlen(chunk1) - 1] = reference[0];
23764 chunk2[0] = reference[1];
23765 chunk2[1] = reference[2];
23766 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23767 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23768}
23769
23770
23771TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit2) {
23772 // Another regression test, similar to the previous one. The difference is
23773 // that the split character is not the last one in the sequence.
23774 const char* reference = "\xec\x92\x81";
23775 char chunk1[] =
23776 "function foo() {\n"
23777 " // This function will contain an UTF-8 character which is not in\n"
23778 " // ASCII.\n"
23779 " var foobX";
23780 char chunk2[] =
23781 "XX\xec\x92\x81r = 13;\n"
23782 " return foob\xec\x92\x81\xec\x92\x81r;\n"
23783 "}\n";
23784 chunk1[strlen(chunk1) - 1] = reference[0];
23785 chunk2[0] = reference[1];
23786 chunk2[1] = reference[2];
23787 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23788 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23789}
23790
23791
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023792TEST(StreamingWithHarmonyScopes) {
23793 // Don't use RunStreamingTest here so that both scripts get to use the same
23794 // LocalContext and HandleScope.
23795 LocalContext env;
23796 v8::Isolate* isolate = env->GetIsolate();
23797 v8::HandleScope scope(isolate);
23798
23799 // First, run a script with a let variable.
23800 CompileRun("\"use strict\"; let x = 1;");
23801
23802 // Then stream a script which (erroneously) tries to introduce the same
23803 // variable again.
23804 const char* chunks[] = {"\"use strict\"; let x = 2;", NULL};
23805
23806 v8::TryCatch try_catch(isolate);
23807 v8::ScriptCompiler::StreamedSource source(
23808 new TestSourceStream(chunks),
23809 v8::ScriptCompiler::StreamedSource::ONE_BYTE);
23810 v8::ScriptCompiler::ScriptStreamingTask* task =
23811 v8::ScriptCompiler::StartStreamingScript(isolate, &source);
23812 task->Run();
23813 delete task;
23814
23815 // Parsing should succeed (the script will be parsed and compiled in a context
23816 // independent way, so the error is not detected).
23817 CHECK_EQ(false, try_catch.HasCaught());
23818
23819 v8::ScriptOrigin origin(v8_str("http://foo.com"));
23820 char* full_source = TestSourceStream::FullSourceString(chunks);
23821 v8::Local<Script> script =
23822 v8::ScriptCompiler::Compile(env.local(), &source, v8_str(full_source),
23823 origin)
23824 .ToLocalChecked();
23825 CHECK(!script.IsEmpty());
23826 CHECK_EQ(false, try_catch.HasCaught());
23827
23828 // Running the script exposes the error.
23829 CHECK(script->Run(env.local()).IsEmpty());
23830 CHECK(try_catch.HasCaught());
23831 delete[] full_source;
23832}
23833
23834
23835TEST(CodeCache) {
23836 v8::Isolate::CreateParams create_params;
23837 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
23838
23839 const char* source = "Math.sqrt(4)";
23840 const char* origin = "code cache test";
23841 v8::ScriptCompiler::CachedData* cache;
23842
23843 v8::Isolate* isolate1 = v8::Isolate::New(create_params);
23844 {
23845 v8::Isolate::Scope iscope(isolate1);
23846 v8::HandleScope scope(isolate1);
23847 v8::Local<v8::Context> context = v8::Context::New(isolate1);
23848 v8::Context::Scope cscope(context);
23849 v8::Local<v8::String> source_string = v8_str(source);
23850 v8::ScriptOrigin script_origin(v8_str(origin));
23851 v8::ScriptCompiler::Source source(source_string, script_origin);
23852 v8::ScriptCompiler::CompileOptions option =
23853 v8::ScriptCompiler::kProduceCodeCache;
23854 v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked();
23855 int length = source.GetCachedData()->length;
23856 uint8_t* cache_data = new uint8_t[length];
23857 memcpy(cache_data, source.GetCachedData()->data, length);
23858 cache = new v8::ScriptCompiler::CachedData(
23859 cache_data, length, v8::ScriptCompiler::CachedData::BufferOwned);
23860 }
23861 isolate1->Dispose();
23862
23863 v8::Isolate* isolate2 = v8::Isolate::New(create_params);
23864 {
23865 v8::Isolate::Scope iscope(isolate2);
23866 v8::HandleScope scope(isolate2);
23867 v8::Local<v8::Context> context = v8::Context::New(isolate2);
23868 v8::Context::Scope cscope(context);
23869 v8::Local<v8::String> source_string = v8_str(source);
23870 v8::ScriptOrigin script_origin(v8_str(origin));
23871 v8::ScriptCompiler::Source source(source_string, script_origin, cache);
23872 v8::ScriptCompiler::CompileOptions option =
23873 v8::ScriptCompiler::kConsumeCodeCache;
23874 v8::Local<v8::Script> script;
23875 {
23876 i::DisallowCompilation no_compile(
23877 reinterpret_cast<i::Isolate*>(isolate2));
23878 script = v8::ScriptCompiler::Compile(context, &source, option)
23879 .ToLocalChecked();
23880 }
23881 CHECK_EQ(2, script->Run(context)
23882 .ToLocalChecked()
23883 ->ToInt32(context)
23884 .ToLocalChecked()
23885 ->Int32Value(context)
23886 .FromJust());
23887 }
23888 isolate2->Dispose();
23889}
23890
23891
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023892void TestInvalidCacheData(v8::ScriptCompiler::CompileOptions option) {
23893 const char* garbage = "garbage garbage garbage garbage garbage garbage";
23894 const uint8_t* data = reinterpret_cast<const uint8_t*>(garbage);
23895 int length = 16;
23896 v8::ScriptCompiler::CachedData* cached_data =
23897 new v8::ScriptCompiler::CachedData(data, length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023898 CHECK(!cached_data->rejected);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023899 v8::ScriptOrigin origin(v8_str("origin"));
23900 v8::ScriptCompiler::Source source(v8_str("42"), origin, cached_data);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023901 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
23902 v8::Local<v8::Script> script =
23903 v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023904 CHECK(cached_data->rejected);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023905 CHECK_EQ(
23906 42,
23907 script->Run(context).ToLocalChecked()->Int32Value(context).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023908}
23909
23910
23911TEST(InvalidCacheData) {
23912 v8::V8::Initialize();
23913 v8::HandleScope scope(CcTest::isolate());
23914 LocalContext context;
23915 TestInvalidCacheData(v8::ScriptCompiler::kConsumeParserCache);
23916 TestInvalidCacheData(v8::ScriptCompiler::kConsumeCodeCache);
23917}
23918
23919
23920TEST(ParserCacheRejectedGracefully) {
23921 i::FLAG_min_preparse_length = 0;
23922 v8::V8::Initialize();
23923 v8::HandleScope scope(CcTest::isolate());
23924 LocalContext context;
23925 // Produce valid cached data.
23926 v8::ScriptOrigin origin(v8_str("origin"));
23927 v8::Local<v8::String> source_str = v8_str("function foo() {}");
23928 v8::ScriptCompiler::Source source(source_str, origin);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023929 v8::Local<v8::Script> script =
23930 v8::ScriptCompiler::Compile(context.local(), &source,
23931 v8::ScriptCompiler::kProduceParserCache)
23932 .ToLocalChecked();
23933 USE(script);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023934 const v8::ScriptCompiler::CachedData* original_cached_data =
23935 source.GetCachedData();
23936 CHECK(original_cached_data != NULL);
23937 CHECK(original_cached_data->data != NULL);
23938 CHECK(!original_cached_data->rejected);
23939 CHECK_GT(original_cached_data->length, 0);
23940 // Recompiling the same script with it won't reject the data.
23941 {
23942 v8::ScriptCompiler::Source source_with_cached_data(
23943 source_str, origin,
23944 new v8::ScriptCompiler::CachedData(original_cached_data->data,
23945 original_cached_data->length));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023946 v8::Local<v8::Script> script =
23947 v8::ScriptCompiler::Compile(context.local(), &source_with_cached_data,
23948 v8::ScriptCompiler::kConsumeParserCache)
23949 .ToLocalChecked();
23950 USE(script);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023951 const v8::ScriptCompiler::CachedData* new_cached_data =
23952 source_with_cached_data.GetCachedData();
23953 CHECK(new_cached_data != NULL);
23954 CHECK(!new_cached_data->rejected);
23955 }
23956 // Compile an incompatible script with the cached data. The new script doesn't
23957 // have the same starting position for the function as the old one, so the old
23958 // cached data will be incompatible with it and will be rejected.
23959 {
23960 v8::Local<v8::String> incompatible_source_str =
23961 v8_str(" function foo() {}");
23962 v8::ScriptCompiler::Source source_with_cached_data(
23963 incompatible_source_str, origin,
23964 new v8::ScriptCompiler::CachedData(original_cached_data->data,
23965 original_cached_data->length));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023966 v8::Local<v8::Script> script =
23967 v8::ScriptCompiler::Compile(context.local(), &source_with_cached_data,
23968 v8::ScriptCompiler::kConsumeParserCache)
23969 .ToLocalChecked();
23970 USE(script);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023971 const v8::ScriptCompiler::CachedData* new_cached_data =
23972 source_with_cached_data.GetCachedData();
23973 CHECK(new_cached_data != NULL);
23974 CHECK(new_cached_data->rejected);
23975 }
23976}
23977
23978
23979TEST(StringConcatOverflow) {
23980 v8::V8::Initialize();
23981 v8::HandleScope scope(CcTest::isolate());
23982 RandomLengthOneByteResource* r =
23983 new RandomLengthOneByteResource(i::String::kMaxLength);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023984 v8::Local<v8::String> str =
23985 v8::String::NewExternalOneByte(CcTest::isolate(), r).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023986 CHECK(!str.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023987 v8::TryCatch try_catch(CcTest::isolate());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023988 v8::Local<v8::String> result = v8::String::Concat(str, str);
23989 CHECK(result.IsEmpty());
23990 CHECK(!try_catch.HasCaught());
23991}
23992
23993
23994TEST(TurboAsmDisablesNeuter) {
23995 v8::V8::Initialize();
23996 v8::HandleScope scope(CcTest::isolate());
23997 LocalContext context;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023998 bool should_be_neuterable = !i::FLAG_turbo_asm;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023999 const char* load =
24000 "function Module(stdlib, foreign, heap) {"
24001 " 'use asm';"
24002 " var MEM32 = new stdlib.Int32Array(heap);"
24003 " function load() { return MEM32[0]; }"
24004 " return { load: load };"
24005 "}"
24006 "var buffer = new ArrayBuffer(4);"
24007 "Module(this, {}, buffer).load();"
24008 "buffer";
24009
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024010 i::FLAG_turbo_osr = false; // TODO(titzer): test requires eager TF.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024011 v8::Local<v8::ArrayBuffer> result = CompileRun(load).As<v8::ArrayBuffer>();
24012 CHECK_EQ(should_be_neuterable, result->IsNeuterable());
24013
24014 const char* store =
24015 "function Module(stdlib, foreign, heap) {"
24016 " 'use asm';"
24017 " var MEM32 = new stdlib.Int32Array(heap);"
24018 " function store() { MEM32[0] = 0; }"
24019 " return { store: store };"
24020 "}"
24021 "var buffer = new ArrayBuffer(4);"
24022 "Module(this, {}, buffer).store();"
24023 "buffer";
24024
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024025 i::FLAG_turbo_osr = false; // TODO(titzer): test requires eager TF.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024026 result = CompileRun(store).As<v8::ArrayBuffer>();
24027 CHECK_EQ(should_be_neuterable, result->IsNeuterable());
24028}
24029
24030
24031TEST(GetPrototypeAccessControl) {
24032 i::FLAG_allow_natives_syntax = true;
24033 v8::Isolate* isolate = CcTest::isolate();
24034 v8::HandleScope handle_scope(isolate);
24035 LocalContext env;
24036
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024037 v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
24038 obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024039
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024040 CHECK(env->Global()
24041 ->Set(env.local(), v8_str("prohibited"),
24042 obj_template->NewInstance(env.local()).ToLocalChecked())
24043 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024044
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024045 CHECK(CompileRun(
24046 "function f() { return %_GetPrototype(prohibited); }"
24047 "%OptimizeFunctionOnNextCall(f);"
24048 "f();")->IsNull());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024049}
24050
24051
24052TEST(GetPrototypeHidden) {
24053 i::FLAG_allow_natives_syntax = true;
24054 v8::Isolate* isolate = CcTest::isolate();
24055 v8::HandleScope handle_scope(isolate);
24056 LocalContext env;
24057
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024058 Local<FunctionTemplate> t = FunctionTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024059 t->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024060 Local<Object> proto = t->GetFunction(env.local())
24061 .ToLocalChecked()
24062 ->NewInstance(env.local())
24063 .ToLocalChecked();
24064 Local<Object> object = Object::New(isolate);
24065 Local<Object> proto2 = Object::New(isolate);
24066 object->SetPrototype(env.local(), proto).FromJust();
24067 proto->SetPrototype(env.local(), proto2).FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024068
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024069 CHECK(env->Global()->Set(env.local(), v8_str("object"), object).FromJust());
24070 CHECK(env->Global()->Set(env.local(), v8_str("proto"), proto).FromJust());
24071 CHECK(env->Global()->Set(env.local(), v8_str("proto2"), proto2).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024072
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024073 v8::Local<v8::Value> result = CompileRun("%_GetPrototype(object)");
24074 CHECK(result->Equals(env.local(), proto2).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024075
24076 result = CompileRun(
24077 "function f() { return %_GetPrototype(object); }"
24078 "%OptimizeFunctionOnNextCall(f);"
24079 "f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024080 CHECK(result->Equals(env.local(), proto2).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024081}
24082
24083
24084TEST(ClassPrototypeCreationContext) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024085 v8::Isolate* isolate = CcTest::isolate();
24086 v8::HandleScope handle_scope(isolate);
24087 LocalContext env;
24088
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024089 Local<Object> result = Local<Object>::Cast(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024090 CompileRun("'use strict'; class Example { }; Example.prototype"));
24091 CHECK(env.local() == result->CreationContext());
24092}
24093
24094
24095TEST(SimpleStreamingScriptWithSourceURL) {
24096 const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo();\n",
24097 "//# sourceURL=bar2.js\n", NULL};
24098 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
24099 "bar2.js");
24100}
24101
24102
24103TEST(StreamingScriptWithSplitSourceURL) {
24104 const char* chunks[] = {"function foo() { ret", "urn 13; } f",
24105 "oo();\n//# sourceURL=b", "ar2.js\n", NULL};
24106 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
24107 "bar2.js");
24108}
24109
24110
24111TEST(StreamingScriptWithSourceMappingURLInTheMiddle) {
24112 const char* chunks[] = {"function foo() { ret", "urn 13; }\n//#",
24113 " sourceMappingURL=bar2.js\n", "foo();", NULL};
24114 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true, NULL,
24115 "bar2.js");
24116}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024117
24118
24119TEST(NewStringRangeError) {
24120 v8::Isolate* isolate = CcTest::isolate();
24121 v8::HandleScope handle_scope(isolate);
24122 const int length = i::String::kMaxLength + 1;
24123 const int buffer_size = length * sizeof(uint16_t);
24124 void* buffer = malloc(buffer_size);
24125 if (buffer == NULL) return;
24126 memset(buffer, 'A', buffer_size);
24127 {
24128 v8::TryCatch try_catch(isolate);
24129 char* data = reinterpret_cast<char*>(buffer);
24130 CHECK(v8::String::NewFromUtf8(isolate, data, v8::NewStringType::kNormal,
24131 length)
24132 .IsEmpty());
24133 CHECK(!try_catch.HasCaught());
24134 }
24135 {
24136 v8::TryCatch try_catch(isolate);
24137 uint8_t* data = reinterpret_cast<uint8_t*>(buffer);
24138 CHECK(v8::String::NewFromOneByte(isolate, data, v8::NewStringType::kNormal,
24139 length)
24140 .IsEmpty());
24141 CHECK(!try_catch.HasCaught());
24142 }
24143 {
24144 v8::TryCatch try_catch(isolate);
24145 uint16_t* data = reinterpret_cast<uint16_t*>(buffer);
24146 CHECK(v8::String::NewFromTwoByte(isolate, data, v8::NewStringType::kNormal,
24147 length)
24148 .IsEmpty());
24149 CHECK(!try_catch.HasCaught());
24150 }
24151 free(buffer);
24152}
24153
24154
24155TEST(SealHandleScope) {
24156 v8::Isolate* isolate = CcTest::isolate();
24157 v8::HandleScope handle_scope(isolate);
24158 LocalContext env;
24159
24160 v8::SealHandleScope seal(isolate);
24161
24162 // Should fail
24163 v8::Local<v8::Object> obj = v8::Object::New(isolate);
24164
24165 USE(obj);
24166}
24167
24168
24169TEST(SealHandleScopeNested) {
24170 v8::Isolate* isolate = CcTest::isolate();
24171 v8::HandleScope handle_scope(isolate);
24172 LocalContext env;
24173
24174 v8::SealHandleScope seal(isolate);
24175
24176 {
24177 v8::HandleScope handle_scope(isolate);
24178
24179 // Should work
24180 v8::Local<v8::Object> obj = v8::Object::New(isolate);
24181
24182 USE(obj);
24183 }
24184}
24185
24186
24187static bool access_was_called = false;
24188
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024189static bool AccessAlwaysAllowedWithFlag(Local<v8::Context> accessing_context,
Ben Murdoch097c5b22016-05-18 11:27:45 +010024190 Local<v8::Object> accessed_object,
24191 Local<v8::Value> data) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024192 access_was_called = true;
24193 return true;
24194}
24195
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024196static bool AccessAlwaysBlockedWithFlag(Local<v8::Context> accessing_context,
Ben Murdoch097c5b22016-05-18 11:27:45 +010024197 Local<v8::Object> accessed_object,
24198 Local<v8::Value> data) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024199 access_was_called = true;
24200 return false;
24201}
24202
24203
24204TEST(StrongModeAccessCheckAllowed) {
24205 i::FLAG_strong_mode = true;
24206 v8::Isolate* isolate = CcTest::isolate();
24207 v8::HandleScope handle_scope(isolate);
24208 v8::Local<Value> value;
24209 access_was_called = false;
24210
24211 v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
24212
24213 obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
24214 obj_template->SetAccessCheckCallback(AccessAlwaysAllowedWithFlag);
24215
24216 // Create an environment
24217 v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
24218 context0->Enter();
24219 v8::Local<v8::Object> global0 = context0->Global();
24220 global0->Set(context0, v8_str("object"),
24221 obj_template->NewInstance(context0).ToLocalChecked())
24222 .FromJust();
24223 {
24224 v8::TryCatch try_catch(isolate);
24225 value = CompileRun("'use strong'; object.x");
24226 CHECK(!try_catch.HasCaught());
24227 CHECK(!access_was_called);
24228 CHECK_EQ(42, value->Int32Value(context0).FromJust());
24229 }
24230 {
24231 v8::TryCatch try_catch(isolate);
24232 value = CompileRun("'use strong'; object.foo");
24233 CHECK(try_catch.HasCaught());
24234 CHECK(!access_was_called);
24235 }
24236 {
24237 v8::TryCatch try_catch(isolate);
24238 value = CompileRun("'use strong'; object[10]");
24239 CHECK(try_catch.HasCaught());
24240 CHECK(!access_was_called);
24241 }
24242
24243 // Create an environment
24244 v8::Local<Context> context1 = Context::New(isolate);
24245 context1->Enter();
24246 v8::Local<v8::Object> global1 = context1->Global();
24247 global1->Set(context1, v8_str("object"),
24248 obj_template->NewInstance(context1).ToLocalChecked())
24249 .FromJust();
24250 {
24251 v8::TryCatch try_catch(isolate);
24252 value = CompileRun("'use strong'; object.x");
24253 CHECK(!try_catch.HasCaught());
24254 CHECK(access_was_called);
24255 CHECK_EQ(42, value->Int32Value(context1).FromJust());
24256 }
24257 access_was_called = false;
24258 {
24259 v8::TryCatch try_catch(isolate);
24260 value = CompileRun("'use strong'; object.foo");
24261 CHECK(try_catch.HasCaught());
24262 CHECK(access_was_called);
24263 }
24264 access_was_called = false;
24265 {
24266 v8::TryCatch try_catch(isolate);
24267 value = CompileRun("'use strong'; object[10]");
24268 CHECK(try_catch.HasCaught());
24269 CHECK(access_was_called);
24270 }
24271
24272 context1->Exit();
24273 context0->Exit();
24274}
24275
24276
24277TEST(StrongModeAccessCheckBlocked) {
24278 i::FLAG_strong_mode = true;
24279 v8::Isolate* isolate = CcTest::isolate();
24280 v8::HandleScope handle_scope(isolate);
24281 v8::Local<Value> value;
24282 access_was_called = false;
24283
24284 v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
24285
24286 obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
24287 obj_template->SetAccessCheckCallback(AccessAlwaysBlockedWithFlag);
24288
24289 // Create an environment
24290 v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
24291 context0->Enter();
24292 v8::Local<v8::Object> global0 = context0->Global();
24293 global0->Set(context0, v8_str("object"),
24294 obj_template->NewInstance(context0).ToLocalChecked())
24295 .FromJust();
24296 {
24297 v8::TryCatch try_catch(isolate);
24298 value = CompileRun("'use strong'; object.x");
24299 CHECK(!try_catch.HasCaught());
24300 CHECK(!access_was_called);
24301 CHECK_EQ(42, value->Int32Value(context0).FromJust());
24302 }
24303 {
24304 v8::TryCatch try_catch(isolate);
24305 value = CompileRun("'use strong'; object.foo");
24306 CHECK(try_catch.HasCaught());
24307 CHECK(!access_was_called);
24308 }
24309 {
24310 v8::TryCatch try_catch(isolate);
24311 value = CompileRun("'use strong'; object[10]");
24312 CHECK(try_catch.HasCaught());
24313 CHECK(!access_was_called);
24314 }
24315
24316 // Create an environment
24317 v8::Local<Context> context1 = Context::New(isolate);
24318 context1->Enter();
24319 v8::Local<v8::Object> global1 = context1->Global();
24320 global1->Set(context1, v8_str("object"),
24321 obj_template->NewInstance(context1).ToLocalChecked())
24322 .FromJust();
24323 {
24324 v8::TryCatch try_catch(isolate);
24325 value = CompileRun("'use strong'; object.x");
24326 CHECK(try_catch.HasCaught());
24327 CHECK(access_was_called);
24328 }
24329 access_was_called = false;
24330 {
24331 v8::TryCatch try_catch(isolate);
24332 value = CompileRun("'use strong'; object.foo");
24333 CHECK(try_catch.HasCaught());
24334 CHECK(access_was_called);
24335 }
24336 access_was_called = false;
24337 {
24338 v8::TryCatch try_catch(isolate);
24339 value = CompileRun("'use strong'; object[10]");
24340 CHECK(try_catch.HasCaught());
24341 CHECK(access_was_called);
24342 }
24343
24344 context1->Exit();
24345 context0->Exit();
24346}
24347
24348
24349TEST(StrongModeArityCallFromApi) {
24350 i::FLAG_strong_mode = true;
24351 LocalContext env;
24352 v8::Isolate* isolate = env->GetIsolate();
24353 v8::HandleScope scope(isolate);
24354 Local<Function> fun;
24355 {
24356 v8::TryCatch try_catch(isolate);
24357 fun = Local<Function>::Cast(CompileRun(
24358 "function f(x) { 'use strong'; }"
24359 "f"));
24360
24361 CHECK(!try_catch.HasCaught());
24362 }
24363
24364 {
24365 v8::TryCatch try_catch(isolate);
24366 CHECK(fun->Call(env.local(), v8::Undefined(isolate), 0, nullptr).IsEmpty());
24367 CHECK(try_catch.HasCaught());
24368 }
24369
24370 {
24371 v8::TryCatch try_catch(isolate);
24372 v8::Local<Value> args[] = {v8_num(42)};
24373 fun->Call(env.local(), v8::Undefined(isolate), arraysize(args), args)
24374 .ToLocalChecked();
24375 CHECK(!try_catch.HasCaught());
24376 }
24377
24378 {
24379 v8::TryCatch try_catch(isolate);
24380 v8::Local<Value> args[] = {v8_num(42), v8_num(555)};
24381 fun->Call(env.local(), v8::Undefined(isolate), arraysize(args), args)
24382 .ToLocalChecked();
24383 CHECK(!try_catch.HasCaught());
24384 }
24385}
24386
24387
24388TEST(StrongModeArityCallFromApi2) {
24389 i::FLAG_strong_mode = true;
24390 LocalContext env;
24391 v8::Isolate* isolate = env->GetIsolate();
24392 v8::HandleScope scope(isolate);
24393 Local<Function> fun;
24394 {
24395 v8::TryCatch try_catch(isolate);
24396 fun = Local<Function>::Cast(CompileRun(
24397 "'use strong';"
24398 "function f(x) {}"
24399 "f"));
24400
24401 CHECK(!try_catch.HasCaught());
24402 }
24403
24404 {
24405 v8::TryCatch try_catch(isolate);
24406 CHECK(fun->Call(env.local(), v8::Undefined(isolate), 0, nullptr).IsEmpty());
24407 CHECK(try_catch.HasCaught());
24408 }
24409
24410 {
24411 v8::TryCatch try_catch(isolate);
24412 v8::Local<Value> args[] = {v8_num(42)};
24413 fun->Call(env.local(), v8::Undefined(isolate), arraysize(args), args)
24414 .ToLocalChecked();
24415 CHECK(!try_catch.HasCaught());
24416 }
24417
24418 {
24419 v8::TryCatch try_catch(isolate);
24420 v8::Local<Value> args[] = {v8_num(42), v8_num(555)};
24421 fun->Call(env.local(), v8::Undefined(isolate), arraysize(args), args)
24422 .ToLocalChecked();
24423 CHECK(!try_catch.HasCaught());
24424 }
24425}
24426
24427
24428TEST(StrongObjectDelete) {
24429 i::FLAG_strong_mode = true;
24430 LocalContext env;
24431 v8::Isolate* isolate = env->GetIsolate();
24432 v8::HandleScope scope(isolate);
24433 Local<Object> obj;
24434 {
24435 v8::TryCatch try_catch(isolate);
24436 obj = Local<Object>::Cast(CompileRun(
24437 "'use strong';"
24438 "({});"));
24439 CHECK(!try_catch.HasCaught());
24440 }
24441 obj->DefineOwnProperty(env.local(), v8_str("foo"), v8_num(1), v8::None)
24442 .FromJust();
24443 obj->DefineOwnProperty(env.local(), v8_str("2"), v8_num(1), v8::None)
24444 .FromJust();
24445 CHECK(obj->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
24446 CHECK(obj->HasOwnProperty(env.local(), v8_str("2")).FromJust());
24447 CHECK(!obj->Delete(env.local(), v8_str("foo")).FromJust());
24448 CHECK(!obj->Delete(env.local(), 2).FromJust());
24449}
24450
24451
24452static void ExtrasBindingTestRuntimeFunction(
24453 const v8::FunctionCallbackInfo<v8::Value>& args) {
24454 CHECK_EQ(
24455 3,
24456 args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust());
24457 args.GetReturnValue().Set(v8_num(7));
24458}
24459
Ben Murdoch097c5b22016-05-18 11:27:45 +010024460TEST(ExtrasFunctionSource) {
24461 v8::Isolate* isolate = CcTest::isolate();
24462 v8::HandleScope handle_scope(isolate);
24463 LocalContext env;
24464
24465 v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
24466
24467 // Functions defined in extras do not expose source code.
24468 auto func = binding->Get(env.local(), v8_str("testFunctionToString"))
24469 .ToLocalChecked()
24470 .As<v8::Function>();
24471 auto undefined = v8::Undefined(isolate);
24472 auto result = func->Call(env.local(), undefined, 0, {})
24473 .ToLocalChecked()
24474 .As<v8::String>();
24475 CHECK(result->StrictEquals(v8_str("function foo() { [native code] }")));
24476
24477 // Functions defined in extras do not show up in the stack trace.
24478 auto wrapper = binding->Get(env.local(), v8_str("testStackTrace"))
24479 .ToLocalChecked()
24480 .As<v8::Function>();
24481 CHECK(env->Global()->Set(env.local(), v8_str("wrapper"), wrapper).FromJust());
24482 ExpectString(
24483 "function f(x) { return wrapper(x) }"
24484 "function g() { return new Error().stack; }"
24485 "f(g)",
24486 "Error\n"
24487 " at g (<anonymous>:1:58)\n"
24488 " at f (<anonymous>:1:24)\n"
24489 " at <anonymous>:1:78");
24490}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024491
24492TEST(ExtrasBindingObject) {
24493 v8::Isolate* isolate = CcTest::isolate();
24494 v8::HandleScope handle_scope(isolate);
24495 LocalContext env;
24496
24497 // standalone.gypi ensures we include the test-extra.js file, which should
24498 // export the tested functions.
24499 v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
24500
24501 auto func = binding->Get(env.local(), v8_str("testExtraShouldReturnFive"))
24502 .ToLocalChecked()
24503 .As<v8::Function>();
24504 auto undefined = v8::Undefined(isolate);
24505 auto result = func->Call(env.local(), undefined, 0, {})
24506 .ToLocalChecked()
24507 .As<v8::Number>();
24508 CHECK_EQ(5, result->Int32Value(env.local()).FromJust());
24509
24510 v8::Local<v8::FunctionTemplate> runtimeFunction =
24511 v8::FunctionTemplate::New(isolate, ExtrasBindingTestRuntimeFunction);
24512 binding->Set(env.local(), v8_str("runtime"),
24513 runtimeFunction->GetFunction(env.local()).ToLocalChecked())
24514 .FromJust();
24515 func = binding->Get(env.local(), v8_str("testExtraShouldCallToRuntime"))
24516 .ToLocalChecked()
24517 .As<v8::Function>();
24518 result = func->Call(env.local(), undefined, 0, {})
24519 .ToLocalChecked()
24520 .As<v8::Number>();
24521 CHECK_EQ(7, result->Int32Value(env.local()).FromJust());
24522}
24523
24524
24525TEST(ExperimentalExtras) {
24526 i::FLAG_experimental_extras = true;
24527
24528 v8::Isolate* isolate = CcTest::isolate();
24529 v8::HandleScope handle_scope(isolate);
24530 LocalContext env;
24531
24532 // standalone.gypi ensures we include the test-experimental-extra.js file,
24533 // which should export the tested functions.
24534 v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
24535
24536 auto func =
24537 binding->Get(env.local(), v8_str("testExperimentalExtraShouldReturnTen"))
24538 .ToLocalChecked()
24539 .As<v8::Function>();
24540 auto undefined = v8::Undefined(isolate);
24541 auto result = func->Call(env.local(), undefined, 0, {})
24542 .ToLocalChecked()
24543 .As<v8::Number>();
24544 CHECK_EQ(10, result->Int32Value(env.local()).FromJust());
24545
24546 v8::Local<v8::FunctionTemplate> runtimeFunction =
24547 v8::FunctionTemplate::New(isolate, ExtrasBindingTestRuntimeFunction);
24548 binding->Set(env.local(), v8_str("runtime"),
24549 runtimeFunction->GetFunction(env.local()).ToLocalChecked())
24550 .FromJust();
24551 func = binding->Get(env.local(),
24552 v8_str("testExperimentalExtraShouldCallToRuntime"))
24553 .ToLocalChecked()
24554 .As<v8::Function>();
24555 result = func->Call(env.local(), undefined, 0, {})
24556 .ToLocalChecked()
24557 .As<v8::Number>();
24558 CHECK_EQ(7, result->Int32Value(env.local()).FromJust());
24559}
24560
24561
24562TEST(ExtrasUtilsObject) {
24563 LocalContext context;
24564 v8::Isolate* isolate = context->GetIsolate();
24565 v8::HandleScope handle_scope(isolate);
24566
24567 LocalContext env;
24568 v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
24569
24570 auto func = binding->Get(env.local(), v8_str("testExtraCanUseUtils"))
24571 .ToLocalChecked()
24572 .As<v8::Function>();
24573 auto undefined = v8::Undefined(isolate);
24574 auto result = func->Call(env.local(), undefined, 0, {})
24575 .ToLocalChecked()
24576 .As<v8::Object>();
24577
24578 auto private_symbol = result->Get(env.local(), v8_str("privateSymbol"))
24579 .ToLocalChecked()
24580 .As<v8::Symbol>();
24581 i::Handle<i::Symbol> ips = v8::Utils::OpenHandle(*private_symbol);
24582 CHECK_EQ(true, ips->IsPrivate());
24583
24584 CompileRun("var result = 0; function store(x) { result = x; }");
24585 auto store = CompileRun("store").As<v8::Function>();
24586
24587 auto fulfilled_promise = result->Get(env.local(), v8_str("fulfilledPromise"))
24588 .ToLocalChecked()
24589 .As<v8::Promise>();
24590 fulfilled_promise->Then(env.local(), store).ToLocalChecked();
24591 isolate->RunMicrotasks();
24592 CHECK_EQ(1, CompileRun("result")->Int32Value(env.local()).FromJust());
24593
24594 auto fulfilled_promise_2 =
24595 result->Get(env.local(), v8_str("fulfilledPromise2"))
24596 .ToLocalChecked()
24597 .As<v8::Promise>();
24598 fulfilled_promise_2->Then(env.local(), store).ToLocalChecked();
24599 isolate->RunMicrotasks();
24600 CHECK_EQ(2, CompileRun("result")->Int32Value(env.local()).FromJust());
24601
24602 auto rejected_promise = result->Get(env.local(), v8_str("rejectedPromise"))
24603 .ToLocalChecked()
24604 .As<v8::Promise>();
24605 rejected_promise->Catch(env.local(), store).ToLocalChecked();
24606 isolate->RunMicrotasks();
24607 CHECK_EQ(3, CompileRun("result")->Int32Value(env.local()).FromJust());
24608}
24609
24610
24611TEST(Map) {
24612 v8::Isolate* isolate = CcTest::isolate();
24613 v8::HandleScope handle_scope(isolate);
24614 LocalContext env;
24615
24616 v8::Local<v8::Map> map = v8::Map::New(isolate);
24617 CHECK(map->IsObject());
24618 CHECK(map->IsMap());
24619 CHECK(map->GetPrototype()->StrictEquals(CompileRun("Map.prototype")));
24620 CHECK_EQ(0U, map->Size());
24621
24622 v8::Local<v8::Value> val = CompileRun("new Map([[1, 2], [3, 4]])");
24623 CHECK(val->IsMap());
24624 map = v8::Local<v8::Map>::Cast(val);
24625 CHECK_EQ(2U, map->Size());
24626
24627 v8::Local<v8::Array> contents = map->AsArray();
24628 CHECK_EQ(4U, contents->Length());
24629 CHECK_EQ(
24630 1,
24631 contents->Get(env.local(), 0).ToLocalChecked().As<v8::Int32>()->Value());
24632 CHECK_EQ(
24633 2,
24634 contents->Get(env.local(), 1).ToLocalChecked().As<v8::Int32>()->Value());
24635 CHECK_EQ(
24636 3,
24637 contents->Get(env.local(), 2).ToLocalChecked().As<v8::Int32>()->Value());
24638 CHECK_EQ(
24639 4,
24640 contents->Get(env.local(), 3).ToLocalChecked().As<v8::Int32>()->Value());
24641
24642 CHECK_EQ(2U, map->Size());
24643
24644 CHECK(map->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
24645 CHECK(map->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
24646
24647 CHECK(!map->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
24648 CHECK(!map->Has(env.local(), map).FromJust());
24649
24650 CHECK_EQ(2, map->Get(env.local(), v8::Integer::New(isolate, 1))
24651 .ToLocalChecked()
24652 ->Int32Value(env.local())
24653 .FromJust());
24654 CHECK_EQ(4, map->Get(env.local(), v8::Integer::New(isolate, 3))
24655 .ToLocalChecked()
24656 ->Int32Value(env.local())
24657 .FromJust());
24658
24659 CHECK(map->Get(env.local(), v8::Integer::New(isolate, 42))
24660 .ToLocalChecked()
24661 ->IsUndefined());
24662
24663 CHECK(!map->Set(env.local(), map, map).IsEmpty());
24664 CHECK_EQ(3U, map->Size());
24665 CHECK(map->Has(env.local(), map).FromJust());
24666
24667 CHECK(map->Delete(env.local(), map).FromJust());
24668 CHECK_EQ(2U, map->Size());
24669 CHECK(!map->Has(env.local(), map).FromJust());
24670 CHECK(!map->Delete(env.local(), map).FromJust());
24671
24672 map->Clear();
24673 CHECK_EQ(0U, map->Size());
24674}
24675
24676
24677TEST(Set) {
24678 v8::Isolate* isolate = CcTest::isolate();
24679 v8::HandleScope handle_scope(isolate);
24680 LocalContext env;
24681
24682 v8::Local<v8::Set> set = v8::Set::New(isolate);
24683 CHECK(set->IsObject());
24684 CHECK(set->IsSet());
24685 CHECK(set->GetPrototype()->StrictEquals(CompileRun("Set.prototype")));
24686 CHECK_EQ(0U, set->Size());
24687
24688 v8::Local<v8::Value> val = CompileRun("new Set([1, 2])");
24689 CHECK(val->IsSet());
24690 set = v8::Local<v8::Set>::Cast(val);
24691 CHECK_EQ(2U, set->Size());
24692
24693 v8::Local<v8::Array> keys = set->AsArray();
24694 CHECK_EQ(2U, keys->Length());
24695 CHECK_EQ(1,
24696 keys->Get(env.local(), 0).ToLocalChecked().As<v8::Int32>()->Value());
24697 CHECK_EQ(2,
24698 keys->Get(env.local(), 1).ToLocalChecked().As<v8::Int32>()->Value());
24699
24700 CHECK_EQ(2U, set->Size());
24701
24702 CHECK(set->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
24703 CHECK(set->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
24704
24705 CHECK(!set->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
24706 CHECK(!set->Has(env.local(), set).FromJust());
24707
24708 CHECK(!set->Add(env.local(), set).IsEmpty());
24709 CHECK_EQ(3U, set->Size());
24710 CHECK(set->Has(env.local(), set).FromJust());
24711
24712 CHECK(set->Delete(env.local(), set).FromJust());
24713 CHECK_EQ(2U, set->Size());
24714 CHECK(!set->Has(env.local(), set).FromJust());
24715 CHECK(!set->Delete(env.local(), set).FromJust());
24716
24717 set->Clear();
24718 CHECK_EQ(0U, set->Size());
24719}
24720
24721
24722TEST(CompatibleReceiverCheckOnCachedICHandler) {
24723 v8::Isolate* isolate = CcTest::isolate();
24724 v8::HandleScope scope(isolate);
24725 v8::Local<v8::FunctionTemplate> parent = FunctionTemplate::New(isolate);
24726 v8::Local<v8::Signature> signature = v8::Signature::New(isolate, parent);
24727 auto returns_42 =
24728 v8::FunctionTemplate::New(isolate, Returns42, Local<Value>(), signature);
24729 parent->PrototypeTemplate()->SetAccessorProperty(v8_str("age"), returns_42);
24730 v8::Local<v8::FunctionTemplate> child = v8::FunctionTemplate::New(isolate);
24731 child->Inherit(parent);
24732 LocalContext env;
24733 CHECK(env->Global()
24734 ->Set(env.local(), v8_str("Child"),
24735 child->GetFunction(env.local()).ToLocalChecked())
24736 .FromJust());
24737
24738 // Make sure there's a compiled stub for "Child.prototype.age" in the cache.
24739 CompileRun(
24740 "var real = new Child();\n"
24741 "for (var i = 0; i < 3; ++i) {\n"
24742 " real.age;\n"
24743 "}\n");
24744
24745 // Check that the cached stub is never used.
24746 ExpectInt32(
24747 "var fake = Object.create(Child.prototype);\n"
24748 "var result = 0;\n"
24749 "function test(d) {\n"
24750 " if (d == 3) return;\n"
24751 " try {\n"
24752 " fake.age;\n"
24753 " result = 1;\n"
24754 " } catch (e) {\n"
24755 " }\n"
24756 " test(d+1);\n"
24757 "}\n"
24758 "test(0);\n"
24759 "result;\n",
24760 0);
24761}
24762
24763class FutexInterruptionThread : public v8::base::Thread {
24764 public:
24765 explicit FutexInterruptionThread(v8::Isolate* isolate)
24766 : Thread(Options("FutexInterruptionThread")), isolate_(isolate) {}
24767
24768 virtual void Run() {
24769 // Wait a bit before terminating.
24770 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
24771 isolate_->TerminateExecution();
24772 }
24773
24774 private:
24775 v8::Isolate* isolate_;
24776};
24777
24778
24779TEST(FutexInterruption) {
24780 i::FLAG_harmony_sharedarraybuffer = true;
24781 v8::Isolate* isolate = CcTest::isolate();
24782 v8::HandleScope scope(isolate);
24783 LocalContext env;
24784
24785 FutexInterruptionThread timeout_thread(isolate);
24786
24787 v8::TryCatch try_catch(CcTest::isolate());
24788 timeout_thread.Start();
24789
24790 CompileRun(
24791 "var ab = new SharedArrayBuffer(4);"
24792 "var i32a = new Int32Array(ab);"
24793 "Atomics.futexWait(i32a, 0, 0);");
24794 CHECK(try_catch.HasTerminated());
24795 timeout_thread.Join();
24796}
24797
24798
24799TEST(EstimatedContextSize) {
24800 v8::Isolate* isolate = CcTest::isolate();
24801 v8::HandleScope scope(isolate);
24802 LocalContext env;
24803 CHECK(50000 < env->EstimatedSize());
24804}
24805
24806
24807static int nb_uncaught_exception_callback_calls = 0;
24808
24809
24810bool NoAbortOnUncaughtException(v8::Isolate* isolate) {
24811 ++nb_uncaught_exception_callback_calls;
24812 return false;
24813}
24814
24815
24816TEST(AbortOnUncaughtExceptionNoAbort) {
24817 v8::Isolate* isolate = CcTest::isolate();
24818 v8::HandleScope handle_scope(isolate);
24819 v8::Local<v8::ObjectTemplate> global_template =
24820 v8::ObjectTemplate::New(isolate);
24821 LocalContext env(NULL, global_template);
24822
24823 i::FLAG_abort_on_uncaught_exception = true;
24824 isolate->SetAbortOnUncaughtExceptionCallback(NoAbortOnUncaughtException);
24825
24826 CompileRun("function boom() { throw new Error(\"boom\") }");
24827
24828 v8::Local<v8::Object> global_object = env->Global();
24829 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
24830 global_object->Get(env.local(), v8_str("boom")).ToLocalChecked());
24831
24832 CHECK(foo->Call(env.local(), global_object, 0, NULL).IsEmpty());
24833
24834 CHECK_EQ(1, nb_uncaught_exception_callback_calls);
24835}
24836
24837
24838TEST(AccessCheckedIsConcatSpreadable) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024839 v8::Isolate* isolate = CcTest::isolate();
24840 HandleScope scope(isolate);
24841 LocalContext env;
24842
24843 // Object with access check
24844 Local<ObjectTemplate> spreadable_template = v8::ObjectTemplate::New(isolate);
24845 spreadable_template->SetAccessCheckCallback(AccessBlocker);
24846 spreadable_template->Set(v8::Symbol::GetIsConcatSpreadable(isolate),
24847 v8::Boolean::New(isolate, true));
24848 Local<Object> object =
24849 spreadable_template->NewInstance(env.local()).ToLocalChecked();
24850
24851 allowed_access = true;
24852 CHECK(env->Global()->Set(env.local(), v8_str("object"), object).FromJust());
24853 object->Set(env.local(), v8_str("length"), v8_num(2)).FromJust();
24854 object->Set(env.local(), 0U, v8_str("a")).FromJust();
24855 object->Set(env.local(), 1U, v8_str("b")).FromJust();
24856
24857 // Access check is allowed, and the object is spread
24858 CompileRun("var result = [].concat(object)");
24859 ExpectTrue("Array.isArray(result)");
24860 ExpectString("result[0]", "a");
24861 ExpectString("result[1]", "b");
24862 ExpectTrue("result.length === 2");
24863 ExpectTrue("object[Symbol.isConcatSpreadable]");
24864
24865 // If access check fails, the value of @@isConcatSpreadable is ignored
24866 allowed_access = false;
24867 CompileRun("var result = [].concat(object)");
24868 ExpectTrue("Array.isArray(result)");
24869 ExpectTrue("result[0] === object");
24870 ExpectTrue("result.length === 1");
24871 ExpectTrue("object[Symbol.isConcatSpreadable] === undefined");
24872}
24873
24874
24875TEST(AccessCheckedToStringTag) {
24876 i::FLAG_harmony_tostring = true;
24877 v8::Isolate* isolate = CcTest::isolate();
24878 HandleScope scope(isolate);
24879 LocalContext env;
24880
24881 // Object with access check
24882 Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
24883 object_template->SetAccessCheckCallback(AccessBlocker);
24884 Local<Object> object =
24885 object_template->NewInstance(env.local()).ToLocalChecked();
24886
24887 allowed_access = true;
24888 env->Global()->Set(env.local(), v8_str("object"), object).FromJust();
24889 object->Set(env.local(), v8::Symbol::GetToStringTag(isolate), v8_str("hello"))
24890 .FromJust();
24891
24892 // Access check is allowed, and the toStringTag is read
24893 CompileRun("var result = Object.prototype.toString.call(object)");
24894 ExpectString("result", "[object hello]");
24895 ExpectString("object[Symbol.toStringTag]", "hello");
24896
24897 // ToString through the API should succeed too.
24898 String::Utf8Value result_allowed(
24899 object->ObjectProtoToString(env.local()).ToLocalChecked());
24900 CHECK_EQ(0, strcmp(*result_allowed, "[object hello]"));
24901
24902 // If access check fails, the value of @@toStringTag is ignored
24903 allowed_access = false;
24904 CompileRun("var result = Object.prototype.toString.call(object)");
24905 ExpectString("result", "[object Object]");
24906 ExpectTrue("object[Symbol.toStringTag] === undefined");
24907
24908 // ToString through the API should also fail.
24909 String::Utf8Value result_denied(
24910 object->ObjectProtoToString(env.local()).ToLocalChecked());
24911 CHECK_EQ(0, strcmp(*result_denied, "[object Object]"));
24912}
24913
24914
24915TEST(ObjectTemplateIntrinsics) {
24916 v8::Isolate* isolate = CcTest::isolate();
24917 v8::HandleScope scope(isolate);
24918 LocalContext env;
24919
24920 Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
24921 object_template->SetIntrinsicDataProperty(v8_str("values"),
24922 v8::kArrayProto_values);
24923 Local<Object> object =
24924 object_template->NewInstance(env.local()).ToLocalChecked();
24925
24926 CHECK(env->Global()->Set(env.local(), v8_str("obj1"), object).FromJust());
24927 ExpectString("typeof obj1.values", "function");
24928
24929 auto values = Local<Function>::Cast(
24930 object->Get(env.local(), v8_str("values")).ToLocalChecked());
24931 auto fn = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*values));
24932 auto ctx = v8::Utils::OpenHandle(*env.local());
24933 CHECK_EQ(fn->GetCreationContext(), *ctx);
24934
24935 {
24936 LocalContext env2;
24937 Local<Object> object2 =
24938 object_template->NewInstance(env2.local()).ToLocalChecked();
24939 CHECK(
24940 env2->Global()->Set(env2.local(), v8_str("obj2"), object2).FromJust());
24941 ExpectString("typeof obj2.values", "function");
24942 CHECK_NE(*object->Get(env2.local(), v8_str("values")).ToLocalChecked(),
24943 *object2->Get(env2.local(), v8_str("values")).ToLocalChecked());
24944
24945 auto values2 = Local<Function>::Cast(
24946 object2->Get(env2.local(), v8_str("values")).ToLocalChecked());
24947 auto fn2 = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*values2));
24948 auto ctx2 = v8::Utils::OpenHandle(*env2.local());
24949 CHECK_EQ(fn2->GetCreationContext(), *ctx2);
24950 }
24951}
24952
24953
24954TEST(Proxy) {
24955 i::FLAG_harmony_proxies = true;
24956 LocalContext context;
24957 v8::Isolate* isolate = CcTest::isolate();
24958 v8::HandleScope scope(isolate);
24959 v8::Local<v8::Object> target = CompileRun("({})").As<v8::Object>();
24960 v8::Local<v8::Object> handler = CompileRun("({})").As<v8::Object>();
24961
24962 v8::Local<v8::Proxy> proxy =
24963 v8::Proxy::New(context.local(), target, handler).ToLocalChecked();
24964 CHECK(proxy->IsProxy());
24965 CHECK(!target->IsProxy());
24966 CHECK(!proxy->IsRevoked());
24967 CHECK(proxy->GetTarget()->SameValue(target));
24968 CHECK(proxy->GetHandler()->SameValue(handler));
24969
24970 proxy->Revoke();
24971 CHECK(proxy->IsProxy());
24972 CHECK(!target->IsProxy());
24973 CHECK(proxy->IsRevoked());
24974 CHECK(proxy->GetTarget()->SameValue(target));
24975 CHECK(proxy->GetHandler()->IsNull());
24976}