blob: 220b0cd07784cbc714c7d3e5496079126d95bd43 [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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002992 LocalContext env;
2993 v8::Isolate* isolate = env->GetIsolate();
2994 v8::HandleScope scope(isolate);
2995
2996 v8::Local<v8::Object> target = CompileRun("({})").As<v8::Object>();
2997 v8::Local<v8::Object> handler = CompileRun("({})").As<v8::Object>();
2998
2999 v8::Local<v8::Proxy> proxy =
3000 v8::Proxy::New(env.local(), target, handler).ToLocalChecked();
3001
3002 v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
3003 v8::Local<v8::Private> priv2 =
3004 v8::Private::New(isolate, v8_str("my-private"));
3005
3006 CcTest::heap()->CollectAllGarbage();
3007
3008 CHECK(priv2->Name()
3009 ->Equals(env.local(),
3010 v8::String::NewFromUtf8(isolate, "my-private",
3011 v8::NewStringType::kNormal)
3012 .ToLocalChecked())
3013 .FromJust());
3014
3015 // Make sure delete of a non-existent private symbol property works.
3016 proxy->DeletePrivate(env.local(), priv1).FromJust();
3017 CHECK(!proxy->HasPrivate(env.local(), priv1).FromJust());
3018
3019 CHECK(proxy->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 1503))
3020 .FromJust());
3021 CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
3022 CHECK_EQ(1503, proxy->GetPrivate(env.local(), priv1)
3023 .ToLocalChecked()
3024 ->Int32Value(env.local())
3025 .FromJust());
3026 CHECK(proxy->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 2002))
3027 .FromJust());
3028 CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
3029 CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
3030 .ToLocalChecked()
3031 ->Int32Value(env.local())
3032 .FromJust());
3033
3034 CHECK_EQ(0u,
3035 proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
3036 unsigned num_props =
3037 proxy->GetPropertyNames(env.local()).ToLocalChecked()->Length();
3038 CHECK(proxy->Set(env.local(), v8::String::NewFromUtf8(
3039 isolate, "bla", v8::NewStringType::kNormal)
3040 .ToLocalChecked(),
3041 v8::Integer::New(isolate, 20))
3042 .FromJust());
3043 CHECK_EQ(1u,
3044 proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
3045 CHECK_EQ(num_props + 1,
3046 proxy->GetPropertyNames(env.local()).ToLocalChecked()->Length());
3047
3048 CcTest::heap()->CollectAllGarbage();
3049
3050 // Add another property and delete it afterwards to force the object in
3051 // slow case.
3052 CHECK(proxy->SetPrivate(env.local(), priv2, v8::Integer::New(isolate, 2008))
3053 .FromJust());
3054 CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
3055 .ToLocalChecked()
3056 ->Int32Value(env.local())
3057 .FromJust());
3058 CHECK_EQ(2008, proxy->GetPrivate(env.local(), priv2)
3059 .ToLocalChecked()
3060 ->Int32Value(env.local())
3061 .FromJust());
3062 CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
3063 .ToLocalChecked()
3064 ->Int32Value(env.local())
3065 .FromJust());
3066 CHECK_EQ(1u,
3067 proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
3068
3069 CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
3070 CHECK(proxy->HasPrivate(env.local(), priv2).FromJust());
3071 CHECK(proxy->DeletePrivate(env.local(), priv2).FromJust());
3072 CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
3073 CHECK(!proxy->HasPrivate(env.local(), priv2).FromJust());
3074 CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
3075 .ToLocalChecked()
3076 ->Int32Value(env.local())
3077 .FromJust());
3078 CHECK_EQ(1u,
3079 proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
3080
3081 // Private properties are not inherited (for the time being).
3082 v8::Local<v8::Object> child = v8::Object::New(isolate);
3083 CHECK(child->SetPrototype(env.local(), proxy).FromJust());
3084 CHECK(!child->HasPrivate(env.local(), priv1).FromJust());
3085 CHECK_EQ(0u,
3086 child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003087}
3088
3089
3090THREADED_TEST(PrivateProperties) {
3091 LocalContext env;
3092 v8::Isolate* isolate = env->GetIsolate();
3093 v8::HandleScope scope(isolate);
3094
3095 v8::Local<v8::Object> obj = v8::Object::New(isolate);
3096 v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
3097 v8::Local<v8::Private> priv2 =
3098 v8::Private::New(isolate, v8_str("my-private"));
3099
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003100 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003101
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003102 CHECK(priv2->Name()
3103 ->Equals(env.local(),
3104 v8::String::NewFromUtf8(isolate, "my-private",
3105 v8::NewStringType::kNormal)
3106 .ToLocalChecked())
3107 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003108
3109 // Make sure delete of a non-existent private symbol property works.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003110 obj->DeletePrivate(env.local(), priv1).FromJust();
3111 CHECK(!obj->HasPrivate(env.local(), priv1).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003112
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003113 CHECK(obj->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 1503))
3114 .FromJust());
3115 CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
3116 CHECK_EQ(1503, obj->GetPrivate(env.local(), priv1)
3117 .ToLocalChecked()
3118 ->Int32Value(env.local())
3119 .FromJust());
3120 CHECK(obj->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 2002))
3121 .FromJust());
3122 CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
3123 CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
3124 .ToLocalChecked()
3125 ->Int32Value(env.local())
3126 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003127
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003128 CHECK_EQ(0u,
3129 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
3130 unsigned num_props =
3131 obj->GetPropertyNames(env.local()).ToLocalChecked()->Length();
3132 CHECK(obj->Set(env.local(), v8::String::NewFromUtf8(
3133 isolate, "bla", v8::NewStringType::kNormal)
3134 .ToLocalChecked(),
3135 v8::Integer::New(isolate, 20))
3136 .FromJust());
3137 CHECK_EQ(1u,
3138 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
3139 CHECK_EQ(num_props + 1,
3140 obj->GetPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003141
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003142 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003143
3144 // Add another property and delete it afterwards to force the object in
3145 // slow case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003146 CHECK(obj->SetPrivate(env.local(), priv2, v8::Integer::New(isolate, 2008))
3147 .FromJust());
3148 CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
3149 .ToLocalChecked()
3150 ->Int32Value(env.local())
3151 .FromJust());
3152 CHECK_EQ(2008, obj->GetPrivate(env.local(), priv2)
3153 .ToLocalChecked()
3154 ->Int32Value(env.local())
3155 .FromJust());
3156 CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
3157 .ToLocalChecked()
3158 ->Int32Value(env.local())
3159 .FromJust());
3160 CHECK_EQ(1u,
3161 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003162
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003163 CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
3164 CHECK(obj->HasPrivate(env.local(), priv2).FromJust());
3165 CHECK(obj->DeletePrivate(env.local(), priv2).FromJust());
3166 CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
3167 CHECK(!obj->HasPrivate(env.local(), priv2).FromJust());
3168 CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
3169 .ToLocalChecked()
3170 ->Int32Value(env.local())
3171 .FromJust());
3172 CHECK_EQ(1u,
3173 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003174
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003175 // Private properties are not inherited (for the time being).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003176 v8::Local<v8::Object> child = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003177 CHECK(child->SetPrototype(env.local(), obj).FromJust());
3178 CHECK(!child->HasPrivate(env.local(), priv1).FromJust());
3179 CHECK_EQ(0u,
3180 child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003181}
3182
3183
3184THREADED_TEST(GlobalSymbols) {
3185 LocalContext env;
3186 v8::Isolate* isolate = env->GetIsolate();
3187 v8::HandleScope scope(isolate);
3188
3189 v8::Local<String> name = v8_str("my-symbol");
3190 v8::Local<v8::Symbol> glob = v8::Symbol::For(isolate, name);
3191 v8::Local<v8::Symbol> glob2 = v8::Symbol::For(isolate, name);
3192 CHECK(glob2->SameValue(glob));
3193
3194 v8::Local<v8::Symbol> glob_api = v8::Symbol::ForApi(isolate, name);
3195 v8::Local<v8::Symbol> glob_api2 = v8::Symbol::ForApi(isolate, name);
3196 CHECK(glob_api2->SameValue(glob_api));
3197 CHECK(!glob_api->SameValue(glob));
3198
3199 v8::Local<v8::Symbol> sym = v8::Symbol::New(isolate, name);
3200 CHECK(!sym->SameValue(glob));
3201
3202 CompileRun("var sym2 = Symbol.for('my-symbol')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003203 v8::Local<Value> sym2 =
3204 env->Global()->Get(env.local(), v8_str("sym2")).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003205 CHECK(sym2->SameValue(glob));
3206 CHECK(!sym2->SameValue(glob_api));
3207}
3208
3209
3210static void CheckWellKnownSymbol(v8::Local<v8::Symbol>(*getter)(v8::Isolate*),
3211 const char* name) {
3212 LocalContext env;
3213 v8::Isolate* isolate = env->GetIsolate();
3214 v8::HandleScope scope(isolate);
3215
3216 v8::Local<v8::Symbol> symbol = getter(isolate);
3217 std::string script = std::string("var sym = ") + name;
3218 CompileRun(script.c_str());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003219 v8::Local<Value> value =
3220 env->Global()->Get(env.local(), v8_str("sym")).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003221
3222 CHECK(!value.IsEmpty());
3223 CHECK(!symbol.IsEmpty());
3224 CHECK(value->SameValue(symbol));
3225}
3226
3227
3228THREADED_TEST(WellKnownSymbols) {
3229 CheckWellKnownSymbol(v8::Symbol::GetIterator, "Symbol.iterator");
3230 CheckWellKnownSymbol(v8::Symbol::GetUnscopables, "Symbol.unscopables");
3231}
3232
3233
3234THREADED_TEST(GlobalPrivates) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003235 i::FLAG_allow_natives_syntax = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003236 LocalContext env;
3237 v8::Isolate* isolate = env->GetIsolate();
3238 v8::HandleScope scope(isolate);
3239
3240 v8::Local<String> name = v8_str("my-private");
3241 v8::Local<v8::Private> glob = v8::Private::ForApi(isolate, name);
3242 v8::Local<v8::Object> obj = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003243 CHECK(obj->SetPrivate(env.local(), glob, v8::Integer::New(isolate, 3))
3244 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003245
3246 v8::Local<v8::Private> glob2 = v8::Private::ForApi(isolate, name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003247 CHECK(obj->HasPrivate(env.local(), glob2).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003248
3249 v8::Local<v8::Private> priv = v8::Private::New(isolate, name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003250 CHECK(!obj->HasPrivate(env.local(), priv).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003251
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003252 CompileRun("var intern = %CreatePrivateSymbol('my-private')");
3253 v8::Local<Value> intern =
3254 env->Global()->Get(env.local(), v8_str("intern")).ToLocalChecked();
3255 CHECK(!obj->Has(env.local(), intern).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003256}
3257
3258
3259class ScopedArrayBufferContents {
3260 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003261 explicit ScopedArrayBufferContents(const v8::ArrayBuffer::Contents& contents)
3262 : contents_(contents) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003263 ~ScopedArrayBufferContents() { free(contents_.Data()); }
3264 void* Data() const { return contents_.Data(); }
3265 size_t ByteLength() const { return contents_.ByteLength(); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003266
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003267 private:
3268 const v8::ArrayBuffer::Contents contents_;
3269};
3270
3271template <typename T>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003272static void CheckInternalFieldsAreZero(v8::Local<T> value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003273 CHECK_EQ(T::kInternalFieldCount, value->InternalFieldCount());
3274 for (int i = 0; i < value->InternalFieldCount(); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003275 CHECK_EQ(0, value->GetInternalField(i)
3276 ->Int32Value(CcTest::isolate()->GetCurrentContext())
3277 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003278 }
3279}
3280
3281
3282THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
3283 LocalContext env;
3284 v8::Isolate* isolate = env->GetIsolate();
3285 v8::HandleScope handle_scope(isolate);
3286
3287 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 1024);
3288 CheckInternalFieldsAreZero(ab);
3289 CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
3290 CHECK(!ab->IsExternal());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003291 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003292
3293 ScopedArrayBufferContents ab_contents(ab->Externalize());
3294 CHECK(ab->IsExternal());
3295
3296 CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
3297 uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003298 CHECK(data != NULL);
3299 CHECK(env->Global()->Set(env.local(), v8_str("ab"), ab).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003300
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003301 v8::Local<v8::Value> result = CompileRun("ab.byteLength");
3302 CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003303
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003304 result = CompileRun(
3305 "var u8 = new Uint8Array(ab);"
3306 "u8[0] = 0xFF;"
3307 "u8[1] = 0xAA;"
3308 "u8.length");
3309 CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003310 CHECK_EQ(0xFF, data[0]);
3311 CHECK_EQ(0xAA, data[1]);
3312 data[0] = 0xCC;
3313 data[1] = 0x11;
3314 result = CompileRun("u8[0] + u8[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003315 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003316}
3317
3318
3319THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
3320 LocalContext env;
3321 v8::Isolate* isolate = env->GetIsolate();
3322 v8::HandleScope handle_scope(isolate);
3323
3324
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003325 v8::Local<v8::Value> result = CompileRun(
3326 "var ab1 = new ArrayBuffer(2);"
3327 "var u8_a = new Uint8Array(ab1);"
3328 "u8_a[0] = 0xAA;"
3329 "u8_a[1] = 0xFF; u8_a.buffer");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003330 Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
3331 CheckInternalFieldsAreZero(ab1);
3332 CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
3333 CHECK(!ab1->IsExternal());
3334 ScopedArrayBufferContents ab1_contents(ab1->Externalize());
3335 CHECK(ab1->IsExternal());
3336
3337 result = CompileRun("ab1.byteLength");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003338 CHECK_EQ(2, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003339 result = CompileRun("u8_a[0]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003340 CHECK_EQ(0xAA, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003341 result = CompileRun("u8_a[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003342 CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
3343 result = CompileRun(
3344 "var u8_b = new Uint8Array(ab1);"
3345 "u8_b[0] = 0xBB;"
3346 "u8_a[0]");
3347 CHECK_EQ(0xBB, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003348 result = CompileRun("u8_b[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003349 CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003350
3351 CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
3352 uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
3353 CHECK_EQ(0xBB, ab1_data[0]);
3354 CHECK_EQ(0xFF, ab1_data[1]);
3355 ab1_data[0] = 0xCC;
3356 ab1_data[1] = 0x11;
3357 result = CompileRun("u8_a[0] + u8_a[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003358 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003359}
3360
3361
3362THREADED_TEST(ArrayBuffer_External) {
3363 LocalContext env;
3364 v8::Isolate* isolate = env->GetIsolate();
3365 v8::HandleScope handle_scope(isolate);
3366
3367 i::ScopedVector<uint8_t> my_data(100);
3368 memset(my_data.start(), 0, 100);
3369 Local<v8::ArrayBuffer> ab3 =
3370 v8::ArrayBuffer::New(isolate, my_data.start(), 100);
3371 CheckInternalFieldsAreZero(ab3);
3372 CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
3373 CHECK(ab3->IsExternal());
3374
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003375 CHECK(env->Global()->Set(env.local(), v8_str("ab3"), ab3).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003376
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003377 v8::Local<v8::Value> result = CompileRun("ab3.byteLength");
3378 CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003379
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003380 result = CompileRun(
3381 "var u8_b = new Uint8Array(ab3);"
3382 "u8_b[0] = 0xBB;"
3383 "u8_b[1] = 0xCC;"
3384 "u8_b.length");
3385 CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003386 CHECK_EQ(0xBB, my_data[0]);
3387 CHECK_EQ(0xCC, my_data[1]);
3388 my_data[0] = 0xCC;
3389 my_data[1] = 0x11;
3390 result = CompileRun("u8_b[0] + u8_b[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003391 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003392}
3393
3394
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003395THREADED_TEST(ArrayBuffer_DisableNeuter) {
3396 LocalContext env;
3397 v8::Isolate* isolate = env->GetIsolate();
3398 v8::HandleScope handle_scope(isolate);
3399
3400 i::ScopedVector<uint8_t> my_data(100);
3401 memset(my_data.start(), 0, 100);
3402 Local<v8::ArrayBuffer> ab =
3403 v8::ArrayBuffer::New(isolate, my_data.start(), 100);
3404 CHECK(ab->IsNeuterable());
3405
3406 i::Handle<i::JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
3407 buf->set_is_neuterable(false);
3408
3409 CHECK(!ab->IsNeuterable());
3410}
3411
3412
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003413static void CheckDataViewIsNeutered(v8::Local<v8::DataView> dv) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003414 CHECK_EQ(0, static_cast<int>(dv->ByteLength()));
3415 CHECK_EQ(0, static_cast<int>(dv->ByteOffset()));
3416}
3417
3418
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003419static void CheckIsNeutered(v8::Local<v8::TypedArray> ta) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003420 CHECK_EQ(0, static_cast<int>(ta->ByteLength()));
3421 CHECK_EQ(0, static_cast<int>(ta->Length()));
3422 CHECK_EQ(0, static_cast<int>(ta->ByteOffset()));
3423}
3424
3425
3426static void CheckIsTypedArrayVarNeutered(const char* name) {
3427 i::ScopedVector<char> source(1024);
3428 i::SNPrintF(source,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003429 "%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
3430 name, name, name);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003431 CHECK(CompileRun(source.start())->IsTrue());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003432 v8::Local<v8::TypedArray> ta =
3433 v8::Local<v8::TypedArray>::Cast(CompileRun(name));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003434 CheckIsNeutered(ta);
3435}
3436
3437
3438template <typename TypedArray, int kElementSize>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003439static Local<TypedArray> CreateAndCheck(Local<v8::ArrayBuffer> ab,
3440 int byteOffset, int length) {
3441 v8::Local<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003442 CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
3443 CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
3444 CHECK_EQ(length, static_cast<int>(ta->Length()));
3445 CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
3446 return ta;
3447}
3448
3449
3450THREADED_TEST(ArrayBuffer_NeuteringApi) {
3451 LocalContext env;
3452 v8::Isolate* isolate = env->GetIsolate();
3453 v8::HandleScope handle_scope(isolate);
3454
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003455 v8::Local<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1024);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003456
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003457 v8::Local<v8::Uint8Array> u8a =
3458 CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
3459 v8::Local<v8::Uint8ClampedArray> u8c =
3460 CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
3461 v8::Local<v8::Int8Array> i8a =
3462 CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003463
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003464 v8::Local<v8::Uint16Array> u16a =
3465 CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
3466 v8::Local<v8::Int16Array> i16a =
3467 CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003468
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003469 v8::Local<v8::Uint32Array> u32a =
3470 CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
3471 v8::Local<v8::Int32Array> i32a =
3472 CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003473
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003474 v8::Local<v8::Float32Array> f32a =
3475 CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
3476 v8::Local<v8::Float64Array> f64a =
3477 CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003478
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003479 v8::Local<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003480 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
3481 CHECK_EQ(1, static_cast<int>(dv->ByteOffset()));
3482 CHECK_EQ(1023, static_cast<int>(dv->ByteLength()));
3483
3484 ScopedArrayBufferContents contents(buffer->Externalize());
3485 buffer->Neuter();
3486 CHECK_EQ(0, static_cast<int>(buffer->ByteLength()));
3487 CheckIsNeutered(u8a);
3488 CheckIsNeutered(u8c);
3489 CheckIsNeutered(i8a);
3490 CheckIsNeutered(u16a);
3491 CheckIsNeutered(i16a);
3492 CheckIsNeutered(u32a);
3493 CheckIsNeutered(i32a);
3494 CheckIsNeutered(f32a);
3495 CheckIsNeutered(f64a);
3496 CheckDataViewIsNeutered(dv);
3497}
3498
3499
3500THREADED_TEST(ArrayBuffer_NeuteringScript) {
3501 LocalContext env;
3502 v8::Isolate* isolate = env->GetIsolate();
3503 v8::HandleScope handle_scope(isolate);
3504
3505 CompileRun(
3506 "var ab = new ArrayBuffer(1024);"
3507 "var u8a = new Uint8Array(ab, 1, 1023);"
3508 "var u8c = new Uint8ClampedArray(ab, 1, 1023);"
3509 "var i8a = new Int8Array(ab, 1, 1023);"
3510 "var u16a = new Uint16Array(ab, 2, 511);"
3511 "var i16a = new Int16Array(ab, 2, 511);"
3512 "var u32a = new Uint32Array(ab, 4, 255);"
3513 "var i32a = new Int32Array(ab, 4, 255);"
3514 "var f32a = new Float32Array(ab, 4, 255);"
3515 "var f64a = new Float64Array(ab, 8, 127);"
3516 "var dv = new DataView(ab, 1, 1023);");
3517
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003518 v8::Local<v8::ArrayBuffer> ab =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003519 Local<v8::ArrayBuffer>::Cast(CompileRun("ab"));
3520
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003521 v8::Local<v8::DataView> dv = v8::Local<v8::DataView>::Cast(CompileRun("dv"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003522
3523 ScopedArrayBufferContents contents(ab->Externalize());
3524 ab->Neuter();
3525 CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003526 CHECK_EQ(0, v8_run_int32value(v8_compile("ab.byteLength")));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003527
3528 CheckIsTypedArrayVarNeutered("u8a");
3529 CheckIsTypedArrayVarNeutered("u8c");
3530 CheckIsTypedArrayVarNeutered("i8a");
3531 CheckIsTypedArrayVarNeutered("u16a");
3532 CheckIsTypedArrayVarNeutered("i16a");
3533 CheckIsTypedArrayVarNeutered("u32a");
3534 CheckIsTypedArrayVarNeutered("i32a");
3535 CheckIsTypedArrayVarNeutered("f32a");
3536 CheckIsTypedArrayVarNeutered("f64a");
3537
3538 CHECK(CompileRun("dv.byteLength == 0 && dv.byteOffset == 0")->IsTrue());
3539 CheckDataViewIsNeutered(dv);
3540}
3541
3542
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003543class ScopedSharedArrayBufferContents {
3544 public:
3545 explicit ScopedSharedArrayBufferContents(
3546 const v8::SharedArrayBuffer::Contents& contents)
3547 : contents_(contents) {}
3548 ~ScopedSharedArrayBufferContents() { free(contents_.Data()); }
3549 void* Data() const { return contents_.Data(); }
3550 size_t ByteLength() const { return contents_.ByteLength(); }
3551
3552 private:
3553 const v8::SharedArrayBuffer::Contents contents_;
3554};
3555
3556
3557THREADED_TEST(SharedArrayBuffer_ApiInternalToExternal) {
3558 i::FLAG_harmony_sharedarraybuffer = true;
3559 LocalContext env;
3560 v8::Isolate* isolate = env->GetIsolate();
3561 v8::HandleScope handle_scope(isolate);
3562
3563 Local<v8::SharedArrayBuffer> ab = v8::SharedArrayBuffer::New(isolate, 1024);
3564 CheckInternalFieldsAreZero(ab);
3565 CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
3566 CHECK(!ab->IsExternal());
3567 CcTest::heap()->CollectAllGarbage();
3568
3569 ScopedSharedArrayBufferContents ab_contents(ab->Externalize());
3570 CHECK(ab->IsExternal());
3571
3572 CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
3573 uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
3574 CHECK(data != NULL);
3575 CHECK(env->Global()->Set(env.local(), v8_str("ab"), ab).FromJust());
3576
3577 v8::Local<v8::Value> result = CompileRun("ab.byteLength");
3578 CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
3579
3580 result = CompileRun(
3581 "var u8 = new Uint8Array(ab);"
3582 "u8[0] = 0xFF;"
3583 "u8[1] = 0xAA;"
3584 "u8.length");
3585 CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
3586 CHECK_EQ(0xFF, data[0]);
3587 CHECK_EQ(0xAA, data[1]);
3588 data[0] = 0xCC;
3589 data[1] = 0x11;
3590 result = CompileRun("u8[0] + u8[1]");
3591 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
3592}
3593
3594
3595THREADED_TEST(SharedArrayBuffer_JSInternalToExternal) {
3596 i::FLAG_harmony_sharedarraybuffer = true;
3597 LocalContext env;
3598 v8::Isolate* isolate = env->GetIsolate();
3599 v8::HandleScope handle_scope(isolate);
3600
3601
3602 v8::Local<v8::Value> result = CompileRun(
3603 "var ab1 = new SharedArrayBuffer(2);"
3604 "var u8_a = new Uint8Array(ab1);"
3605 "u8_a[0] = 0xAA;"
3606 "u8_a[1] = 0xFF; u8_a.buffer");
3607 Local<v8::SharedArrayBuffer> ab1 = Local<v8::SharedArrayBuffer>::Cast(result);
3608 CheckInternalFieldsAreZero(ab1);
3609 CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
3610 CHECK(!ab1->IsExternal());
3611 ScopedSharedArrayBufferContents ab1_contents(ab1->Externalize());
3612 CHECK(ab1->IsExternal());
3613
3614 result = CompileRun("ab1.byteLength");
3615 CHECK_EQ(2, result->Int32Value(env.local()).FromJust());
3616 result = CompileRun("u8_a[0]");
3617 CHECK_EQ(0xAA, result->Int32Value(env.local()).FromJust());
3618 result = CompileRun("u8_a[1]");
3619 CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
3620 result = CompileRun(
3621 "var u8_b = new Uint8Array(ab1);"
3622 "u8_b[0] = 0xBB;"
3623 "u8_a[0]");
3624 CHECK_EQ(0xBB, result->Int32Value(env.local()).FromJust());
3625 result = CompileRun("u8_b[1]");
3626 CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
3627
3628 CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
3629 uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
3630 CHECK_EQ(0xBB, ab1_data[0]);
3631 CHECK_EQ(0xFF, ab1_data[1]);
3632 ab1_data[0] = 0xCC;
3633 ab1_data[1] = 0x11;
3634 result = CompileRun("u8_a[0] + u8_a[1]");
3635 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
3636}
3637
3638
3639THREADED_TEST(SharedArrayBuffer_External) {
3640 i::FLAG_harmony_sharedarraybuffer = true;
3641 LocalContext env;
3642 v8::Isolate* isolate = env->GetIsolate();
3643 v8::HandleScope handle_scope(isolate);
3644
3645 i::ScopedVector<uint8_t> my_data(100);
3646 memset(my_data.start(), 0, 100);
3647 Local<v8::SharedArrayBuffer> ab3 =
3648 v8::SharedArrayBuffer::New(isolate, my_data.start(), 100);
3649 CheckInternalFieldsAreZero(ab3);
3650 CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
3651 CHECK(ab3->IsExternal());
3652
3653 CHECK(env->Global()->Set(env.local(), v8_str("ab3"), ab3).FromJust());
3654
3655 v8::Local<v8::Value> result = CompileRun("ab3.byteLength");
3656 CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
3657
3658 result = CompileRun(
3659 "var u8_b = new Uint8Array(ab3);"
3660 "u8_b[0] = 0xBB;"
3661 "u8_b[1] = 0xCC;"
3662 "u8_b.length");
3663 CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
3664 CHECK_EQ(0xBB, my_data[0]);
3665 CHECK_EQ(0xCC, my_data[1]);
3666 my_data[0] = 0xCC;
3667 my_data[1] = 0x11;
3668 result = CompileRun("u8_b[0] + u8_b[1]");
3669 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
3670}
3671
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003672
3673THREADED_TEST(HiddenProperties) {
3674 LocalContext env;
3675 v8::Isolate* isolate = env->GetIsolate();
3676 v8::HandleScope scope(isolate);
3677
3678 v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003679 v8::Local<v8::Private> key =
3680 v8::Private::ForApi(isolate, v8_str("api-test::hidden-key"));
Steve Blocka7e24c12009-10-30 11:49:00 +00003681 v8::Local<v8::String> empty = v8_str("");
3682 v8::Local<v8::String> prop_name = v8_str("prop_name");
3683
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003684 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +00003685
3686 // Make sure delete of a non-existent hidden value works
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003687 obj->DeletePrivate(env.local(), key).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00003688
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003689 CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 1503))
3690 .FromJust());
3691 CHECK_EQ(1503, obj->GetPrivate(env.local(), key)
3692 .ToLocalChecked()
3693 ->Int32Value(env.local())
3694 .FromJust());
3695 CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 2002))
3696 .FromJust());
3697 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3698 .ToLocalChecked()
3699 ->Int32Value(env.local())
3700 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00003701
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003702 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +00003703
3704 // Make sure we do not find the hidden property.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003705 CHECK(!obj->Has(env.local(), empty).FromJust());
3706 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3707 .ToLocalChecked()
3708 ->Int32Value(env.local())
3709 .FromJust());
3710 CHECK(obj->Get(env.local(), empty).ToLocalChecked()->IsUndefined());
3711 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3712 .ToLocalChecked()
3713 ->Int32Value(env.local())
3714 .FromJust());
3715 CHECK(
3716 obj->Set(env.local(), empty, v8::Integer::New(isolate, 2003)).FromJust());
3717 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3718 .ToLocalChecked()
3719 ->Int32Value(env.local())
3720 .FromJust());
3721 CHECK_EQ(2003, obj->Get(env.local(), empty)
3722 .ToLocalChecked()
3723 ->Int32Value(env.local())
3724 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00003725
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003726 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +00003727
3728 // Add another property and delete it afterwards to force the object in
3729 // slow case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003730 CHECK(obj->Set(env.local(), prop_name, v8::Integer::New(isolate, 2008))
3731 .FromJust());
3732 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3733 .ToLocalChecked()
3734 ->Int32Value(env.local())
3735 .FromJust());
3736 CHECK_EQ(2008, obj->Get(env.local(), prop_name)
3737 .ToLocalChecked()
3738 ->Int32Value(env.local())
3739 .FromJust());
3740 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3741 .ToLocalChecked()
3742 ->Int32Value(env.local())
3743 .FromJust());
3744 CHECK(obj->Delete(env.local(), prop_name).FromJust());
3745 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3746 .ToLocalChecked()
3747 ->Int32Value(env.local())
3748 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00003749
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003750 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +00003751
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003752 CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 2002))
3753 .FromJust());
3754 CHECK(obj->DeletePrivate(env.local(), key).FromJust());
3755 CHECK(!obj->HasPrivate(env.local(), key).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00003756}
3757
3758
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003759THREADED_TEST(Regress97784) {
3760 // Regression test for crbug.com/97784
3761 // Messing with the Object.prototype should not have effect on
3762 // hidden properties.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003763 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003764 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003765
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003766 v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003767 v8::Local<v8::Private> key =
3768 v8::Private::New(env->GetIsolate(), v8_str("hidden"));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003769
3770 CompileRun(
3771 "set_called = false;"
3772 "Object.defineProperty("
3773 " Object.prototype,"
3774 " 'hidden',"
3775 " {get: function() { return 45; },"
3776 " set: function() { set_called = true; }})");
3777
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003778 CHECK(!obj->HasPrivate(env.local(), key).FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003779 // Make sure that the getter and setter from Object.prototype is not invoked.
3780 // If it did we would have full access to the hidden properties in
3781 // the accessor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003782 CHECK(
3783 obj->SetPrivate(env.local(), key, v8::Integer::New(env->GetIsolate(), 42))
3784 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003785 ExpectFalse("set_called");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003786 CHECK_EQ(42, obj->GetPrivate(env.local(), key)
3787 .ToLocalChecked()
3788 ->Int32Value(env.local())
3789 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00003790}
3791
3792
3793THREADED_TEST(External) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003794 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00003795 int x = 3;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003796 Local<v8::External> ext = v8::External::New(CcTest::isolate(), &x);
Steve Blocka7e24c12009-10-30 11:49:00 +00003797 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003798 CHECK(env->Global()->Set(env.local(), v8_str("ext"), ext).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003799 Local<Value> reext_obj = CompileRun("this.ext");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003800 v8::Local<v8::External> reext = reext_obj.As<v8::External>();
Steve Blocka7e24c12009-10-30 11:49:00 +00003801 int* ptr = static_cast<int*>(reext->Value());
3802 CHECK_EQ(x, 3);
3803 *ptr = 10;
3804 CHECK_EQ(x, 10);
3805
3806 // Make sure unaligned pointers are wrapped properly.
3807 char* data = i::StrDup("0123456789");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003808 Local<v8::Value> zero = v8::External::New(CcTest::isolate(), &data[0]);
3809 Local<v8::Value> one = v8::External::New(CcTest::isolate(), &data[1]);
3810 Local<v8::Value> two = v8::External::New(CcTest::isolate(), &data[2]);
3811 Local<v8::Value> three = v8::External::New(CcTest::isolate(), &data[3]);
Steve Blocka7e24c12009-10-30 11:49:00 +00003812
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003813 char* char_ptr = reinterpret_cast<char*>(v8::External::Cast(*zero)->Value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003814 CHECK_EQ('0', *char_ptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003815 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*one)->Value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003816 CHECK_EQ('1', *char_ptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003817 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*two)->Value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003818 CHECK_EQ('2', *char_ptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003819 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*three)->Value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003820 CHECK_EQ('3', *char_ptr);
3821 i::DeleteArray(data);
3822}
3823
3824
3825THREADED_TEST(GlobalHandle) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003826 v8::Isolate* isolate = CcTest::isolate();
Steve Blocka7e24c12009-10-30 11:49:00 +00003827 v8::Persistent<String> global;
3828 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003829 v8::HandleScope scope(isolate);
3830 global.Reset(isolate, v8_str("str"));
Steve Blocka7e24c12009-10-30 11:49:00 +00003831 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003832 {
3833 v8::HandleScope scope(isolate);
3834 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3835 }
3836 global.Reset();
3837 {
3838 v8::HandleScope scope(isolate);
3839 global.Reset(isolate, v8_str("str"));
3840 }
3841 {
3842 v8::HandleScope scope(isolate);
3843 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3844 }
3845 global.Reset();
3846}
3847
3848
3849THREADED_TEST(ResettingGlobalHandle) {
3850 v8::Isolate* isolate = CcTest::isolate();
3851 v8::Persistent<String> global;
3852 {
3853 v8::HandleScope scope(isolate);
3854 global.Reset(isolate, v8_str("str"));
3855 }
3856 v8::internal::GlobalHandles* global_handles =
3857 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3858 int initial_handle_count = global_handles->global_handles_count();
3859 {
3860 v8::HandleScope scope(isolate);
3861 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3862 }
3863 {
3864 v8::HandleScope scope(isolate);
3865 global.Reset(isolate, v8_str("longer"));
3866 }
3867 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count);
3868 {
3869 v8::HandleScope scope(isolate);
3870 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 6);
3871 }
3872 global.Reset();
3873 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
3874}
3875
3876
3877THREADED_TEST(ResettingGlobalHandleToEmpty) {
3878 v8::Isolate* isolate = CcTest::isolate();
3879 v8::Persistent<String> global;
3880 {
3881 v8::HandleScope scope(isolate);
3882 global.Reset(isolate, v8_str("str"));
3883 }
3884 v8::internal::GlobalHandles* global_handles =
3885 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3886 int initial_handle_count = global_handles->global_handles_count();
3887 {
3888 v8::HandleScope scope(isolate);
3889 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3890 }
3891 {
3892 v8::HandleScope scope(isolate);
3893 Local<String> empty;
3894 global.Reset(isolate, empty);
3895 }
3896 CHECK(global.IsEmpty());
3897 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
3898}
3899
3900
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003901template <class T>
3902static v8::Global<T> PassUnique(v8::Global<T> unique) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003903 return unique.Pass();
3904}
3905
3906
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003907template <class T>
3908static v8::Global<T> ReturnUnique(v8::Isolate* isolate,
3909 const v8::Persistent<T>& global) {
3910 v8::Global<String> unique(isolate, global);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003911 return unique.Pass();
3912}
3913
3914
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003915THREADED_TEST(Global) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003916 v8::Isolate* isolate = CcTest::isolate();
3917 v8::Persistent<String> global;
3918 {
3919 v8::HandleScope scope(isolate);
3920 global.Reset(isolate, v8_str("str"));
3921 }
3922 v8::internal::GlobalHandles* global_handles =
3923 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3924 int initial_handle_count = global_handles->global_handles_count();
3925 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003926 v8::Global<String> unique(isolate, global);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003927 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3928 // Test assignment via Pass
3929 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003930 v8::Global<String> copy = unique.Pass();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003931 CHECK(unique.IsEmpty());
3932 CHECK(copy == global);
3933 CHECK_EQ(initial_handle_count + 1,
3934 global_handles->global_handles_count());
3935 unique = copy.Pass();
3936 }
3937 // Test ctor via Pass
3938 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003939 v8::Global<String> copy(unique.Pass());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003940 CHECK(unique.IsEmpty());
3941 CHECK(copy == global);
3942 CHECK_EQ(initial_handle_count + 1,
3943 global_handles->global_handles_count());
3944 unique = copy.Pass();
3945 }
3946 // Test pass through function call
3947 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003948 v8::Global<String> copy = PassUnique(unique.Pass());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003949 CHECK(unique.IsEmpty());
3950 CHECK(copy == global);
3951 CHECK_EQ(initial_handle_count + 1,
3952 global_handles->global_handles_count());
3953 unique = copy.Pass();
3954 }
3955 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3956 }
3957 // Test pass from function call
3958 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003959 v8::Global<String> unique = ReturnUnique(isolate, global);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003960 CHECK(unique == global);
3961 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3962 }
3963 CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
3964 global.Reset();
3965}
3966
3967
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003968namespace {
3969
3970class TwoPassCallbackData;
3971void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
3972void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
3973
3974
3975class TwoPassCallbackData {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003976 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003977 TwoPassCallbackData(v8::Isolate* isolate, int* instance_counter)
3978 : first_pass_called_(false),
3979 second_pass_called_(false),
3980 trigger_gc_(false),
3981 instance_counter_(instance_counter) {
3982 HandleScope scope(isolate);
3983 i::ScopedVector<char> buffer(40);
3984 i::SNPrintF(buffer, "%p", static_cast<void*>(this));
3985 auto string =
3986 v8::String::NewFromUtf8(isolate, buffer.start(),
3987 v8::NewStringType::kNormal).ToLocalChecked();
3988 cell_.Reset(isolate, string);
3989 (*instance_counter_)++;
3990 }
3991
3992 ~TwoPassCallbackData() {
3993 CHECK(first_pass_called_);
3994 CHECK(second_pass_called_);
3995 CHECK(cell_.IsEmpty());
3996 (*instance_counter_)--;
3997 }
3998
3999 void FirstPass() {
4000 CHECK(!first_pass_called_);
4001 CHECK(!second_pass_called_);
4002 CHECK(!cell_.IsEmpty());
4003 cell_.Reset();
4004 first_pass_called_ = true;
4005 }
4006
4007 void SecondPass() {
4008 CHECK(first_pass_called_);
4009 CHECK(!second_pass_called_);
4010 CHECK(cell_.IsEmpty());
4011 second_pass_called_ = true;
4012 delete this;
4013 }
4014
4015 void SetWeak() {
4016 cell_.SetWeak(this, FirstPassCallback, v8::WeakCallbackType::kParameter);
4017 }
4018
4019 void MarkTriggerGc() { trigger_gc_ = true; }
4020 bool trigger_gc() { return trigger_gc_; }
4021
4022 int* instance_counter() { return instance_counter_; }
4023
4024 private:
4025 bool first_pass_called_;
4026 bool second_pass_called_;
4027 bool trigger_gc_;
4028 v8::Global<v8::String> cell_;
4029 int* instance_counter_;
4030};
4031
4032
4033void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
4034 ApiTestFuzzer::Fuzz();
4035 bool trigger_gc = data.GetParameter()->trigger_gc();
4036 int* instance_counter = data.GetParameter()->instance_counter();
4037 data.GetParameter()->SecondPass();
4038 if (!trigger_gc) return;
4039 auto data_2 = new TwoPassCallbackData(data.GetIsolate(), instance_counter);
4040 data_2->SetWeak();
4041 CcTest::heap()->CollectAllGarbage();
4042}
4043
4044
4045void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
4046 data.GetParameter()->FirstPass();
4047 data.SetSecondPassCallback(SecondPassCallback);
4048}
4049
4050} // namespace
4051
4052
4053TEST(TwoPassPhantomCallbacks) {
4054 auto isolate = CcTest::isolate();
4055 const size_t kLength = 20;
4056 int instance_counter = 0;
4057 for (size_t i = 0; i < kLength; ++i) {
4058 auto data = new TwoPassCallbackData(isolate, &instance_counter);
4059 data->SetWeak();
4060 }
4061 CHECK_EQ(static_cast<int>(kLength), instance_counter);
4062 CcTest::heap()->CollectAllGarbage();
4063 EmptyMessageQueues(isolate);
4064 CHECK_EQ(0, instance_counter);
4065}
4066
4067
4068TEST(TwoPassPhantomCallbacksNestedGc) {
4069 auto isolate = CcTest::isolate();
4070 const size_t kLength = 20;
4071 TwoPassCallbackData* array[kLength];
4072 int instance_counter = 0;
4073 for (size_t i = 0; i < kLength; ++i) {
4074 array[i] = new TwoPassCallbackData(isolate, &instance_counter);
4075 array[i]->SetWeak();
4076 }
4077 array[5]->MarkTriggerGc();
4078 array[10]->MarkTriggerGc();
4079 array[15]->MarkTriggerGc();
4080 CHECK_EQ(static_cast<int>(kLength), instance_counter);
4081 CcTest::heap()->CollectAllGarbage();
4082 EmptyMessageQueues(isolate);
4083 CHECK_EQ(0, instance_counter);
4084}
4085
4086
4087namespace {
4088
4089void* IntKeyToVoidPointer(int key) { return reinterpret_cast<void*>(key << 1); }
4090
4091
4092Local<v8::Object> NewObjectForIntKey(
4093 v8::Isolate* isolate, const v8::Global<v8::ObjectTemplate>& templ,
4094 int key) {
4095 auto local = Local<v8::ObjectTemplate>::New(isolate, templ);
4096 auto obj = local->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
4097 obj->SetAlignedPointerInInternalField(0, IntKeyToVoidPointer(key));
4098 return obj;
4099}
4100
4101
4102template <typename K, typename V>
4103class PhantomStdMapTraits : public v8::StdMapTraits<K, V> {
4104 public:
4105 typedef typename v8::GlobalValueMap<K, V, PhantomStdMapTraits<K, V>> MapType;
4106 static const v8::PersistentContainerCallbackType kCallbackType =
4107 v8::kWeakWithInternalFields;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004108 struct WeakCallbackDataType {
4109 MapType* map;
4110 K key;
4111 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004112 static WeakCallbackDataType* WeakCallbackParameter(MapType* map, const K& key,
4113 Local<V> value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004114 WeakCallbackDataType* data = new WeakCallbackDataType;
4115 data->map = map;
4116 data->key = key;
4117 return data;
4118 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004119 static MapType* MapFromWeakCallbackInfo(
4120 const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004121 return data.GetParameter()->map;
4122 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004123 static K KeyFromWeakCallbackInfo(
4124 const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004125 return data.GetParameter()->key;
4126 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004127 static void DisposeCallbackData(WeakCallbackDataType* data) { delete data; }
4128 static void Dispose(v8::Isolate* isolate, v8::Global<V> value, K key) {
4129 CHECK_EQ(IntKeyToVoidPointer(key),
4130 v8::Object::GetAlignedPointerFromInternalField(value, 0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004131 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004132 static void OnWeakCallback(
4133 const v8::WeakCallbackInfo<WeakCallbackDataType>&) {}
4134 static void DisposeWeak(
4135 const v8::WeakCallbackInfo<WeakCallbackDataType>& info) {
4136 K key = KeyFromWeakCallbackInfo(info);
4137 CHECK_EQ(IntKeyToVoidPointer(key), info.GetInternalField(0));
4138 DisposeCallbackData(info.GetParameter());
4139 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004140};
4141
4142
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004143template <typename Map>
4144void TestGlobalValueMap() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004145 LocalContext env;
4146 v8::Isolate* isolate = env->GetIsolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004147 v8::Global<ObjectTemplate> templ;
4148 {
4149 HandleScope scope(isolate);
4150 auto t = ObjectTemplate::New(isolate);
4151 t->SetInternalFieldCount(1);
4152 templ.Reset(isolate, t);
4153 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004154 Map map(isolate);
4155 v8::internal::GlobalHandles* global_handles =
4156 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
4157 int initial_handle_count = global_handles->global_handles_count();
4158 CHECK_EQ(0, static_cast<int>(map.Size()));
4159 {
4160 HandleScope scope(isolate);
4161 Local<v8::Object> obj = map.Get(7);
4162 CHECK(obj.IsEmpty());
4163 Local<v8::Object> expected = v8::Object::New(isolate);
4164 map.Set(7, expected);
4165 CHECK_EQ(1, static_cast<int>(map.Size()));
4166 obj = map.Get(7);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004167 CHECK(expected->Equals(env.local(), obj).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004168 {
4169 typename Map::PersistentValueReference ref = map.GetReference(7);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004170 CHECK(expected->Equals(env.local(), ref.NewLocal(isolate)).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004171 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004172 v8::Global<v8::Object> removed = map.Remove(7);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004173 CHECK_EQ(0, static_cast<int>(map.Size()));
4174 CHECK(expected == removed);
4175 removed = map.Remove(7);
4176 CHECK(removed.IsEmpty());
4177 map.Set(8, expected);
4178 CHECK_EQ(1, static_cast<int>(map.Size()));
4179 map.Set(8, expected);
4180 CHECK_EQ(1, static_cast<int>(map.Size()));
4181 {
4182 typename Map::PersistentValueReference ref;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004183 Local<v8::Object> expected2 = NewObjectForIntKey(isolate, templ, 8);
4184 removed = map.Set(8, v8::Global<v8::Object>(isolate, expected2), &ref);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004185 CHECK_EQ(1, static_cast<int>(map.Size()));
4186 CHECK(expected == removed);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004187 CHECK(expected2->Equals(env.local(), ref.NewLocal(isolate)).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004188 }
4189 }
4190 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
4191 if (map.IsWeak()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004192 CcTest::i_isolate()->heap()->CollectAllGarbage(
4193 i::Heap::kAbortIncrementalMarkingMask);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004194 } else {
4195 map.Clear();
4196 }
4197 CHECK_EQ(0, static_cast<int>(map.Size()));
4198 CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004199 {
4200 HandleScope scope(isolate);
4201 Local<v8::Object> value = NewObjectForIntKey(isolate, templ, 9);
4202 map.Set(9, value);
4203 map.Clear();
4204 }
4205 CHECK_EQ(0, static_cast<int>(map.Size()));
4206 CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004207}
4208
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004209} // namespace
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004210
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004211
4212TEST(GlobalValueMap) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004213 // Default case, w/o weak callbacks:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004214 TestGlobalValueMap<v8::StdGlobalValueMap<int, v8::Object>>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004215
4216 // Custom traits with weak callbacks:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004217 typedef v8::GlobalValueMap<int, v8::Object,
4218 PhantomStdMapTraits<int, v8::Object>> WeakMap;
4219 TestGlobalValueMap<WeakMap>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004220}
4221
4222
4223TEST(PersistentValueVector) {
4224 LocalContext env;
4225 v8::Isolate* isolate = env->GetIsolate();
4226 v8::internal::GlobalHandles* global_handles =
4227 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
4228 int handle_count = global_handles->global_handles_count();
4229 HandleScope scope(isolate);
4230
4231 v8::PersistentValueVector<v8::Object> vector(isolate);
4232
4233 Local<v8::Object> obj1 = v8::Object::New(isolate);
4234 Local<v8::Object> obj2 = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004235 v8::Global<v8::Object> obj3(isolate, v8::Object::New(isolate));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004236
4237 CHECK(vector.IsEmpty());
4238 CHECK_EQ(0, static_cast<int>(vector.Size()));
4239
4240 vector.ReserveCapacity(3);
4241 CHECK(vector.IsEmpty());
4242
4243 vector.Append(obj1);
4244 vector.Append(obj2);
4245 vector.Append(obj1);
4246 vector.Append(obj3.Pass());
4247 vector.Append(obj1);
4248
4249 CHECK(!vector.IsEmpty());
4250 CHECK_EQ(5, static_cast<int>(vector.Size()));
4251 CHECK(obj3.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004252 CHECK(obj1->Equals(env.local(), vector.Get(0)).FromJust());
4253 CHECK(obj1->Equals(env.local(), vector.Get(2)).FromJust());
4254 CHECK(obj1->Equals(env.local(), vector.Get(4)).FromJust());
4255 CHECK(obj2->Equals(env.local(), vector.Get(1)).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004256
4257 CHECK_EQ(5 + handle_count, global_handles->global_handles_count());
4258
4259 vector.Clear();
4260 CHECK(vector.IsEmpty());
4261 CHECK_EQ(0, static_cast<int>(vector.Size()));
4262 CHECK_EQ(handle_count, global_handles->global_handles_count());
4263}
4264
4265
4266THREADED_TEST(GlobalHandleUpcast) {
4267 v8::Isolate* isolate = CcTest::isolate();
4268 v8::HandleScope scope(isolate);
4269 v8::Local<String> local = v8::Local<String>::New(isolate, v8_str("str"));
4270 v8::Persistent<String> global_string(isolate, local);
4271 v8::Persistent<Value>& global_value =
4272 v8::Persistent<Value>::Cast(global_string);
4273 CHECK(v8::Local<v8::Value>::New(isolate, global_value)->IsString());
4274 CHECK(global_string == v8::Persistent<String>::Cast(global_value));
4275 global_string.Reset();
4276}
4277
4278
4279THREADED_TEST(HandleEquality) {
4280 v8::Isolate* isolate = CcTest::isolate();
4281 v8::Persistent<String> global1;
4282 v8::Persistent<String> global2;
4283 {
4284 v8::HandleScope scope(isolate);
4285 global1.Reset(isolate, v8_str("str"));
4286 global2.Reset(isolate, v8_str("str2"));
4287 }
4288 CHECK_EQ(global1 == global1, true);
4289 CHECK_EQ(global1 != global1, false);
4290 {
4291 v8::HandleScope scope(isolate);
4292 Local<String> local1 = Local<String>::New(isolate, global1);
4293 Local<String> local2 = Local<String>::New(isolate, global2);
4294
4295 CHECK_EQ(global1 == local1, true);
4296 CHECK_EQ(global1 != local1, false);
4297 CHECK_EQ(local1 == global1, true);
4298 CHECK_EQ(local1 != global1, false);
4299
4300 CHECK_EQ(global1 == local2, false);
4301 CHECK_EQ(global1 != local2, true);
4302 CHECK_EQ(local2 == global1, false);
4303 CHECK_EQ(local2 != global1, true);
4304
4305 CHECK_EQ(local1 == local2, false);
4306 CHECK_EQ(local1 != local2, true);
4307
4308 Local<String> anotherLocal1 = Local<String>::New(isolate, global1);
4309 CHECK_EQ(local1 == anotherLocal1, true);
4310 CHECK_EQ(local1 != anotherLocal1, false);
4311 }
4312 global1.Reset();
4313 global2.Reset();
4314}
4315
4316
4317THREADED_TEST(LocalHandle) {
4318 v8::HandleScope scope(CcTest::isolate());
4319 v8::Local<String> local =
4320 v8::Local<String>::New(CcTest::isolate(), v8_str("str"));
4321 CHECK_EQ(local->Length(), 3);
Steve Blocka7e24c12009-10-30 11:49:00 +00004322}
4323
4324
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004325class WeakCallCounter {
4326 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004327 explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) {}
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004328 int id() { return id_; }
4329 void increment() { number_of_weak_calls_++; }
4330 int NumberOfWeakCalls() { return number_of_weak_calls_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004331
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004332 private:
4333 int id_;
4334 int number_of_weak_calls_;
4335};
4336
4337
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004338template <typename T>
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004339struct WeakCallCounterAndPersistent {
4340 explicit WeakCallCounterAndPersistent(WeakCallCounter* counter)
4341 : counter(counter) {}
4342 WeakCallCounter* counter;
4343 v8::Persistent<T> handle;
4344};
4345
4346
4347template <typename T>
4348static void WeakPointerCallback(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004349 const v8::WeakCallbackInfo<WeakCallCounterAndPersistent<T>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004350 CHECK_EQ(1234, data.GetParameter()->counter->id());
4351 data.GetParameter()->counter->increment();
4352 data.GetParameter()->handle.Reset();
4353}
4354
4355
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004356template <typename T>
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004357static UniqueId MakeUniqueId(const Persistent<T>& p) {
4358 return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
Steve Block44f0eee2011-05-26 01:26:41 +01004359}
4360
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004361
Steve Block44f0eee2011-05-26 01:26:41 +01004362THREADED_TEST(ApiObjectGroups) {
Steve Block44f0eee2011-05-26 01:26:41 +01004363 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004364 v8::Isolate* iso = env->GetIsolate();
4365 HandleScope scope(iso);
Steve Block44f0eee2011-05-26 01:26:41 +01004366
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004367 WeakCallCounter counter(1234);
4368
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004369 WeakCallCounterAndPersistent<Value> g1s1(&counter);
4370 WeakCallCounterAndPersistent<Value> g1s2(&counter);
4371 WeakCallCounterAndPersistent<Value> g1c1(&counter);
4372 WeakCallCounterAndPersistent<Value> g2s1(&counter);
4373 WeakCallCounterAndPersistent<Value> g2s2(&counter);
4374 WeakCallCounterAndPersistent<Value> g2c1(&counter);
Steve Block44f0eee2011-05-26 01:26:41 +01004375
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004376 {
4377 HandleScope scope(iso);
4378 g1s1.handle.Reset(iso, Object::New(iso));
4379 g1s2.handle.Reset(iso, Object::New(iso));
4380 g1c1.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004381 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
4382 v8::WeakCallbackType::kParameter);
4383 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
4384 v8::WeakCallbackType::kParameter);
4385 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
4386 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004387
4388 g2s1.handle.Reset(iso, Object::New(iso));
4389 g2s2.handle.Reset(iso, Object::New(iso));
4390 g2c1.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004391 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
4392 v8::WeakCallbackType::kParameter);
4393 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
4394 v8::WeakCallbackType::kParameter);
4395 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
4396 v8::WeakCallbackType::kParameter);
Steve Block44f0eee2011-05-26 01:26:41 +01004397 }
4398
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004399 WeakCallCounterAndPersistent<Value> root(&counter);
4400 root.handle.Reset(iso, g1s1.handle); // make a root.
Steve Block44f0eee2011-05-26 01:26:41 +01004401
4402 // Connect group 1 and 2, make a cycle.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004403 {
4404 HandleScope scope(iso);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004405 CHECK(Local<Object>::New(iso, g1s2.handle.As<Object>())
4406 ->Set(env.local(), 0, Local<Value>::New(iso, g2s2.handle))
4407 .FromJust());
4408 CHECK(Local<Object>::New(iso, g2s1.handle.As<Object>())
4409 ->Set(env.local(), 0, Local<Value>::New(iso, g1s1.handle))
4410 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004411 }
Steve Block44f0eee2011-05-26 01:26:41 +01004412
4413 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004414 UniqueId id1 = MakeUniqueId(g1s1.handle);
4415 UniqueId id2 = MakeUniqueId(g2s2.handle);
4416 iso->SetObjectGroupId(g1s1.handle, id1);
4417 iso->SetObjectGroupId(g1s2.handle, id1);
4418 iso->SetReferenceFromGroup(id1, g1c1.handle);
4419 iso->SetObjectGroupId(g2s1.handle, id2);
4420 iso->SetObjectGroupId(g2s2.handle, id2);
4421 iso->SetReferenceFromGroup(id2, g2c1.handle);
Steve Block44f0eee2011-05-26 01:26:41 +01004422 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004423 // Do a single full GC, ensure incremental marking is stopped.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004424 v8::internal::Heap* heap =
4425 reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
4426 heap->CollectAllGarbage();
Steve Block44f0eee2011-05-26 01:26:41 +01004427
4428 // All object should be alive.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004429 CHECK_EQ(0, counter.NumberOfWeakCalls());
Steve Block44f0eee2011-05-26 01:26:41 +01004430
4431 // Weaken the root.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004432 root.handle.SetWeak(&root, &WeakPointerCallback,
4433 v8::WeakCallbackType::kParameter);
Steve Block44f0eee2011-05-26 01:26:41 +01004434 // But make children strong roots---all the objects (except for children)
4435 // should be collectable now.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004436 g1c1.handle.ClearWeak();
4437 g2c1.handle.ClearWeak();
Steve Block44f0eee2011-05-26 01:26:41 +01004438
4439 // Groups are deleted, rebuild groups.
4440 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004441 UniqueId id1 = MakeUniqueId(g1s1.handle);
4442 UniqueId id2 = MakeUniqueId(g2s2.handle);
4443 iso->SetObjectGroupId(g1s1.handle, id1);
4444 iso->SetObjectGroupId(g1s2.handle, id1);
4445 iso->SetReferenceFromGroup(id1, g1c1.handle);
4446 iso->SetObjectGroupId(g2s1.handle, id2);
4447 iso->SetObjectGroupId(g2s2.handle, id2);
4448 iso->SetReferenceFromGroup(id2, g2c1.handle);
Steve Block44f0eee2011-05-26 01:26:41 +01004449 }
4450
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004451 heap->CollectAllGarbage();
Steve Block44f0eee2011-05-26 01:26:41 +01004452
4453 // All objects should be gone. 5 global handles in total.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004454 CHECK_EQ(5, counter.NumberOfWeakCalls());
Steve Block44f0eee2011-05-26 01:26:41 +01004455
4456 // And now make children weak again and collect them.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004457 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
4458 v8::WeakCallbackType::kParameter);
4459 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
4460 v8::WeakCallbackType::kParameter);
Steve Block44f0eee2011-05-26 01:26:41 +01004461
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004462 heap->CollectAllGarbage();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004463 CHECK_EQ(7, counter.NumberOfWeakCalls());
Steve Block44f0eee2011-05-26 01:26:41 +01004464}
4465
4466
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004467THREADED_TEST(ApiObjectGroupsForSubtypes) {
Steve Block44f0eee2011-05-26 01:26:41 +01004468 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004469 v8::Isolate* iso = env->GetIsolate();
4470 HandleScope scope(iso);
Steve Block44f0eee2011-05-26 01:26:41 +01004471
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004472 WeakCallCounter counter(1234);
Steve Block44f0eee2011-05-26 01:26:41 +01004473
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004474 WeakCallCounterAndPersistent<Object> g1s1(&counter);
4475 WeakCallCounterAndPersistent<String> g1s2(&counter);
4476 WeakCallCounterAndPersistent<String> g1c1(&counter);
4477 WeakCallCounterAndPersistent<Object> g2s1(&counter);
4478 WeakCallCounterAndPersistent<String> g2s2(&counter);
4479 WeakCallCounterAndPersistent<String> g2c1(&counter);
Steve Block44f0eee2011-05-26 01:26:41 +01004480
4481 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004482 HandleScope scope(iso);
4483 g1s1.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004484 g1s2.handle.Reset(iso, v8_str("foo1"));
4485 g1c1.handle.Reset(iso, v8_str("foo2"));
4486 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
4487 v8::WeakCallbackType::kParameter);
4488 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
4489 v8::WeakCallbackType::kParameter);
4490 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
4491 v8::WeakCallbackType::kParameter);
Steve Block44f0eee2011-05-26 01:26:41 +01004492
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004493 g2s1.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004494 g2s2.handle.Reset(iso, v8_str("foo3"));
4495 g2c1.handle.Reset(iso, v8_str("foo4"));
4496 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
4497 v8::WeakCallbackType::kParameter);
4498 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
4499 v8::WeakCallbackType::kParameter);
4500 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
4501 v8::WeakCallbackType::kParameter);
Steve Block44f0eee2011-05-26 01:26:41 +01004502 }
4503
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004504 WeakCallCounterAndPersistent<Value> root(&counter);
4505 root.handle.Reset(iso, g1s1.handle); // make a root.
Steve Block44f0eee2011-05-26 01:26:41 +01004506
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004507 // Connect group 1 and 2, make a cycle.
Steve Block44f0eee2011-05-26 01:26:41 +01004508 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004509 HandleScope scope(iso);
4510 CHECK(Local<Object>::New(iso, g1s1.handle)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004511 ->Set(env.local(), 0, Local<Object>::New(iso, g2s1.handle))
4512 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004513 CHECK(Local<Object>::New(iso, g2s1.handle)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004514 ->Set(env.local(), 0, Local<Object>::New(iso, g1s1.handle))
4515 .FromJust());
Steve Block44f0eee2011-05-26 01:26:41 +01004516 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004517
4518 {
4519 UniqueId id1 = MakeUniqueId(g1s1.handle);
4520 UniqueId id2 = MakeUniqueId(g2s2.handle);
4521 iso->SetObjectGroupId(g1s1.handle, id1);
4522 iso->SetObjectGroupId(g1s2.handle, id1);
4523 iso->SetReference(g1s1.handle, g1c1.handle);
4524 iso->SetObjectGroupId(g2s1.handle, id2);
4525 iso->SetObjectGroupId(g2s2.handle, id2);
4526 iso->SetReferenceFromGroup(id2, g2c1.handle);
4527 }
4528 // Do a single full GC, ensure incremental marking is stopped.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004529 v8::internal::Heap* heap =
4530 reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
4531 heap->CollectAllGarbage();
Steve Block44f0eee2011-05-26 01:26:41 +01004532
4533 // All object should be alive.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004534 CHECK_EQ(0, counter.NumberOfWeakCalls());
Steve Block44f0eee2011-05-26 01:26:41 +01004535
4536 // Weaken the root.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004537 root.handle.SetWeak(&root, &WeakPointerCallback,
4538 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004539 // But make children strong roots---all the objects (except for children)
4540 // should be collectable now.
4541 g1c1.handle.ClearWeak();
4542 g2c1.handle.ClearWeak();
Steve Block44f0eee2011-05-26 01:26:41 +01004543
4544 // Groups are deleted, rebuild groups.
4545 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004546 UniqueId id1 = MakeUniqueId(g1s1.handle);
4547 UniqueId id2 = MakeUniqueId(g2s2.handle);
4548 iso->SetObjectGroupId(g1s1.handle, id1);
4549 iso->SetObjectGroupId(g1s2.handle, id1);
4550 iso->SetReference(g1s1.handle, g1c1.handle);
4551 iso->SetObjectGroupId(g2s1.handle, id2);
4552 iso->SetObjectGroupId(g2s2.handle, id2);
4553 iso->SetReferenceFromGroup(id2, g2c1.handle);
Steve Block44f0eee2011-05-26 01:26:41 +01004554 }
4555
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004556 heap->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004557
4558 // All objects should be gone. 5 global handles in total.
4559 CHECK_EQ(5, counter.NumberOfWeakCalls());
4560
4561 // And now make children weak again and collect them.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004562 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
4563 v8::WeakCallbackType::kParameter);
4564 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
4565 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004566
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004567 heap->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004568 CHECK_EQ(7, counter.NumberOfWeakCalls());
4569}
4570
4571
4572THREADED_TEST(ApiObjectGroupsCycle) {
4573 LocalContext env;
4574 v8::Isolate* iso = env->GetIsolate();
4575 HandleScope scope(iso);
4576
4577 WeakCallCounter counter(1234);
4578
4579 WeakCallCounterAndPersistent<Value> g1s1(&counter);
4580 WeakCallCounterAndPersistent<Value> g1s2(&counter);
4581 WeakCallCounterAndPersistent<Value> g2s1(&counter);
4582 WeakCallCounterAndPersistent<Value> g2s2(&counter);
4583 WeakCallCounterAndPersistent<Value> g3s1(&counter);
4584 WeakCallCounterAndPersistent<Value> g3s2(&counter);
4585 WeakCallCounterAndPersistent<Value> g4s1(&counter);
4586 WeakCallCounterAndPersistent<Value> g4s2(&counter);
4587
4588 {
4589 HandleScope scope(iso);
4590 g1s1.handle.Reset(iso, Object::New(iso));
4591 g1s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004592 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
4593 v8::WeakCallbackType::kParameter);
4594 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
4595 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004596 CHECK(g1s1.handle.IsWeak());
4597 CHECK(g1s2.handle.IsWeak());
4598
4599 g2s1.handle.Reset(iso, Object::New(iso));
4600 g2s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004601 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
4602 v8::WeakCallbackType::kParameter);
4603 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
4604 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004605 CHECK(g2s1.handle.IsWeak());
4606 CHECK(g2s2.handle.IsWeak());
4607
4608 g3s1.handle.Reset(iso, Object::New(iso));
4609 g3s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004610 g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback,
4611 v8::WeakCallbackType::kParameter);
4612 g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback,
4613 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004614 CHECK(g3s1.handle.IsWeak());
4615 CHECK(g3s2.handle.IsWeak());
4616
4617 g4s1.handle.Reset(iso, Object::New(iso));
4618 g4s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004619 g4s1.handle.SetWeak(&g4s1, &WeakPointerCallback,
4620 v8::WeakCallbackType::kParameter);
4621 g4s2.handle.SetWeak(&g4s2, &WeakPointerCallback,
4622 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004623 CHECK(g4s1.handle.IsWeak());
4624 CHECK(g4s2.handle.IsWeak());
4625 }
4626
4627 WeakCallCounterAndPersistent<Value> root(&counter);
4628 root.handle.Reset(iso, g1s1.handle); // make a root.
4629
4630 // Connect groups. We're building the following cycle:
4631 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
4632 // groups.
4633 {
4634 UniqueId id1 = MakeUniqueId(g1s1.handle);
4635 UniqueId id2 = MakeUniqueId(g2s1.handle);
4636 UniqueId id3 = MakeUniqueId(g3s1.handle);
4637 UniqueId id4 = MakeUniqueId(g4s1.handle);
4638 iso->SetObjectGroupId(g1s1.handle, id1);
4639 iso->SetObjectGroupId(g1s2.handle, id1);
4640 iso->SetReferenceFromGroup(id1, g2s1.handle);
4641 iso->SetObjectGroupId(g2s1.handle, id2);
4642 iso->SetObjectGroupId(g2s2.handle, id2);
4643 iso->SetReferenceFromGroup(id2, g3s1.handle);
4644 iso->SetObjectGroupId(g3s1.handle, id3);
4645 iso->SetObjectGroupId(g3s2.handle, id3);
4646 iso->SetReferenceFromGroup(id3, g4s1.handle);
4647 iso->SetObjectGroupId(g4s1.handle, id4);
4648 iso->SetObjectGroupId(g4s2.handle, id4);
4649 iso->SetReferenceFromGroup(id4, g1s1.handle);
4650 }
4651 // Do a single full GC
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004652 v8::internal::Heap* heap =
4653 reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
4654 heap->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004655
4656 // All object should be alive.
4657 CHECK_EQ(0, counter.NumberOfWeakCalls());
4658
4659 // Weaken the root.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004660 root.handle.SetWeak(&root, &WeakPointerCallback,
4661 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004662
4663 // Groups are deleted, rebuild groups.
4664 {
4665 UniqueId id1 = MakeUniqueId(g1s1.handle);
4666 UniqueId id2 = MakeUniqueId(g2s1.handle);
4667 UniqueId id3 = MakeUniqueId(g3s1.handle);
4668 UniqueId id4 = MakeUniqueId(g4s1.handle);
4669 iso->SetObjectGroupId(g1s1.handle, id1);
4670 iso->SetObjectGroupId(g1s2.handle, id1);
4671 iso->SetReferenceFromGroup(id1, g2s1.handle);
4672 iso->SetObjectGroupId(g2s1.handle, id2);
4673 iso->SetObjectGroupId(g2s2.handle, id2);
4674 iso->SetReferenceFromGroup(id2, g3s1.handle);
4675 iso->SetObjectGroupId(g3s1.handle, id3);
4676 iso->SetObjectGroupId(g3s2.handle, id3);
4677 iso->SetReferenceFromGroup(id3, g4s1.handle);
4678 iso->SetObjectGroupId(g4s1.handle, id4);
4679 iso->SetObjectGroupId(g4s2.handle, id4);
4680 iso->SetReferenceFromGroup(id4, g1s1.handle);
4681 }
4682
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004683 heap->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004684
4685 // All objects should be gone. 9 global handles in total.
4686 CHECK_EQ(9, counter.NumberOfWeakCalls());
4687}
4688
4689
4690// TODO(mstarzinger): This should be a THREADED_TEST but causes failures
4691// on the buildbots, so was made non-threaded for the time being.
4692TEST(ApiObjectGroupsCycleForScavenger) {
4693 i::FLAG_stress_compaction = false;
4694 i::FLAG_gc_global = false;
4695 LocalContext env;
4696 v8::Isolate* iso = env->GetIsolate();
4697 HandleScope scope(iso);
4698
4699 WeakCallCounter counter(1234);
4700
4701 WeakCallCounterAndPersistent<Value> g1s1(&counter);
4702 WeakCallCounterAndPersistent<Value> g1s2(&counter);
4703 WeakCallCounterAndPersistent<Value> g2s1(&counter);
4704 WeakCallCounterAndPersistent<Value> g2s2(&counter);
4705 WeakCallCounterAndPersistent<Value> g3s1(&counter);
4706 WeakCallCounterAndPersistent<Value> g3s2(&counter);
4707
4708 {
4709 HandleScope scope(iso);
4710 g1s1.handle.Reset(iso, Object::New(iso));
4711 g1s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004712 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
4713 v8::WeakCallbackType::kParameter);
4714 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
4715 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004716
4717 g2s1.handle.Reset(iso, Object::New(iso));
4718 g2s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004719 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
4720 v8::WeakCallbackType::kParameter);
4721 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
4722 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004723
4724 g3s1.handle.Reset(iso, Object::New(iso));
4725 g3s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004726 g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback,
4727 v8::WeakCallbackType::kParameter);
4728 g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback,
4729 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004730 }
4731
4732 // Make a root.
4733 WeakCallCounterAndPersistent<Value> root(&counter);
4734 root.handle.Reset(iso, g1s1.handle);
4735 root.handle.MarkPartiallyDependent();
4736
4737 // Connect groups. We're building the following cycle:
4738 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
4739 // groups.
4740 {
4741 HandleScope handle_scope(iso);
4742 g1s1.handle.MarkPartiallyDependent();
4743 g1s2.handle.MarkPartiallyDependent();
4744 g2s1.handle.MarkPartiallyDependent();
4745 g2s2.handle.MarkPartiallyDependent();
4746 g3s1.handle.MarkPartiallyDependent();
4747 g3s2.handle.MarkPartiallyDependent();
4748 iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
4749 iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004750 Local<Object>::New(iso, g1s1.handle.As<Object>())
4751 ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g2s1.handle))
4752 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004753 iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
4754 iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004755 Local<Object>::New(iso, g2s1.handle.As<Object>())
4756 ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g3s1.handle))
4757 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004758 iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
4759 iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004760 Local<Object>::New(iso, g3s1.handle.As<Object>())
4761 ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g1s1.handle))
4762 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004763 }
4764
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004765 v8::internal::Heap* heap =
4766 reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
4767 heap->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004768
4769 // All objects should be alive.
4770 CHECK_EQ(0, counter.NumberOfWeakCalls());
4771
4772 // Weaken the root.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004773 root.handle.SetWeak(&root, &WeakPointerCallback,
4774 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004775 root.handle.MarkPartiallyDependent();
4776
4777 // Groups are deleted, rebuild groups.
4778 {
4779 HandleScope handle_scope(iso);
4780 g1s1.handle.MarkPartiallyDependent();
4781 g1s2.handle.MarkPartiallyDependent();
4782 g2s1.handle.MarkPartiallyDependent();
4783 g2s2.handle.MarkPartiallyDependent();
4784 g3s1.handle.MarkPartiallyDependent();
4785 g3s2.handle.MarkPartiallyDependent();
4786 iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
4787 iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004788 Local<Object>::New(iso, g1s1.handle.As<Object>())
4789 ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g2s1.handle))
4790 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004791 iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
4792 iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004793 Local<Object>::New(iso, g2s1.handle.As<Object>())
4794 ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g3s1.handle))
4795 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004796 iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
4797 iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004798 Local<Object>::New(iso, g3s1.handle.As<Object>())
4799 ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g1s1.handle))
4800 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004801 }
4802
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004803 heap->CollectAllGarbage();
Steve Block44f0eee2011-05-26 01:26:41 +01004804
4805 // All objects should be gone. 7 global handles in total.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004806 CHECK_EQ(7, counter.NumberOfWeakCalls());
Steve Block44f0eee2011-05-26 01:26:41 +01004807}
4808
4809
Steve Blocka7e24c12009-10-30 11:49:00 +00004810THREADED_TEST(ScriptException) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004811 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004812 v8::HandleScope scope(env->GetIsolate());
4813 Local<Script> script = v8_compile("throw 'panama!';");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004814 v8::TryCatch try_catch(env->GetIsolate());
4815 v8::MaybeLocal<Value> result = script->Run(env.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00004816 CHECK(result.IsEmpty());
4817 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004818 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004819 CHECK_EQ(0, strcmp(*exception_value, "panama!"));
Steve Blocka7e24c12009-10-30 11:49:00 +00004820}
4821
4822
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004823TEST(TryCatchCustomException) {
4824 LocalContext env;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004825 v8::Isolate* isolate = env->GetIsolate();
4826 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004827 v8::TryCatch try_catch(isolate);
4828 CompileRun(
4829 "function CustomError() { this.a = 'b'; }"
4830 "(function f() { throw new CustomError(); })();");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004831 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004832 CHECK(try_catch.Exception()
4833 ->ToObject(env.local())
4834 .ToLocalChecked()
4835 ->Get(env.local(), v8_str("a"))
4836 .ToLocalChecked()
4837 ->Equals(env.local(), v8_str("b"))
4838 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004839}
4840
4841
Steve Blocka7e24c12009-10-30 11:49:00 +00004842bool message_received;
4843
4844
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004845static void check_message_0(v8::Local<v8::Message> message,
4846 v8::Local<Value> data) {
4847 CHECK_EQ(5.76, data->NumberValue(CcTest::isolate()->GetCurrentContext())
4848 .FromJust());
4849 CHECK_EQ(6.75, message->GetScriptOrigin()
4850 .ResourceName()
4851 ->NumberValue(CcTest::isolate()->GetCurrentContext())
4852 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004853 CHECK(!message->IsSharedCrossOrigin());
Steve Blocka7e24c12009-10-30 11:49:00 +00004854 message_received = true;
4855}
4856
4857
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004858THREADED_TEST(MessageHandler0) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004859 message_received = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004860 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00004861 CHECK(!message_received);
Steve Blocka7e24c12009-10-30 11:49:00 +00004862 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004863 CcTest::isolate()->AddMessageListener(check_message_0, v8_num(5.76));
4864 v8::Local<v8::Script> script = CompileWithOrigin("throw 'error'", "6.75");
4865 CHECK(script->Run(context.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00004866 CHECK(message_received);
4867 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004868 CcTest::isolate()->RemoveMessageListeners(check_message_0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004869}
4870
4871
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004872static void check_message_1(v8::Local<v8::Message> message,
4873 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004874 CHECK(data->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004875 CHECK_EQ(1337,
4876 data->Int32Value(CcTest::isolate()->GetCurrentContext()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004877 CHECK(!message->IsSharedCrossOrigin());
4878 message_received = true;
4879}
4880
4881
4882TEST(MessageHandler1) {
4883 message_received = false;
4884 v8::HandleScope scope(CcTest::isolate());
4885 CHECK(!message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004886 CcTest::isolate()->AddMessageListener(check_message_1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004887 LocalContext context;
4888 CompileRun("throw 1337;");
4889 CHECK(message_received);
4890 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004891 CcTest::isolate()->RemoveMessageListeners(check_message_1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004892}
4893
4894
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004895static void check_message_2(v8::Local<v8::Message> message,
4896 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004897 LocalContext context;
4898 CHECK(data->IsObject());
4899 v8::Local<v8::Value> hidden_property =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004900 v8::Object::Cast(*data)
4901 ->GetPrivate(
4902 context.local(),
4903 v8::Private::ForApi(CcTest::isolate(), v8_str("hidden key")))
4904 .ToLocalChecked();
4905 CHECK(v8_str("hidden value")
4906 ->Equals(context.local(), hidden_property)
4907 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004908 CHECK(!message->IsSharedCrossOrigin());
4909 message_received = true;
4910}
4911
4912
4913TEST(MessageHandler2) {
4914 message_received = false;
4915 v8::HandleScope scope(CcTest::isolate());
4916 CHECK(!message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004917 CcTest::isolate()->AddMessageListener(check_message_2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004918 LocalContext context;
4919 v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004920 v8::Object::Cast(*error)
4921 ->SetPrivate(context.local(),
4922 v8::Private::ForApi(CcTest::isolate(), v8_str("hidden key")),
4923 v8_str("hidden value"))
4924 .FromJust();
4925 CHECK(context->Global()
4926 ->Set(context.local(), v8_str("error"), error)
4927 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004928 CompileRun("throw error;");
4929 CHECK(message_received);
4930 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004931 CcTest::isolate()->RemoveMessageListeners(check_message_2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004932}
4933
4934
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004935static void check_message_3(v8::Local<v8::Message> message,
4936 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004937 CHECK(message->IsSharedCrossOrigin());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004938 CHECK(message->GetScriptOrigin().Options().IsSharedCrossOrigin());
4939 CHECK(message->GetScriptOrigin().Options().IsEmbedderDebugScript());
4940 CHECK(message->GetScriptOrigin().Options().IsOpaque());
4941 CHECK_EQ(6.75, message->GetScriptOrigin()
4942 .ResourceName()
4943 ->NumberValue(CcTest::isolate()->GetCurrentContext())
4944 .FromJust());
4945 CHECK_EQ(7.40, message->GetScriptOrigin()
4946 .SourceMapUrl()
4947 ->NumberValue(CcTest::isolate()->GetCurrentContext())
4948 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004949 message_received = true;
4950}
4951
4952
4953TEST(MessageHandler3) {
4954 message_received = false;
4955 v8::Isolate* isolate = CcTest::isolate();
4956 v8::HandleScope scope(isolate);
4957 CHECK(!message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004958 isolate->AddMessageListener(check_message_3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004959 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004960 v8::ScriptOrigin origin = v8::ScriptOrigin(
4961 v8_str("6.75"), v8::Integer::New(isolate, 1),
4962 v8::Integer::New(isolate, 2), v8::True(isolate), Local<v8::Integer>(),
4963 v8::True(isolate), v8_str("7.40"), v8::True(isolate));
4964 v8::Local<v8::Script> script =
4965 Script::Compile(context.local(), v8_str("throw 'error'"), &origin)
4966 .ToLocalChecked();
4967 CHECK(script->Run(context.local()).IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004968 CHECK(message_received);
4969 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004970 isolate->RemoveMessageListeners(check_message_3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004971}
4972
4973
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004974static void check_message_4(v8::Local<v8::Message> message,
4975 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004976 CHECK(!message->IsSharedCrossOrigin());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004977 CHECK_EQ(6.75, message->GetScriptOrigin()
4978 .ResourceName()
4979 ->NumberValue(CcTest::isolate()->GetCurrentContext())
4980 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004981 message_received = true;
4982}
4983
4984
4985TEST(MessageHandler4) {
4986 message_received = false;
4987 v8::Isolate* isolate = CcTest::isolate();
4988 v8::HandleScope scope(isolate);
4989 CHECK(!message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004990 isolate->AddMessageListener(check_message_4);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004991 LocalContext context;
4992 v8::ScriptOrigin origin =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004993 v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
4994 v8::Integer::New(isolate, 2), v8::False(isolate));
4995 v8::Local<v8::Script> script =
4996 Script::Compile(context.local(), v8_str("throw 'error'"), &origin)
4997 .ToLocalChecked();
4998 CHECK(script->Run(context.local()).IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004999 CHECK(message_received);
5000 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005001 isolate->RemoveMessageListeners(check_message_4);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005002}
5003
5004
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005005static void check_message_5a(v8::Local<v8::Message> message,
5006 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005007 CHECK(message->IsSharedCrossOrigin());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005008 CHECK_EQ(6.75, message->GetScriptOrigin()
5009 .ResourceName()
5010 ->NumberValue(CcTest::isolate()->GetCurrentContext())
5011 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005012 message_received = true;
5013}
5014
5015
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005016static void check_message_5b(v8::Local<v8::Message> message,
5017 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005018 CHECK(!message->IsSharedCrossOrigin());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005019 CHECK_EQ(6.75, message->GetScriptOrigin()
5020 .ResourceName()
5021 ->NumberValue(CcTest::isolate()->GetCurrentContext())
5022 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005023 message_received = true;
5024}
5025
5026
5027TEST(MessageHandler5) {
5028 message_received = false;
5029 v8::Isolate* isolate = CcTest::isolate();
5030 v8::HandleScope scope(isolate);
5031 CHECK(!message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005032 isolate->AddMessageListener(check_message_5a);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005033 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005034 v8::ScriptOrigin origin1 =
5035 v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
5036 v8::Integer::New(isolate, 2), v8::True(isolate));
5037 v8::Local<v8::Script> script =
5038 Script::Compile(context.local(), v8_str("throw 'error'"), &origin1)
5039 .ToLocalChecked();
5040 CHECK(script->Run(context.local()).IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005041 CHECK(message_received);
5042 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005043 isolate->RemoveMessageListeners(check_message_5a);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005044
5045 message_received = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005046 isolate->AddMessageListener(check_message_5b);
5047 v8::ScriptOrigin origin2 =
5048 v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
5049 v8::Integer::New(isolate, 2), v8::False(isolate));
5050 script = Script::Compile(context.local(), v8_str("throw 'error'"), &origin2)
5051 .ToLocalChecked();
5052 CHECK(script->Run(context.local()).IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005053 CHECK(message_received);
5054 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005055 isolate->RemoveMessageListeners(check_message_5b);
5056}
5057
5058
5059TEST(NativeWeakMap) {
5060 v8::Isolate* isolate = CcTest::isolate();
5061 HandleScope scope(isolate);
5062 Local<v8::NativeWeakMap> weak_map(v8::NativeWeakMap::New(isolate));
5063 CHECK(!weak_map.IsEmpty());
5064
5065 LocalContext env;
5066 Local<Object> value = v8::Object::New(isolate);
5067
5068 Local<Object> local1 = v8::Object::New(isolate);
5069 CHECK(!weak_map->Has(local1));
5070 CHECK(weak_map->Get(local1)->IsUndefined());
5071 weak_map->Set(local1, value);
5072 CHECK(weak_map->Has(local1));
5073 CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
5074
5075 WeakCallCounter counter(1234);
5076 WeakCallCounterAndPersistent<Value> o1(&counter);
5077 WeakCallCounterAndPersistent<Value> o2(&counter);
5078 WeakCallCounterAndPersistent<Value> s1(&counter);
5079 {
5080 HandleScope scope(isolate);
5081 Local<v8::Object> obj1 = v8::Object::New(isolate);
5082 Local<v8::Object> obj2 = v8::Object::New(isolate);
5083 Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
5084
5085 weak_map->Set(obj1, value);
5086 weak_map->Set(obj2, value);
5087 weak_map->Set(sym1, value);
5088
5089 o1.handle.Reset(isolate, obj1);
5090 o2.handle.Reset(isolate, obj2);
5091 s1.handle.Reset(isolate, sym1);
5092
5093 CHECK(weak_map->Has(local1));
5094 CHECK(weak_map->Has(obj1));
5095 CHECK(weak_map->Has(obj2));
5096 CHECK(weak_map->Has(sym1));
5097
5098 CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
5099 CHECK(value->Equals(env.local(), weak_map->Get(obj1)).FromJust());
5100 CHECK(value->Equals(env.local(), weak_map->Get(obj2)).FromJust());
5101 CHECK(value->Equals(env.local(), weak_map->Get(sym1)).FromJust());
5102 }
5103 CcTest::heap()->CollectAllGarbage();
5104 {
5105 HandleScope scope(isolate);
5106 CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
5107 CHECK(value->Equals(env.local(),
5108 weak_map->Get(Local<Value>::New(isolate, o1.handle)))
5109 .FromJust());
5110 CHECK(value->Equals(env.local(),
5111 weak_map->Get(Local<Value>::New(isolate, o2.handle)))
5112 .FromJust());
5113 CHECK(value->Equals(env.local(),
5114 weak_map->Get(Local<Value>::New(isolate, s1.handle)))
5115 .FromJust());
5116 }
5117
5118 o1.handle.SetWeak(&o1, &WeakPointerCallback,
5119 v8::WeakCallbackType::kParameter);
5120 o2.handle.SetWeak(&o2, &WeakPointerCallback,
5121 v8::WeakCallbackType::kParameter);
5122 s1.handle.SetWeak(&s1, &WeakPointerCallback,
5123 v8::WeakCallbackType::kParameter);
5124
5125 CcTest::heap()->CollectAllGarbage();
5126 CHECK_EQ(3, counter.NumberOfWeakCalls());
5127
5128 CHECK(o1.handle.IsEmpty());
5129 CHECK(o2.handle.IsEmpty());
5130 CHECK(s1.handle.IsEmpty());
5131
5132 CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
5133 CHECK(weak_map->Delete(local1));
5134 CHECK(!weak_map->Has(local1));
5135 CHECK(weak_map->Get(local1)->IsUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +00005136}
5137
5138
5139THREADED_TEST(GetSetProperty) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005140 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005141 v8::Isolate* isolate = context->GetIsolate();
5142 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005143 CHECK(context->Global()
5144 ->Set(context.local(), v8_str("foo"), v8_num(14))
5145 .FromJust());
5146 CHECK(context->Global()
5147 ->Set(context.local(), v8_str("12"), v8_num(92))
5148 .FromJust());
5149 CHECK(context->Global()
5150 ->Set(context.local(), v8::Integer::New(isolate, 16), v8_num(32))
5151 .FromJust());
5152 CHECK(context->Global()
5153 ->Set(context.local(), v8_num(13), v8_num(56))
5154 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005155 Local<Value> foo = CompileRun("this.foo");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005156 CHECK_EQ(14, foo->Int32Value(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005157 Local<Value> twelve = CompileRun("this[12]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005158 CHECK_EQ(92, twelve->Int32Value(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005159 Local<Value> sixteen = CompileRun("this[16]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005160 CHECK_EQ(32, sixteen->Int32Value(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005161 Local<Value> thirteen = CompileRun("this[13]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005162 CHECK_EQ(56, thirteen->Int32Value(context.local()).FromJust());
5163 CHECK_EQ(92, context->Global()
5164 ->Get(context.local(), v8::Integer::New(isolate, 12))
5165 .ToLocalChecked()
5166 ->Int32Value(context.local())
5167 .FromJust());
5168 CHECK_EQ(92, context->Global()
5169 ->Get(context.local(), v8_str("12"))
5170 .ToLocalChecked()
5171 ->Int32Value(context.local())
5172 .FromJust());
5173 CHECK_EQ(92, context->Global()
5174 ->Get(context.local(), v8_num(12))
5175 .ToLocalChecked()
5176 ->Int32Value(context.local())
5177 .FromJust());
5178 CHECK_EQ(32, context->Global()
5179 ->Get(context.local(), v8::Integer::New(isolate, 16))
5180 .ToLocalChecked()
5181 ->Int32Value(context.local())
5182 .FromJust());
5183 CHECK_EQ(32, context->Global()
5184 ->Get(context.local(), v8_str("16"))
5185 .ToLocalChecked()
5186 ->Int32Value(context.local())
5187 .FromJust());
5188 CHECK_EQ(32, context->Global()
5189 ->Get(context.local(), v8_num(16))
5190 .ToLocalChecked()
5191 ->Int32Value(context.local())
5192 .FromJust());
5193 CHECK_EQ(56, context->Global()
5194 ->Get(context.local(), v8::Integer::New(isolate, 13))
5195 .ToLocalChecked()
5196 ->Int32Value(context.local())
5197 .FromJust());
5198 CHECK_EQ(56, context->Global()
5199 ->Get(context.local(), v8_str("13"))
5200 .ToLocalChecked()
5201 ->Int32Value(context.local())
5202 .FromJust());
5203 CHECK_EQ(56, context->Global()
5204 ->Get(context.local(), v8_num(13))
5205 .ToLocalChecked()
5206 ->Int32Value(context.local())
5207 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005208}
5209
5210
5211THREADED_TEST(PropertyAttributes) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005212 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005213 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005214 // none
5215 Local<String> prop = v8_str("none");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005216 CHECK(context->Global()->Set(context.local(), prop, v8_num(7)).FromJust());
5217 CHECK_EQ(v8::None, context->Global()
5218 ->GetPropertyAttributes(context.local(), prop)
5219 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005220 // read-only
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005221 prop = v8_str("read_only");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005222 context->Global()
5223 ->DefineOwnProperty(context.local(), prop, v8_num(7), v8::ReadOnly)
5224 .FromJust();
5225 CHECK_EQ(7, context->Global()
5226 ->Get(context.local(), prop)
5227 .ToLocalChecked()
5228 ->Int32Value(context.local())
5229 .FromJust());
5230 CHECK_EQ(v8::ReadOnly, context->Global()
5231 ->GetPropertyAttributes(context.local(), prop)
5232 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005233 CompileRun("read_only = 9");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005234 CHECK_EQ(7, context->Global()
5235 ->Get(context.local(), prop)
5236 .ToLocalChecked()
5237 ->Int32Value(context.local())
5238 .FromJust());
5239 CHECK(context->Global()->Set(context.local(), prop, v8_num(10)).FromJust());
5240 CHECK_EQ(7, context->Global()
5241 ->Get(context.local(), prop)
5242 .ToLocalChecked()
5243 ->Int32Value(context.local())
5244 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005245 // dont-delete
5246 prop = v8_str("dont_delete");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005247 context->Global()
5248 ->DefineOwnProperty(context.local(), prop, v8_num(13), v8::DontDelete)
5249 .FromJust();
5250 CHECK_EQ(13, context->Global()
5251 ->Get(context.local(), prop)
5252 .ToLocalChecked()
5253 ->Int32Value(context.local())
5254 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005255 CompileRun("delete dont_delete");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005256 CHECK_EQ(13, context->Global()
5257 ->Get(context.local(), prop)
5258 .ToLocalChecked()
5259 ->Int32Value(context.local())
5260 .FromJust());
5261 CHECK_EQ(v8::DontDelete, context->Global()
5262 ->GetPropertyAttributes(context.local(), prop)
5263 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005264 // dont-enum
5265 prop = v8_str("dont_enum");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005266 context->Global()
5267 ->DefineOwnProperty(context.local(), prop, v8_num(28), v8::DontEnum)
5268 .FromJust();
5269 CHECK_EQ(v8::DontEnum, context->Global()
5270 ->GetPropertyAttributes(context.local(), prop)
5271 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005272 // absent
5273 prop = v8_str("absent");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005274 CHECK_EQ(v8::None, context->Global()
5275 ->GetPropertyAttributes(context.local(), prop)
5276 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005277 Local<Value> fake_prop = v8_num(1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005278 CHECK_EQ(v8::None, context->Global()
5279 ->GetPropertyAttributes(context.local(), fake_prop)
5280 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005281 // exception
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005282 TryCatch try_catch(context->GetIsolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005283 Local<Value> exception =
5284 CompileRun("({ toString: function() { throw 'exception';} })");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005285 CHECK(context->Global()
5286 ->GetPropertyAttributes(context.local(), exception)
5287 .IsNothing());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005288 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005289 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005290 CHECK_EQ(0, strcmp("exception", *exception_value));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005291 try_catch.Reset();
Steve Blocka7e24c12009-10-30 11:49:00 +00005292}
5293
5294
5295THREADED_TEST(Array) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005296 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005297 v8::HandleScope scope(context->GetIsolate());
5298 Local<v8::Array> array = v8::Array::New(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005299 CHECK_EQ(0u, array->Length());
5300 CHECK(array->Get(context.local(), 0).ToLocalChecked()->IsUndefined());
5301 CHECK(!array->Has(context.local(), 0).FromJust());
5302 CHECK(array->Get(context.local(), 100).ToLocalChecked()->IsUndefined());
5303 CHECK(!array->Has(context.local(), 100).FromJust());
5304 CHECK(array->Set(context.local(), 2, v8_num(7)).FromJust());
5305 CHECK_EQ(3u, array->Length());
5306 CHECK(!array->Has(context.local(), 0).FromJust());
5307 CHECK(!array->Has(context.local(), 1).FromJust());
5308 CHECK(array->Has(context.local(), 2).FromJust());
5309 CHECK_EQ(7, array->Get(context.local(), 2)
5310 .ToLocalChecked()
5311 ->Int32Value(context.local())
5312 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005313 Local<Value> obj = CompileRun("[1, 2, 3]");
Steve Block6ded16b2010-05-10 14:33:55 +01005314 Local<v8::Array> arr = obj.As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005315 CHECK_EQ(3u, arr->Length());
5316 CHECK_EQ(1, arr->Get(context.local(), 0)
5317 .ToLocalChecked()
5318 ->Int32Value(context.local())
5319 .FromJust());
5320 CHECK_EQ(2, arr->Get(context.local(), 1)
5321 .ToLocalChecked()
5322 ->Int32Value(context.local())
5323 .FromJust());
5324 CHECK_EQ(3, arr->Get(context.local(), 2)
5325 .ToLocalChecked()
5326 ->Int32Value(context.local())
5327 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005328 array = v8::Array::New(context->GetIsolate(), 27);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005329 CHECK_EQ(27u, array->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005330 array = v8::Array::New(context->GetIsolate(), -27);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005331 CHECK_EQ(0u, array->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +00005332}
5333
5334
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005335void HandleF(const v8::FunctionCallbackInfo<v8::Value>& args) {
5336 v8::EscapableHandleScope scope(args.GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00005337 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005338 Local<v8::Array> result = v8::Array::New(args.GetIsolate(), args.Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005339 for (int i = 0; i < args.Length(); i++) {
5340 CHECK(result->Set(CcTest::isolate()->GetCurrentContext(), i, args[i])
5341 .FromJust());
5342 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005343 args.GetReturnValue().Set(scope.Escape(result));
Steve Blocka7e24c12009-10-30 11:49:00 +00005344}
5345
5346
5347THREADED_TEST(Vector) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005348 v8::Isolate* isolate = CcTest::isolate();
5349 v8::HandleScope scope(isolate);
5350 Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
5351 global->Set(v8_str("f"), v8::FunctionTemplate::New(isolate, HandleF));
Steve Blocka7e24c12009-10-30 11:49:00 +00005352 LocalContext context(0, global);
5353
5354 const char* fun = "f()";
Steve Block6ded16b2010-05-10 14:33:55 +01005355 Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005356 CHECK_EQ(0u, a0->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +00005357
5358 const char* fun2 = "f(11)";
Steve Block6ded16b2010-05-10 14:33:55 +01005359 Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005360 CHECK_EQ(1u, a1->Length());
5361 CHECK_EQ(11, a1->Get(context.local(), 0)
5362 .ToLocalChecked()
5363 ->Int32Value(context.local())
5364 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005365
5366 const char* fun3 = "f(12, 13)";
Steve Block6ded16b2010-05-10 14:33:55 +01005367 Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005368 CHECK_EQ(2u, a2->Length());
5369 CHECK_EQ(12, a2->Get(context.local(), 0)
5370 .ToLocalChecked()
5371 ->Int32Value(context.local())
5372 .FromJust());
5373 CHECK_EQ(13, a2->Get(context.local(), 1)
5374 .ToLocalChecked()
5375 ->Int32Value(context.local())
5376 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005377
5378 const char* fun4 = "f(14, 15, 16)";
Steve Block6ded16b2010-05-10 14:33:55 +01005379 Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005380 CHECK_EQ(3u, a3->Length());
5381 CHECK_EQ(14, a3->Get(context.local(), 0)
5382 .ToLocalChecked()
5383 ->Int32Value(context.local())
5384 .FromJust());
5385 CHECK_EQ(15, a3->Get(context.local(), 1)
5386 .ToLocalChecked()
5387 ->Int32Value(context.local())
5388 .FromJust());
5389 CHECK_EQ(16, a3->Get(context.local(), 2)
5390 .ToLocalChecked()
5391 ->Int32Value(context.local())
5392 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005393
5394 const char* fun5 = "f(17, 18, 19, 20)";
Steve Block6ded16b2010-05-10 14:33:55 +01005395 Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005396 CHECK_EQ(4u, a4->Length());
5397 CHECK_EQ(17, a4->Get(context.local(), 0)
5398 .ToLocalChecked()
5399 ->Int32Value(context.local())
5400 .FromJust());
5401 CHECK_EQ(18, a4->Get(context.local(), 1)
5402 .ToLocalChecked()
5403 ->Int32Value(context.local())
5404 .FromJust());
5405 CHECK_EQ(19, a4->Get(context.local(), 2)
5406 .ToLocalChecked()
5407 ->Int32Value(context.local())
5408 .FromJust());
5409 CHECK_EQ(20, a4->Get(context.local(), 3)
5410 .ToLocalChecked()
5411 ->Int32Value(context.local())
5412 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005413}
5414
5415
5416THREADED_TEST(FunctionCall) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005417 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005418 v8::Isolate* isolate = context->GetIsolate();
5419 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005420 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005421 "function Foo() {"
5422 " var result = [];"
5423 " for (var i = 0; i < arguments.length; i++) {"
5424 " result.push(arguments[i]);"
5425 " }"
5426 " return result;"
5427 "}"
5428 "function ReturnThisSloppy() {"
5429 " return this;"
5430 "}"
5431 "function ReturnThisStrict() {"
5432 " 'use strict';"
5433 " return this;"
5434 "}");
5435 Local<Function> Foo = Local<Function>::Cast(
5436 context->Global()->Get(context.local(), v8_str("Foo")).ToLocalChecked());
5437 Local<Function> ReturnThisSloppy = Local<Function>::Cast(
5438 context->Global()
5439 ->Get(context.local(), v8_str("ReturnThisSloppy"))
5440 .ToLocalChecked());
5441 Local<Function> ReturnThisStrict = Local<Function>::Cast(
5442 context->Global()
5443 ->Get(context.local(), v8_str("ReturnThisStrict"))
5444 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00005445
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005446 v8::Local<Value>* args0 = NULL;
5447 Local<v8::Array> a0 = Local<v8::Array>::Cast(
5448 Foo->Call(context.local(), Foo, 0, args0).ToLocalChecked());
5449 CHECK_EQ(0u, a0->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +00005450
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005451 v8::Local<Value> args1[] = {v8_num(1.1)};
5452 Local<v8::Array> a1 = Local<v8::Array>::Cast(
5453 Foo->Call(context.local(), Foo, 1, args1).ToLocalChecked());
5454 CHECK_EQ(1u, a1->Length());
5455 CHECK_EQ(1.1, a1->Get(context.local(), v8::Integer::New(isolate, 0))
5456 .ToLocalChecked()
5457 ->NumberValue(context.local())
5458 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005459
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005460 v8::Local<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
5461 Local<v8::Array> a2 = Local<v8::Array>::Cast(
5462 Foo->Call(context.local(), Foo, 2, args2).ToLocalChecked());
5463 CHECK_EQ(2u, a2->Length());
5464 CHECK_EQ(2.2, a2->Get(context.local(), v8::Integer::New(isolate, 0))
5465 .ToLocalChecked()
5466 ->NumberValue(context.local())
5467 .FromJust());
5468 CHECK_EQ(3.3, a2->Get(context.local(), v8::Integer::New(isolate, 1))
5469 .ToLocalChecked()
5470 ->NumberValue(context.local())
5471 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005472
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005473 v8::Local<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
5474 Local<v8::Array> a3 = Local<v8::Array>::Cast(
5475 Foo->Call(context.local(), Foo, 3, args3).ToLocalChecked());
5476 CHECK_EQ(3u, a3->Length());
5477 CHECK_EQ(4.4, a3->Get(context.local(), v8::Integer::New(isolate, 0))
5478 .ToLocalChecked()
5479 ->NumberValue(context.local())
5480 .FromJust());
5481 CHECK_EQ(5.5, a3->Get(context.local(), v8::Integer::New(isolate, 1))
5482 .ToLocalChecked()
5483 ->NumberValue(context.local())
5484 .FromJust());
5485 CHECK_EQ(6.6, a3->Get(context.local(), v8::Integer::New(isolate, 2))
5486 .ToLocalChecked()
5487 ->NumberValue(context.local())
5488 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005489
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005490 v8::Local<Value> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
5491 v8_num(10.11)};
5492 Local<v8::Array> a4 = Local<v8::Array>::Cast(
5493 Foo->Call(context.local(), Foo, 4, args4).ToLocalChecked());
5494 CHECK_EQ(4u, a4->Length());
5495 CHECK_EQ(7.7, a4->Get(context.local(), v8::Integer::New(isolate, 0))
5496 .ToLocalChecked()
5497 ->NumberValue(context.local())
5498 .FromJust());
5499 CHECK_EQ(8.8, a4->Get(context.local(), v8::Integer::New(isolate, 1))
5500 .ToLocalChecked()
5501 ->NumberValue(context.local())
5502 .FromJust());
5503 CHECK_EQ(9.9, a4->Get(context.local(), v8::Integer::New(isolate, 2))
5504 .ToLocalChecked()
5505 ->NumberValue(context.local())
5506 .FromJust());
5507 CHECK_EQ(10.11, a4->Get(context.local(), v8::Integer::New(isolate, 3))
5508 .ToLocalChecked()
5509 ->NumberValue(context.local())
5510 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005511
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005512 Local<v8::Value> r1 =
5513 ReturnThisSloppy->Call(context.local(), v8::Undefined(isolate), 0, NULL)
5514 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005515 CHECK(r1->StrictEquals(context->Global()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005516 Local<v8::Value> r2 =
5517 ReturnThisSloppy->Call(context.local(), v8::Null(isolate), 0, NULL)
5518 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005519 CHECK(r2->StrictEquals(context->Global()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005520 Local<v8::Value> r3 =
5521 ReturnThisSloppy->Call(context.local(), v8_num(42), 0, NULL)
5522 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005523 CHECK(r3->IsNumberObject());
5524 CHECK_EQ(42.0, r3.As<v8::NumberObject>()->ValueOf());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005525 Local<v8::Value> r4 =
5526 ReturnThisSloppy->Call(context.local(), v8_str("hello"), 0, NULL)
5527 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005528 CHECK(r4->IsStringObject());
5529 CHECK(r4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005530 Local<v8::Value> r5 =
5531 ReturnThisSloppy->Call(context.local(), v8::True(isolate), 0, NULL)
5532 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005533 CHECK(r5->IsBooleanObject());
5534 CHECK(r5.As<v8::BooleanObject>()->ValueOf());
Steve Blocka7e24c12009-10-30 11:49:00 +00005535
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005536 Local<v8::Value> r6 =
5537 ReturnThisStrict->Call(context.local(), v8::Undefined(isolate), 0, NULL)
5538 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005539 CHECK(r6->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005540 Local<v8::Value> r7 =
5541 ReturnThisStrict->Call(context.local(), v8::Null(isolate), 0, NULL)
5542 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005543 CHECK(r7->IsNull());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005544 Local<v8::Value> r8 =
5545 ReturnThisStrict->Call(context.local(), v8_num(42), 0, NULL)
5546 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005547 CHECK(r8->StrictEquals(v8_num(42)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005548 Local<v8::Value> r9 =
5549 ReturnThisStrict->Call(context.local(), v8_str("hello"), 0, NULL)
5550 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005551 CHECK(r9->StrictEquals(v8_str("hello")));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005552 Local<v8::Value> r10 =
5553 ReturnThisStrict->Call(context.local(), v8::True(isolate), 0, NULL)
5554 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005555 CHECK(r10->StrictEquals(v8::True(isolate)));
Steve Blocka7e24c12009-10-30 11:49:00 +00005556}
5557
5558
5559THREADED_TEST(ConstructCall) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005560 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005561 v8::Isolate* isolate = context->GetIsolate();
5562 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005563 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005564 "function Foo() {"
5565 " var result = [];"
5566 " for (var i = 0; i < arguments.length; i++) {"
5567 " result.push(arguments[i]);"
5568 " }"
5569 " return result;"
5570 "}");
5571 Local<Function> Foo = Local<Function>::Cast(
5572 context->Global()->Get(context.local(), v8_str("Foo")).ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00005573
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005574 v8::Local<Value>* args0 = NULL;
5575 Local<v8::Array> a0 = Local<v8::Array>::Cast(
5576 Foo->NewInstance(context.local(), 0, args0).ToLocalChecked());
5577 CHECK_EQ(0u, a0->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +00005578
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005579 v8::Local<Value> args1[] = {v8_num(1.1)};
5580 Local<v8::Array> a1 = Local<v8::Array>::Cast(
5581 Foo->NewInstance(context.local(), 1, args1).ToLocalChecked());
5582 CHECK_EQ(1u, a1->Length());
5583 CHECK_EQ(1.1, a1->Get(context.local(), v8::Integer::New(isolate, 0))
5584 .ToLocalChecked()
5585 ->NumberValue(context.local())
5586 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005587
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005588 v8::Local<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
5589 Local<v8::Array> a2 = Local<v8::Array>::Cast(
5590 Foo->NewInstance(context.local(), 2, args2).ToLocalChecked());
5591 CHECK_EQ(2u, a2->Length());
5592 CHECK_EQ(2.2, a2->Get(context.local(), v8::Integer::New(isolate, 0))
5593 .ToLocalChecked()
5594 ->NumberValue(context.local())
5595 .FromJust());
5596 CHECK_EQ(3.3, a2->Get(context.local(), v8::Integer::New(isolate, 1))
5597 .ToLocalChecked()
5598 ->NumberValue(context.local())
5599 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005600
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005601 v8::Local<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
5602 Local<v8::Array> a3 = Local<v8::Array>::Cast(
5603 Foo->NewInstance(context.local(), 3, args3).ToLocalChecked());
5604 CHECK_EQ(3u, a3->Length());
5605 CHECK_EQ(4.4, a3->Get(context.local(), v8::Integer::New(isolate, 0))
5606 .ToLocalChecked()
5607 ->NumberValue(context.local())
5608 .FromJust());
5609 CHECK_EQ(5.5, a3->Get(context.local(), v8::Integer::New(isolate, 1))
5610 .ToLocalChecked()
5611 ->NumberValue(context.local())
5612 .FromJust());
5613 CHECK_EQ(6.6, a3->Get(context.local(), v8::Integer::New(isolate, 2))
5614 .ToLocalChecked()
5615 ->NumberValue(context.local())
5616 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005617
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005618 v8::Local<Value> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
5619 v8_num(10.11)};
5620 Local<v8::Array> a4 = Local<v8::Array>::Cast(
5621 Foo->NewInstance(context.local(), 4, args4).ToLocalChecked());
5622 CHECK_EQ(4u, a4->Length());
5623 CHECK_EQ(7.7, a4->Get(context.local(), v8::Integer::New(isolate, 0))
5624 .ToLocalChecked()
5625 ->NumberValue(context.local())
5626 .FromJust());
5627 CHECK_EQ(8.8, a4->Get(context.local(), v8::Integer::New(isolate, 1))
5628 .ToLocalChecked()
5629 ->NumberValue(context.local())
5630 .FromJust());
5631 CHECK_EQ(9.9, a4->Get(context.local(), v8::Integer::New(isolate, 2))
5632 .ToLocalChecked()
5633 ->NumberValue(context.local())
5634 .FromJust());
5635 CHECK_EQ(10.11, a4->Get(context.local(), v8::Integer::New(isolate, 3))
5636 .ToLocalChecked()
5637 ->NumberValue(context.local())
5638 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005639}
5640
5641
Steve Block6ded16b2010-05-10 14:33:55 +01005642THREADED_TEST(ConversionNumber) {
Steve Block6ded16b2010-05-10 14:33:55 +01005643 LocalContext env;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005644 v8::Isolate* isolate = env->GetIsolate();
5645 v8::HandleScope scope(isolate);
Steve Block6ded16b2010-05-10 14:33:55 +01005646 // Very large number.
5647 CompileRun("var obj = Math.pow(2,32) * 1237;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005648 Local<Value> obj =
5649 env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5650 CHECK_EQ(5312874545152.0,
5651 obj->ToNumber(env.local()).ToLocalChecked()->Value());
5652 CHECK_EQ(0, obj->ToInt32(env.local()).ToLocalChecked()->Value());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005653 CHECK(0u ==
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005654 obj->ToUint32(env.local())
5655 .ToLocalChecked()
5656 ->Value()); // NOLINT - no CHECK_EQ for unsigned.
Steve Block6ded16b2010-05-10 14:33:55 +01005657 // Large number.
5658 CompileRun("var obj = -1234567890123;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005659 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5660 CHECK_EQ(-1234567890123.0,
5661 obj->ToNumber(env.local()).ToLocalChecked()->Value());
5662 CHECK_EQ(-1912276171, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5663 CHECK(2382691125u ==
5664 obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005665 // Small positive integer.
5666 CompileRun("var obj = 42;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005667 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5668 CHECK_EQ(42.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
5669 CHECK_EQ(42, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5670 CHECK(42u == obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005671 // Negative integer.
5672 CompileRun("var obj = -37;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005673 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5674 CHECK_EQ(-37.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
5675 CHECK_EQ(-37, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5676 CHECK(4294967259u ==
5677 obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005678 // Positive non-int32 integer.
5679 CompileRun("var obj = 0x81234567;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005680 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5681 CHECK_EQ(2166572391.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
5682 CHECK_EQ(-2128394905, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5683 CHECK(2166572391u ==
5684 obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005685 // Fraction.
5686 CompileRun("var obj = 42.3;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005687 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5688 CHECK_EQ(42.3, obj->ToNumber(env.local()).ToLocalChecked()->Value());
5689 CHECK_EQ(42, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5690 CHECK(42u == obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005691 // Large negative fraction.
5692 CompileRun("var obj = -5726623061.75;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005693 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5694 CHECK_EQ(-5726623061.75,
5695 obj->ToNumber(env.local()).ToLocalChecked()->Value());
5696 CHECK_EQ(-1431655765, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5697 CHECK(2863311531u ==
5698 obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005699}
5700
5701
5702THREADED_TEST(isNumberType) {
Steve Block6ded16b2010-05-10 14:33:55 +01005703 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005704 v8::HandleScope scope(env->GetIsolate());
Steve Block6ded16b2010-05-10 14:33:55 +01005705 // Very large number.
5706 CompileRun("var obj = Math.pow(2,32) * 1237;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005707 Local<Value> obj =
5708 env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005709 CHECK(!obj->IsInt32());
5710 CHECK(!obj->IsUint32());
5711 // Large negative number.
5712 CompileRun("var obj = -1234567890123;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005713 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005714 CHECK(!obj->IsInt32());
5715 CHECK(!obj->IsUint32());
5716 // Small positive integer.
5717 CompileRun("var obj = 42;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005718 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005719 CHECK(obj->IsInt32());
5720 CHECK(obj->IsUint32());
5721 // Negative integer.
5722 CompileRun("var obj = -37;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005723 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005724 CHECK(obj->IsInt32());
5725 CHECK(!obj->IsUint32());
5726 // Positive non-int32 integer.
5727 CompileRun("var obj = 0x81234567;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005728 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005729 CHECK(!obj->IsInt32());
5730 CHECK(obj->IsUint32());
5731 // Fraction.
5732 CompileRun("var obj = 42.3;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005733 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005734 CHECK(!obj->IsInt32());
5735 CHECK(!obj->IsUint32());
5736 // Large negative fraction.
5737 CompileRun("var obj = -5726623061.75;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005738 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005739 CHECK(!obj->IsInt32());
5740 CHECK(!obj->IsUint32());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005741 // Positive zero
5742 CompileRun("var obj = 0.0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005743 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005744 CHECK(obj->IsInt32());
5745 CHECK(obj->IsUint32());
5746 // Positive zero
5747 CompileRun("var obj = -0.0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005748 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005749 CHECK(!obj->IsInt32());
5750 CHECK(!obj->IsUint32());
Steve Block6ded16b2010-05-10 14:33:55 +01005751}
5752
5753
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005754static void CheckUncle(v8::TryCatch* try_catch) {
5755 CHECK(try_catch->HasCaught());
5756 String::Utf8Value str_value(try_catch->Exception());
5757 CHECK_EQ(0, strcmp(*str_value, "uncle?"));
5758 try_catch->Reset();
5759}
5760
5761
Steve Blocka7e24c12009-10-30 11:49:00 +00005762THREADED_TEST(ConversionException) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005763 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005764 v8::Isolate* isolate = env->GetIsolate();
5765 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005766 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005767 "function TestClass() { };"
5768 "TestClass.prototype.toString = function () { throw 'uncle?'; };"
5769 "var obj = new TestClass();");
5770 Local<Value> obj =
5771 env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00005772
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005773 v8::TryCatch try_catch(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005774
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005775 CHECK(obj->ToString(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005776 CheckUncle(&try_catch);
5777
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005778 CHECK(obj->ToNumber(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005779 CheckUncle(&try_catch);
5780
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005781 CHECK(obj->ToInteger(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005782 CheckUncle(&try_catch);
5783
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005784 CHECK(obj->ToUint32(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005785 CheckUncle(&try_catch);
5786
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005787 CHECK(obj->ToInt32(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005788 CheckUncle(&try_catch);
5789
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005790 CHECK(v8::Undefined(isolate)->ToObject(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005791 CHECK(try_catch.HasCaught());
5792 try_catch.Reset();
5793
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005794 CHECK(obj->Int32Value(env.local()).IsNothing());
Steve Blocka7e24c12009-10-30 11:49:00 +00005795 CheckUncle(&try_catch);
5796
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005797 CHECK(obj->Uint32Value(env.local()).IsNothing());
Steve Blocka7e24c12009-10-30 11:49:00 +00005798 CheckUncle(&try_catch);
5799
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005800 CHECK(obj->NumberValue(env.local()).IsNothing());
Steve Blocka7e24c12009-10-30 11:49:00 +00005801 CheckUncle(&try_catch);
5802
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005803 CHECK(obj->IntegerValue(env.local()).IsNothing());
Steve Blocka7e24c12009-10-30 11:49:00 +00005804 CheckUncle(&try_catch);
5805}
5806
5807
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005808void ThrowFromC(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005809 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005810 args.GetIsolate()->ThrowException(v8_str("konto"));
Steve Blocka7e24c12009-10-30 11:49:00 +00005811}
5812
5813
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005814void CCatcher(const v8::FunctionCallbackInfo<v8::Value>& args) {
5815 if (args.Length() < 1) {
5816 args.GetReturnValue().Set(false);
5817 return;
5818 }
5819 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005820 v8::TryCatch try_catch(args.GetIsolate());
5821 Local<Value> result =
5822 CompileRun(args[0]
5823 ->ToString(args.GetIsolate()->GetCurrentContext())
5824 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00005825 CHECK(!try_catch.HasCaught() || result.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005826 args.GetReturnValue().Set(try_catch.HasCaught());
Steve Blocka7e24c12009-10-30 11:49:00 +00005827}
5828
5829
5830THREADED_TEST(APICatch) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005831 v8::Isolate* isolate = CcTest::isolate();
5832 v8::HandleScope scope(isolate);
5833 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005834 templ->Set(v8_str("ThrowFromC"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005835 v8::FunctionTemplate::New(isolate, ThrowFromC));
Steve Blocka7e24c12009-10-30 11:49:00 +00005836 LocalContext context(0, templ);
5837 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005838 "var thrown = false;"
5839 "try {"
5840 " ThrowFromC();"
5841 "} catch (e) {"
5842 " thrown = true;"
5843 "}");
5844 Local<Value> thrown = context->Global()
5845 ->Get(context.local(), v8_str("thrown"))
5846 .ToLocalChecked();
5847 CHECK(thrown->BooleanValue(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005848}
5849
5850
5851THREADED_TEST(APIThrowTryCatch) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005852 v8::Isolate* isolate = CcTest::isolate();
5853 v8::HandleScope scope(isolate);
5854 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005855 templ->Set(v8_str("ThrowFromC"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005856 v8::FunctionTemplate::New(isolate, ThrowFromC));
Steve Blocka7e24c12009-10-30 11:49:00 +00005857 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005858 v8::TryCatch try_catch(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005859 CompileRun("ThrowFromC();");
5860 CHECK(try_catch.HasCaught());
5861}
5862
5863
5864// Test that a try-finally block doesn't shadow a try-catch block
5865// when setting up an external handler.
5866//
5867// BUG(271): Some of the exception propagation does not work on the
5868// ARM simulator because the simulator separates the C++ stack and the
5869// JS stack. This test therefore fails on the simulator. The test is
5870// not threaded to allow the threading tests to run on the simulator.
5871TEST(TryCatchInTryFinally) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005872 v8::Isolate* isolate = CcTest::isolate();
5873 v8::HandleScope scope(isolate);
5874 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005875 templ->Set(v8_str("CCatcher"), v8::FunctionTemplate::New(isolate, CCatcher));
Steve Blocka7e24c12009-10-30 11:49:00 +00005876 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005877 Local<Value> result = CompileRun(
5878 "try {"
5879 " try {"
5880 " CCatcher('throw 7;');"
5881 " } finally {"
5882 " }"
5883 "} catch (e) {"
5884 "}");
Steve Blocka7e24c12009-10-30 11:49:00 +00005885 CHECK(result->IsTrue());
5886}
5887
5888
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005889static void check_custom_error_tostring(v8::Local<v8::Message> message,
5890 v8::Local<v8::Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005891 const char* uncaught_error = "Uncaught MyError toString";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005892 CHECK(message->Get()
5893 ->Equals(CcTest::isolate()->GetCurrentContext(),
5894 v8_str(uncaught_error))
5895 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005896}
5897
5898
5899TEST(CustomErrorToString) {
5900 LocalContext context;
5901 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005902 context->GetIsolate()->AddMessageListener(check_custom_error_tostring);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005903 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005904 "function MyError(name, message) { "
5905 " this.name = name; "
5906 " this.message = message; "
5907 "} "
5908 "MyError.prototype = Object.create(Error.prototype); "
5909 "MyError.prototype.toString = function() { "
5910 " return 'MyError toString'; "
5911 "}; "
5912 "throw new MyError('my name', 'my message'); ");
5913 context->GetIsolate()->RemoveMessageListeners(check_custom_error_tostring);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005914}
5915
5916
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005917static void check_custom_error_message(v8::Local<v8::Message> message,
5918 v8::Local<v8::Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005919 const char* uncaught_error = "Uncaught MyError: my message";
5920 printf("%s\n", *v8::String::Utf8Value(message->Get()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005921 CHECK(message->Get()
5922 ->Equals(CcTest::isolate()->GetCurrentContext(),
5923 v8_str(uncaught_error))
5924 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005925}
5926
5927
5928TEST(CustomErrorMessage) {
5929 LocalContext context;
5930 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005931 context->GetIsolate()->AddMessageListener(check_custom_error_message);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005932
5933 // Handlebars.
5934 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005935 "function MyError(msg) { "
5936 " this.name = 'MyError'; "
5937 " this.message = msg; "
5938 "} "
5939 "MyError.prototype = new Error(); "
5940 "throw new MyError('my message'); ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005941
5942 // Closure.
5943 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005944 "function MyError(msg) { "
5945 " this.name = 'MyError'; "
5946 " this.message = msg; "
5947 "} "
5948 "inherits = function(childCtor, parentCtor) { "
5949 " function tempCtor() {}; "
5950 " tempCtor.prototype = parentCtor.prototype; "
5951 " childCtor.superClass_ = parentCtor.prototype; "
5952 " childCtor.prototype = new tempCtor(); "
5953 " childCtor.prototype.constructor = childCtor; "
5954 "}; "
5955 "inherits(MyError, Error); "
5956 "throw new MyError('my message'); ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005957
5958 // Object.create.
5959 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005960 "function MyError(msg) { "
5961 " this.name = 'MyError'; "
5962 " this.message = msg; "
5963 "} "
5964 "MyError.prototype = Object.create(Error.prototype); "
5965 "throw new MyError('my message'); ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005966
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005967 context->GetIsolate()->RemoveMessageListeners(check_custom_error_message);
Ben Murdochb8e0da22011-05-16 14:20:40 +01005968}
5969
5970
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005971static void check_custom_rethrowing_message(v8::Local<v8::Message> message,
5972 v8::Local<v8::Value> data) {
5973 const char* uncaught_error = "Uncaught exception";
5974 CHECK(message->Get()
5975 ->Equals(CcTest::isolate()->GetCurrentContext(),
5976 v8_str(uncaught_error))
5977 .FromJust());
5978}
5979
5980
5981TEST(CustomErrorRethrowsOnToString) {
5982 LocalContext context;
5983 v8::HandleScope scope(context->GetIsolate());
5984 context->GetIsolate()->AddMessageListener(check_custom_rethrowing_message);
5985
5986 CompileRun(
5987 "var e = { toString: function() { throw e; } };"
5988 "try { throw e; } finally {}");
5989
5990 context->GetIsolate()->RemoveMessageListeners(
5991 check_custom_rethrowing_message);
5992}
5993
5994
5995static void receive_message(v8::Local<v8::Message> message,
5996 v8::Local<v8::Value> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005997 message->Get();
5998 message_received = true;
5999}
6000
6001
6002TEST(APIThrowMessage) {
6003 message_received = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006004 v8::Isolate* isolate = CcTest::isolate();
6005 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006006 isolate->AddMessageListener(receive_message);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006007 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00006008 templ->Set(v8_str("ThrowFromC"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006009 v8::FunctionTemplate::New(isolate, ThrowFromC));
Steve Blocka7e24c12009-10-30 11:49:00 +00006010 LocalContext context(0, templ);
6011 CompileRun("ThrowFromC();");
6012 CHECK(message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006013 isolate->RemoveMessageListeners(receive_message);
Steve Blocka7e24c12009-10-30 11:49:00 +00006014}
6015
6016
6017TEST(APIThrowMessageAndVerboseTryCatch) {
6018 message_received = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006019 v8::Isolate* isolate = CcTest::isolate();
6020 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006021 isolate->AddMessageListener(receive_message);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006022 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00006023 templ->Set(v8_str("ThrowFromC"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006024 v8::FunctionTemplate::New(isolate, ThrowFromC));
Steve Blocka7e24c12009-10-30 11:49:00 +00006025 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006026 v8::TryCatch try_catch(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00006027 try_catch.SetVerbose(true);
6028 Local<Value> result = CompileRun("ThrowFromC();");
6029 CHECK(try_catch.HasCaught());
6030 CHECK(result.IsEmpty());
6031 CHECK(message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006032 isolate->RemoveMessageListeners(receive_message);
Steve Blocka7e24c12009-10-30 11:49:00 +00006033}
6034
6035
Ben Murdoch8b112d22011-06-08 16:22:53 +01006036TEST(APIStackOverflowAndVerboseTryCatch) {
6037 message_received = false;
Ben Murdoch8b112d22011-06-08 16:22:53 +01006038 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006039 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006040 context->GetIsolate()->AddMessageListener(receive_message);
6041 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +01006042 try_catch.SetVerbose(true);
6043 Local<Value> result = CompileRun("function foo() { foo(); } foo();");
6044 CHECK(try_catch.HasCaught());
6045 CHECK(result.IsEmpty());
6046 CHECK(message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006047 context->GetIsolate()->RemoveMessageListeners(receive_message);
Ben Murdoch8b112d22011-06-08 16:22:53 +01006048}
6049
6050
Steve Blocka7e24c12009-10-30 11:49:00 +00006051THREADED_TEST(ExternalScriptException) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006052 v8::Isolate* isolate = CcTest::isolate();
6053 v8::HandleScope scope(isolate);
6054 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00006055 templ->Set(v8_str("ThrowFromC"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006056 v8::FunctionTemplate::New(isolate, ThrowFromC));
Steve Blocka7e24c12009-10-30 11:49:00 +00006057 LocalContext context(0, templ);
6058
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006059 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006060 Local<Value> result = CompileRun("ThrowFromC(); throw 'panama';");
Steve Blocka7e24c12009-10-30 11:49:00 +00006061 CHECK(result.IsEmpty());
6062 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006063 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006064 CHECK_EQ(0, strcmp("konto", *exception_value));
Steve Blocka7e24c12009-10-30 11:49:00 +00006065}
6066
6067
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006068void CThrowCountDown(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006069 ApiTestFuzzer::Fuzz();
6070 CHECK_EQ(4, args.Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006071 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
6072 int count = args[0]->Int32Value(context).FromJust();
6073 int cInterval = args[2]->Int32Value(context).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00006074 if (count == 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006075 args.GetIsolate()->ThrowException(v8_str("FromC"));
6076 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00006077 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006078 Local<v8::Object> global = context->Global();
6079 Local<Value> fun =
6080 global->Get(context, v8_str("JSThrowCountDown")).ToLocalChecked();
6081 v8::Local<Value> argv[] = {v8_num(count - 1), args[1], args[2], args[3]};
Steve Blocka7e24c12009-10-30 11:49:00 +00006082 if (count % cInterval == 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006083 v8::TryCatch try_catch(args.GetIsolate());
6084 Local<Value> result = fun.As<Function>()
6085 ->Call(context, global, 4, argv)
6086 .FromMaybe(Local<Value>());
6087 int expected = args[3]->Int32Value(context).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00006088 if (try_catch.HasCaught()) {
6089 CHECK_EQ(expected, count);
6090 CHECK(result.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006091 CHECK(!CcTest::i_isolate()->has_scheduled_exception());
Steve Blocka7e24c12009-10-30 11:49:00 +00006092 } else {
6093 CHECK_NE(expected, count);
6094 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006095 args.GetReturnValue().Set(result);
6096 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00006097 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006098 args.GetReturnValue().Set(fun.As<Function>()
6099 ->Call(context, global, 4, argv)
6100 .FromMaybe(v8::Local<v8::Value>()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006101 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00006102 }
6103 }
6104}
6105
6106
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006107void JSCheck(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006108 ApiTestFuzzer::Fuzz();
6109 CHECK_EQ(3, args.Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006110 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
6111 bool equality = args[0]->BooleanValue(context).FromJust();
6112 int count = args[1]->Int32Value(context).FromJust();
6113 int expected = args[2]->Int32Value(context).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00006114 if (equality) {
6115 CHECK_EQ(count, expected);
6116 } else {
6117 CHECK_NE(count, expected);
6118 }
Steve Blocka7e24c12009-10-30 11:49:00 +00006119}
6120
6121
6122THREADED_TEST(EvalInTryFinally) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006123 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006124 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006125 v8::TryCatch try_catch(context->GetIsolate());
6126 CompileRun(
6127 "(function() {"
6128 " try {"
6129 " eval('asldkf (*&^&*^');"
6130 " } finally {"
6131 " return;"
6132 " }"
6133 "})()");
Steve Blocka7e24c12009-10-30 11:49:00 +00006134 CHECK(!try_catch.HasCaught());
6135}
6136
6137
6138// This test works by making a stack of alternating JavaScript and C
6139// activations. These activations set up exception handlers with regular
6140// intervals, one interval for C activations and another for JavaScript
6141// activations. When enough activations have been created an exception is
6142// thrown and we check that the right activation catches the exception and that
6143// no other activations do. The right activation is always the topmost one with
6144// a handler, regardless of whether it is in JavaScript or C.
6145//
6146// The notation used to describe a test case looks like this:
6147//
6148// *JS[4] *C[3] @JS[2] C[1] JS[0]
6149//
6150// Each entry is an activation, either JS or C. The index is the count at that
6151// level. Stars identify activations with exception handlers, the @ identifies
6152// the exception handler that should catch the exception.
6153//
6154// BUG(271): Some of the exception propagation does not work on the
6155// ARM simulator because the simulator separates the C++ stack and the
6156// JS stack. This test therefore fails on the simulator. The test is
6157// not threaded to allow the threading tests to run on the simulator.
6158TEST(ExceptionOrder) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006159 v8::Isolate* isolate = CcTest::isolate();
6160 v8::HandleScope scope(isolate);
6161 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6162 templ->Set(v8_str("check"), v8::FunctionTemplate::New(isolate, JSCheck));
Steve Blocka7e24c12009-10-30 11:49:00 +00006163 templ->Set(v8_str("CThrowCountDown"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006164 v8::FunctionTemplate::New(isolate, CThrowCountDown));
Steve Blocka7e24c12009-10-30 11:49:00 +00006165 LocalContext context(0, templ);
6166 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006167 "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
6168 " if (count == 0) throw 'FromJS';"
6169 " if (count % jsInterval == 0) {"
6170 " try {"
6171 " var value = CThrowCountDown(count - 1,"
6172 " jsInterval,"
6173 " cInterval,"
6174 " expected);"
6175 " check(false, count, expected);"
6176 " return value;"
6177 " } catch (e) {"
6178 " check(true, count, expected);"
6179 " }"
6180 " } else {"
6181 " return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
6182 " }"
6183 "}");
6184 Local<Function> fun = Local<Function>::Cast(
6185 context->Global()
6186 ->Get(context.local(), v8_str("JSThrowCountDown"))
6187 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00006188
6189 const int argc = 4;
6190 // count jsInterval cInterval expected
6191
6192 // *JS[4] *C[3] @JS[2] C[1] JS[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006193 v8::Local<Value> a0[argc] = {v8_num(4), v8_num(2), v8_num(3), v8_num(2)};
6194 fun->Call(context.local(), fun, argc, a0).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006195
6196 // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006197 v8::Local<Value> a1[argc] = {v8_num(5), v8_num(6), v8_num(1), v8_num(2)};
6198 fun->Call(context.local(), fun, argc, a1).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006199
6200 // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006201 v8::Local<Value> a2[argc] = {v8_num(6), v8_num(7), v8_num(5), v8_num(5)};
6202 fun->Call(context.local(), fun, argc, a2).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006203
6204 // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006205 v8::Local<Value> a3[argc] = {v8_num(6), v8_num(6), v8_num(7), v8_num(6)};
6206 fun->Call(context.local(), fun, argc, a3).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006207
6208 // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006209 v8::Local<Value> a4[argc] = {v8_num(6), v8_num(4), v8_num(5), v8_num(4)};
6210 fun->Call(context.local(), fun, argc, a4).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006211
6212 // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006213 v8::Local<Value> a5[argc] = {v8_num(6), v8_num(4), v8_num(3), v8_num(3)};
6214 fun->Call(context.local(), fun, argc, a5).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006215}
6216
6217
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006218void ThrowValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006219 ApiTestFuzzer::Fuzz();
6220 CHECK_EQ(1, args.Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006221 args.GetIsolate()->ThrowException(args[0]);
Steve Blocka7e24c12009-10-30 11:49:00 +00006222}
6223
6224
6225THREADED_TEST(ThrowValues) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006226 v8::Isolate* isolate = CcTest::isolate();
6227 v8::HandleScope scope(isolate);
6228 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6229 templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(isolate, ThrowValue));
Steve Blocka7e24c12009-10-30 11:49:00 +00006230 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006231 v8::Local<v8::Array> result = v8::Local<v8::Array>::Cast(
6232 CompileRun("function Run(obj) {"
6233 " try {"
6234 " Throw(obj);"
6235 " } catch (e) {"
6236 " return e;"
6237 " }"
6238 " return 'no exception';"
6239 "}"
6240 "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
6241 CHECK_EQ(5u, result->Length());
6242 CHECK(result->Get(context.local(), v8::Integer::New(isolate, 0))
6243 .ToLocalChecked()
6244 ->IsString());
6245 CHECK(result->Get(context.local(), v8::Integer::New(isolate, 1))
6246 .ToLocalChecked()
6247 ->IsNumber());
6248 CHECK_EQ(1, result->Get(context.local(), v8::Integer::New(isolate, 1))
6249 .ToLocalChecked()
6250 ->Int32Value(context.local())
6251 .FromJust());
6252 CHECK(result->Get(context.local(), v8::Integer::New(isolate, 2))
6253 .ToLocalChecked()
6254 ->IsNumber());
6255 CHECK_EQ(0, result->Get(context.local(), v8::Integer::New(isolate, 2))
6256 .ToLocalChecked()
6257 ->Int32Value(context.local())
6258 .FromJust());
6259 CHECK(result->Get(context.local(), v8::Integer::New(isolate, 3))
6260 .ToLocalChecked()
6261 ->IsNull());
6262 CHECK(result->Get(context.local(), v8::Integer::New(isolate, 4))
6263 .ToLocalChecked()
6264 ->IsUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +00006265}
6266
6267
6268THREADED_TEST(CatchZero) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006269 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006270 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006271 v8::TryCatch try_catch(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006272 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006273 CompileRun("throw 10");
Steve Blocka7e24c12009-10-30 11:49:00 +00006274 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006275 CHECK_EQ(10, try_catch.Exception()->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006276 try_catch.Reset();
6277 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006278 CompileRun("throw 0");
Steve Blocka7e24c12009-10-30 11:49:00 +00006279 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006280 CHECK_EQ(0, try_catch.Exception()->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006281}
6282
6283
6284THREADED_TEST(CatchExceptionFromWith) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006285 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006286 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006287 v8::TryCatch try_catch(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006288 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006289 CompileRun("var o = {}; with (o) { throw 42; }");
Steve Blocka7e24c12009-10-30 11:49:00 +00006290 CHECK(try_catch.HasCaught());
6291}
6292
6293
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006294THREADED_TEST(TryCatchAndFinallyHidingException) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006295 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006296 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006297 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006298 CHECK(!try_catch.HasCaught());
6299 CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
6300 CompileRun("f({toString: function() { throw 42; }});");
6301 CHECK(!try_catch.HasCaught());
6302}
6303
6304
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006305void WithTryCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006306 v8::TryCatch try_catch(args.GetIsolate());
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006307}
6308
6309
6310THREADED_TEST(TryCatchAndFinally) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006311 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006312 v8::Isolate* isolate = context->GetIsolate();
6313 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006314 CHECK(context->Global()
6315 ->Set(context.local(), v8_str("native_with_try_catch"),
6316 v8::FunctionTemplate::New(isolate, WithTryCatch)
6317 ->GetFunction(context.local())
6318 .ToLocalChecked())
6319 .FromJust());
6320 v8::TryCatch try_catch(isolate);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006321 CHECK(!try_catch.HasCaught());
6322 CompileRun(
6323 "try {\n"
6324 " throw new Error('a');\n"
6325 "} finally {\n"
6326 " native_with_try_catch();\n"
6327 "}\n");
6328 CHECK(try_catch.HasCaught());
6329}
6330
6331
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006332static void TryCatchNested1Helper(int depth) {
6333 if (depth > 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006334 v8::TryCatch try_catch(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006335 try_catch.SetVerbose(true);
6336 TryCatchNested1Helper(depth - 1);
6337 CHECK(try_catch.HasCaught());
6338 try_catch.ReThrow();
6339 } else {
6340 CcTest::isolate()->ThrowException(v8_str("E1"));
6341 }
6342}
6343
6344
6345static void TryCatchNested2Helper(int depth) {
6346 if (depth > 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006347 v8::TryCatch try_catch(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006348 try_catch.SetVerbose(true);
6349 TryCatchNested2Helper(depth - 1);
6350 CHECK(try_catch.HasCaught());
6351 try_catch.ReThrow();
6352 } else {
6353 CompileRun("throw 'E2';");
6354 }
6355}
6356
6357
6358TEST(TryCatchNested) {
6359 v8::V8::Initialize();
Steve Blocka7e24c12009-10-30 11:49:00 +00006360 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006361 v8::HandleScope scope(context->GetIsolate());
6362
6363 {
6364 // Test nested try-catch with a native throw in the end.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006365 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006366 TryCatchNested1Helper(5);
6367 CHECK(try_catch.HasCaught());
6368 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E1"));
6369 }
6370
6371 {
6372 // Test nested try-catch with a JavaScript throw in the end.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006373 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006374 TryCatchNested2Helper(5);
6375 CHECK(try_catch.HasCaught());
6376 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E2"));
6377 }
6378}
6379
6380
6381void TryCatchMixedNestingCheck(v8::TryCatch* try_catch) {
6382 CHECK(try_catch->HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006383 Local<Message> message = try_catch->Message();
6384 Local<Value> resource = message->GetScriptOrigin().ResourceName();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006385 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(resource), "inner"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006386 CHECK_EQ(0,
6387 strcmp(*v8::String::Utf8Value(message->Get()), "Uncaught Error: a"));
6388 CHECK_EQ(1, message->GetLineNumber(CcTest::isolate()->GetCurrentContext())
6389 .FromJust());
6390 CHECK_EQ(0, message->GetStartColumn(CcTest::isolate()->GetCurrentContext())
6391 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006392}
6393
6394
6395void TryCatchMixedNestingHelper(
6396 const v8::FunctionCallbackInfo<v8::Value>& args) {
6397 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006398 v8::TryCatch try_catch(args.GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006399 CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
6400 CHECK(try_catch.HasCaught());
6401 TryCatchMixedNestingCheck(&try_catch);
6402 try_catch.ReThrow();
6403}
6404
6405
6406// This test ensures that an outer TryCatch in the following situation:
6407// C++/TryCatch -> JS -> C++/TryCatch -> JS w/ SyntaxError
6408// does not clobber the Message object generated for the inner TryCatch.
6409// This exercises the ability of TryCatch.ReThrow() to restore the
6410// inner pending Message before throwing the exception again.
6411TEST(TryCatchMixedNesting) {
6412 v8::Isolate* isolate = CcTest::isolate();
6413 v8::HandleScope scope(isolate);
6414 v8::V8::Initialize();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006415 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006416 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6417 templ->Set(v8_str("TryCatchMixedNestingHelper"),
6418 v8::FunctionTemplate::New(isolate, TryCatchMixedNestingHelper));
6419 LocalContext context(0, templ);
6420 CompileRunWithOrigin("TryCatchMixedNestingHelper();\n", "outer", 1, 1);
6421 TryCatchMixedNestingCheck(&try_catch);
6422}
6423
6424
6425void TryCatchNativeHelper(const v8::FunctionCallbackInfo<v8::Value>& args) {
6426 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006427 v8::TryCatch try_catch(args.GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006428 args.GetIsolate()->ThrowException(v8_str("boom"));
6429 CHECK(try_catch.HasCaught());
6430}
6431
6432
6433TEST(TryCatchNative) {
6434 v8::Isolate* isolate = CcTest::isolate();
6435 v8::HandleScope scope(isolate);
6436 v8::V8::Initialize();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006437 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006438 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6439 templ->Set(v8_str("TryCatchNativeHelper"),
6440 v8::FunctionTemplate::New(isolate, TryCatchNativeHelper));
6441 LocalContext context(0, templ);
6442 CompileRun("TryCatchNativeHelper();");
6443 CHECK(!try_catch.HasCaught());
6444}
6445
6446
6447void TryCatchNativeResetHelper(
6448 const v8::FunctionCallbackInfo<v8::Value>& args) {
6449 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006450 v8::TryCatch try_catch(args.GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006451 args.GetIsolate()->ThrowException(v8_str("boom"));
6452 CHECK(try_catch.HasCaught());
6453 try_catch.Reset();
6454 CHECK(!try_catch.HasCaught());
6455}
6456
6457
6458TEST(TryCatchNativeReset) {
6459 v8::Isolate* isolate = CcTest::isolate();
6460 v8::HandleScope scope(isolate);
6461 v8::V8::Initialize();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006462 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006463 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6464 templ->Set(v8_str("TryCatchNativeResetHelper"),
6465 v8::FunctionTemplate::New(isolate, TryCatchNativeResetHelper));
6466 LocalContext context(0, templ);
6467 CompileRun("TryCatchNativeResetHelper();");
6468 CHECK(!try_catch.HasCaught());
6469}
6470
6471
6472THREADED_TEST(Equality) {
6473 LocalContext context;
6474 v8::Isolate* isolate = context->GetIsolate();
6475 v8::HandleScope scope(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006476 // Check that equality works at all before relying on CHECK_EQ
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006477 CHECK(v8_str("a")->Equals(context.local(), v8_str("a")).FromJust());
6478 CHECK(!v8_str("a")->Equals(context.local(), v8_str("b")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006479
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006480 CHECK(v8_str("a")->Equals(context.local(), v8_str("a")).FromJust());
6481 CHECK(!v8_str("a")->Equals(context.local(), v8_str("b")).FromJust());
6482 CHECK(v8_num(1)->Equals(context.local(), v8_num(1)).FromJust());
6483 CHECK(v8_num(1.00)->Equals(context.local(), v8_num(1)).FromJust());
6484 CHECK(!v8_num(1)->Equals(context.local(), v8_num(2)).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006485
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006486 // Assume String is not internalized.
Steve Blocka7e24c12009-10-30 11:49:00 +00006487 CHECK(v8_str("a")->StrictEquals(v8_str("a")));
6488 CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
6489 CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
6490 CHECK(v8_num(1)->StrictEquals(v8_num(1)));
6491 CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006492 CHECK(v8_num(0.0)->StrictEquals(v8_num(-0.0)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006493 Local<Value> not_a_number = v8_num(std::numeric_limits<double>::quiet_NaN());
Steve Blocka7e24c12009-10-30 11:49:00 +00006494 CHECK(!not_a_number->StrictEquals(not_a_number));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006495 CHECK(v8::False(isolate)->StrictEquals(v8::False(isolate)));
6496 CHECK(!v8::False(isolate)->StrictEquals(v8::Undefined(isolate)));
Steve Blocka7e24c12009-10-30 11:49:00 +00006497
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006498 v8::Local<v8::Object> obj = v8::Object::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006499 v8::Persistent<v8::Object> alias(isolate, obj);
6500 CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
6501 alias.Reset();
6502
6503 CHECK(v8_str("a")->SameValue(v8_str("a")));
6504 CHECK(!v8_str("a")->SameValue(v8_str("b")));
6505 CHECK(!v8_str("5")->SameValue(v8_num(5)));
6506 CHECK(v8_num(1)->SameValue(v8_num(1)));
6507 CHECK(!v8_num(1)->SameValue(v8_num(2)));
6508 CHECK(!v8_num(0.0)->SameValue(v8_num(-0.0)));
6509 CHECK(not_a_number->SameValue(not_a_number));
6510 CHECK(v8::False(isolate)->SameValue(v8::False(isolate)));
6511 CHECK(!v8::False(isolate)->SameValue(v8::Undefined(isolate)));
Steve Blocka7e24c12009-10-30 11:49:00 +00006512}
6513
6514
6515THREADED_TEST(MultiRun) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006516 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006517 v8::HandleScope scope(context->GetIsolate());
6518 Local<Script> script = v8_compile("x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006519 for (int i = 0; i < 10; i++) {
6520 script->Run(context.local()).IsEmpty();
6521 }
Steve Blocka7e24c12009-10-30 11:49:00 +00006522}
6523
6524
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006525static void GetXValue(Local<Name> name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006526 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006527 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006528 CHECK(info.Data()
6529 ->Equals(CcTest::isolate()->GetCurrentContext(), v8_str("donut"))
6530 .FromJust());
6531 CHECK(name->Equals(CcTest::isolate()->GetCurrentContext(), v8_str("x"))
6532 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006533 info.GetReturnValue().Set(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00006534}
6535
6536
6537THREADED_TEST(SimplePropertyRead) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006538 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006539 v8::Isolate* isolate = context->GetIsolate();
6540 v8::HandleScope scope(isolate);
6541 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6542 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006543 CHECK(context->Global()
6544 ->Set(context.local(), v8_str("obj"),
6545 templ->NewInstance(context.local()).ToLocalChecked())
6546 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006547 Local<Script> script = v8_compile("obj.x");
Steve Blocka7e24c12009-10-30 11:49:00 +00006548 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006549 Local<Value> result = script->Run(context.local()).ToLocalChecked();
6550 CHECK(result->Equals(context.local(), v8_str("x")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006551 }
6552}
6553
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006554
Andrei Popescu31002712010-02-23 13:46:05 +00006555THREADED_TEST(DefinePropertyOnAPIAccessor) {
Andrei Popescu31002712010-02-23 13:46:05 +00006556 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006557 v8::Isolate* isolate = context->GetIsolate();
6558 v8::HandleScope scope(isolate);
6559 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6560 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006561 CHECK(context->Global()
6562 ->Set(context.local(), v8_str("obj"),
6563 templ->NewInstance(context.local()).ToLocalChecked())
6564 .FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +00006565
6566 // Uses getOwnPropertyDescriptor to check the configurable status
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006567 Local<Script> script_desc = v8_compile(
6568 "var prop = Object.getOwnPropertyDescriptor( "
6569 "obj, 'x');"
6570 "prop.configurable;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006571 Local<Value> result = script_desc->Run(context.local()).ToLocalChecked();
6572 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), true);
Andrei Popescu31002712010-02-23 13:46:05 +00006573
6574 // Redefine get - but still configurable
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006575 Local<Script> script_define = v8_compile(
6576 "var desc = { get: function(){return 42; },"
6577 " configurable: true };"
6578 "Object.defineProperty(obj, 'x', desc);"
6579 "obj.x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006580 result = script_define->Run(context.local()).ToLocalChecked();
6581 CHECK(result->Equals(context.local(), v8_num(42)).FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +00006582
6583 // Check that the accessor is still configurable
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006584 result = script_desc->Run(context.local()).ToLocalChecked();
6585 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), true);
Andrei Popescu31002712010-02-23 13:46:05 +00006586
6587 // Redefine to a non-configurable
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006588 script_define = v8_compile(
6589 "var desc = { get: function(){return 43; },"
6590 " configurable: false };"
6591 "Object.defineProperty(obj, 'x', desc);"
6592 "obj.x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006593 result = script_define->Run(context.local()).ToLocalChecked();
6594 CHECK(result->Equals(context.local(), v8_num(43)).FromJust());
6595 result = script_desc->Run(context.local()).ToLocalChecked();
6596 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), false);
Andrei Popescu31002712010-02-23 13:46:05 +00006597
6598 // Make sure that it is not possible to redefine again
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006599 v8::TryCatch try_catch(isolate);
6600 CHECK(script_define->Run(context.local()).IsEmpty());
Andrei Popescu31002712010-02-23 13:46:05 +00006601 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006602 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006603 CHECK_EQ(0,
6604 strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
Andrei Popescu31002712010-02-23 13:46:05 +00006605}
6606
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006607
Andrei Popescu31002712010-02-23 13:46:05 +00006608THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006609 v8::Isolate* isolate = CcTest::isolate();
6610 v8::HandleScope scope(isolate);
6611 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Andrei Popescu31002712010-02-23 13:46:05 +00006612 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
6613 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006614 CHECK(context->Global()
6615 ->Set(context.local(), v8_str("obj"),
6616 templ->NewInstance(context.local()).ToLocalChecked())
6617 .FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +00006618
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006619 Local<Script> script_desc = v8_compile(
6620 "var prop ="
6621 "Object.getOwnPropertyDescriptor( "
6622 "obj, 'x');"
6623 "prop.configurable;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006624 Local<Value> result = script_desc->Run(context.local()).ToLocalChecked();
6625 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), true);
Andrei Popescu31002712010-02-23 13:46:05 +00006626
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006627 Local<Script> script_define = v8_compile(
6628 "var desc = {get: function(){return 42; },"
6629 " configurable: true };"
6630 "Object.defineProperty(obj, 'x', desc);"
6631 "obj.x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006632 result = script_define->Run(context.local()).ToLocalChecked();
6633 CHECK(result->Equals(context.local(), v8_num(42)).FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +00006634
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006635 result = script_desc->Run(context.local()).ToLocalChecked();
6636 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), true);
Andrei Popescu31002712010-02-23 13:46:05 +00006637
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006638 script_define = v8_compile(
6639 "var desc = {get: function(){return 43; },"
6640 " configurable: false };"
6641 "Object.defineProperty(obj, 'x', desc);"
6642 "obj.x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006643 result = script_define->Run(context.local()).ToLocalChecked();
6644 CHECK(result->Equals(context.local(), v8_num(43)).FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +00006645
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006646 result = script_desc->Run(context.local()).ToLocalChecked();
6647 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), false);
Andrei Popescu31002712010-02-23 13:46:05 +00006648
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006649 v8::TryCatch try_catch(isolate);
6650 CHECK(script_define->Run(context.local()).IsEmpty());
Andrei Popescu31002712010-02-23 13:46:05 +00006651 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006652 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006653 CHECK_EQ(0,
6654 strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
Andrei Popescu31002712010-02-23 13:46:05 +00006655}
6656
6657
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006658static v8::Local<v8::Object> GetGlobalProperty(LocalContext* context,
6659 char const* name) {
6660 return v8::Local<v8::Object>::Cast(
6661 (*context)
6662 ->Global()
6663 ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(name))
6664 .ToLocalChecked());
Leon Clarkef7060e22010-06-03 12:02:55 +01006665}
Andrei Popescu31002712010-02-23 13:46:05 +00006666
6667
Leon Clarkef7060e22010-06-03 12:02:55 +01006668THREADED_TEST(DefineAPIAccessorOnObject) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006669 v8::Isolate* isolate = CcTest::isolate();
6670 v8::HandleScope scope(isolate);
6671 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Leon Clarkef7060e22010-06-03 12:02:55 +01006672 LocalContext context;
6673
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006674 CHECK(context->Global()
6675 ->Set(context.local(), v8_str("obj1"),
6676 templ->NewInstance(context.local()).ToLocalChecked())
6677 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006678 CompileRun("var obj2 = {};");
6679
6680 CHECK(CompileRun("obj1.x")->IsUndefined());
6681 CHECK(CompileRun("obj2.x")->IsUndefined());
6682
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006683 CHECK(GetGlobalProperty(&context, "obj1")
6684 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6685 v8_str("donut"))
6686 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006687
6688 ExpectString("obj1.x", "x");
6689 CHECK(CompileRun("obj2.x")->IsUndefined());
6690
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006691 CHECK(GetGlobalProperty(&context, "obj2")
6692 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6693 v8_str("donut"))
6694 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006695
6696 ExpectString("obj1.x", "x");
6697 ExpectString("obj2.x", "x");
6698
6699 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
6700 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
6701
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006702 CompileRun(
6703 "Object.defineProperty(obj1, 'x',"
6704 "{ get: function() { return 'y'; }, configurable: true })");
Leon Clarkef7060e22010-06-03 12:02:55 +01006705
6706 ExpectString("obj1.x", "y");
6707 ExpectString("obj2.x", "x");
6708
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006709 CompileRun(
6710 "Object.defineProperty(obj2, 'x',"
6711 "{ get: function() { return 'y'; }, configurable: true })");
Leon Clarkef7060e22010-06-03 12:02:55 +01006712
6713 ExpectString("obj1.x", "y");
6714 ExpectString("obj2.x", "y");
6715
6716 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
6717 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
6718
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006719 CHECK(GetGlobalProperty(&context, "obj1")
6720 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6721 v8_str("donut"))
6722 .FromJust());
6723 CHECK(GetGlobalProperty(&context, "obj2")
6724 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6725 v8_str("donut"))
6726 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006727
6728 ExpectString("obj1.x", "x");
6729 ExpectString("obj2.x", "x");
6730
6731 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
6732 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
6733
6734 // Define getters/setters, but now make them not configurable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006735 CompileRun(
6736 "Object.defineProperty(obj1, 'x',"
6737 "{ get: function() { return 'z'; }, configurable: false })");
6738 CompileRun(
6739 "Object.defineProperty(obj2, 'x',"
6740 "{ get: function() { return 'z'; }, configurable: false })");
Leon Clarkef7060e22010-06-03 12:02:55 +01006741 ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
6742 ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
6743
6744 ExpectString("obj1.x", "z");
6745 ExpectString("obj2.x", "z");
6746
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006747 CHECK(GetGlobalProperty(&context, "obj1")
6748 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6749 v8_str("donut"))
6750 .IsNothing());
6751 CHECK(GetGlobalProperty(&context, "obj2")
6752 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6753 v8_str("donut"))
6754 .IsNothing());
Leon Clarkef7060e22010-06-03 12:02:55 +01006755
6756 ExpectString("obj1.x", "z");
6757 ExpectString("obj2.x", "z");
6758}
6759
6760
6761THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006762 v8::Isolate* isolate = CcTest::isolate();
6763 v8::HandleScope scope(isolate);
6764 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Leon Clarkef7060e22010-06-03 12:02:55 +01006765 LocalContext context;
6766
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006767 CHECK(context->Global()
6768 ->Set(context.local(), v8_str("obj1"),
6769 templ->NewInstance(context.local()).ToLocalChecked())
6770 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006771 CompileRun("var obj2 = {};");
6772
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006773 CHECK(GetGlobalProperty(&context, "obj1")
6774 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6775 v8_str("donut"), v8::DEFAULT, v8::DontDelete)
6776 .FromJust());
6777 CHECK(GetGlobalProperty(&context, "obj2")
6778 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6779 v8_str("donut"), v8::DEFAULT, v8::DontDelete)
6780 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006781
6782 ExpectString("obj1.x", "x");
6783 ExpectString("obj2.x", "x");
6784
6785 ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
6786 ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
6787
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006788 CHECK(GetGlobalProperty(&context, "obj1")
6789 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6790 v8_str("donut"))
6791 .IsNothing());
6792 CHECK(GetGlobalProperty(&context, "obj2")
6793 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6794 v8_str("donut"))
6795 .IsNothing());
Leon Clarkef7060e22010-06-03 12:02:55 +01006796
6797 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006798 v8::TryCatch try_catch(isolate);
6799 CompileRun(
6800 "Object.defineProperty(obj1, 'x',"
Leon Clarkef7060e22010-06-03 12:02:55 +01006801 "{get: function() { return 'func'; }})");
6802 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006803 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006804 CHECK_EQ(
6805 0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
Leon Clarkef7060e22010-06-03 12:02:55 +01006806 }
6807 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006808 v8::TryCatch try_catch(isolate);
6809 CompileRun(
6810 "Object.defineProperty(obj2, 'x',"
Leon Clarkef7060e22010-06-03 12:02:55 +01006811 "{get: function() { return 'func'; }})");
6812 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006813 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006814 CHECK_EQ(
6815 0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
Leon Clarkef7060e22010-06-03 12:02:55 +01006816 }
6817}
6818
6819
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006820static void Get239Value(Local<Name> name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006821 const v8::PropertyCallbackInfo<v8::Value>& info) {
Leon Clarkef7060e22010-06-03 12:02:55 +01006822 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006823 CHECK(info.Data()
6824 ->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("donut"))
6825 .FromJust());
6826 CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("239"))
6827 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006828 info.GetReturnValue().Set(name);
Leon Clarkef7060e22010-06-03 12:02:55 +01006829}
6830
6831
6832THREADED_TEST(ElementAPIAccessor) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006833 v8::Isolate* isolate = CcTest::isolate();
6834 v8::HandleScope scope(isolate);
6835 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Leon Clarkef7060e22010-06-03 12:02:55 +01006836 LocalContext context;
6837
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006838 CHECK(context->Global()
6839 ->Set(context.local(), v8_str("obj1"),
6840 templ->NewInstance(context.local()).ToLocalChecked())
6841 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006842 CompileRun("var obj2 = {};");
6843
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006844 CHECK(GetGlobalProperty(&context, "obj1")
6845 ->SetAccessor(context.local(), v8_str("239"), Get239Value, NULL,
6846 v8_str("donut"))
6847 .FromJust());
6848 CHECK(GetGlobalProperty(&context, "obj2")
6849 ->SetAccessor(context.local(), v8_str("239"), Get239Value, NULL,
6850 v8_str("donut"))
6851 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006852
6853 ExpectString("obj1[239]", "239");
6854 ExpectString("obj2[239]", "239");
6855 ExpectString("obj1['239']", "239");
6856 ExpectString("obj2['239']", "239");
6857}
6858
Steve Blocka7e24c12009-10-30 11:49:00 +00006859
6860v8::Persistent<Value> xValue;
6861
6862
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006863static void SetXValue(Local<Name> name, Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006864 const v8::PropertyCallbackInfo<void>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006865 Local<Context> context = info.GetIsolate()->GetCurrentContext();
6866 CHECK(value->Equals(context, v8_num(4)).FromJust());
6867 CHECK(info.Data()->Equals(context, v8_str("donut")).FromJust());
6868 CHECK(name->Equals(context, v8_str("x")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006869 CHECK(xValue.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006870 xValue.Reset(info.GetIsolate(), value);
Steve Blocka7e24c12009-10-30 11:49:00 +00006871}
6872
6873
6874THREADED_TEST(SimplePropertyWrite) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006875 v8::Isolate* isolate = CcTest::isolate();
6876 v8::HandleScope scope(isolate);
6877 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00006878 templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
6879 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006880 CHECK(context->Global()
6881 ->Set(context.local(), v8_str("obj"),
6882 templ->NewInstance(context.local()).ToLocalChecked())
6883 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006884 Local<Script> script = v8_compile("obj.x = 4");
Steve Blocka7e24c12009-10-30 11:49:00 +00006885 for (int i = 0; i < 10; i++) {
6886 CHECK(xValue.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006887 script->Run(context.local()).ToLocalChecked();
6888 CHECK(v8_num(4)
6889 ->Equals(context.local(),
6890 Local<Value>::New(CcTest::isolate(), xValue))
6891 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006892 xValue.Reset();
Steve Blocka7e24c12009-10-30 11:49:00 +00006893 }
6894}
6895
6896
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006897THREADED_TEST(SetterOnly) {
6898 v8::Isolate* isolate = CcTest::isolate();
6899 v8::HandleScope scope(isolate);
6900 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6901 templ->SetAccessor(v8_str("x"), NULL, SetXValue, v8_str("donut"));
6902 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006903 CHECK(context->Global()
6904 ->Set(context.local(), v8_str("obj"),
6905 templ->NewInstance(context.local()).ToLocalChecked())
6906 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006907 Local<Script> script = v8_compile("obj.x = 4; obj.x");
6908 for (int i = 0; i < 10; i++) {
6909 CHECK(xValue.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006910 script->Run(context.local()).ToLocalChecked();
6911 CHECK(v8_num(4)
6912 ->Equals(context.local(),
6913 Local<Value>::New(CcTest::isolate(), xValue))
6914 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006915 xValue.Reset();
6916 }
6917}
6918
6919
6920THREADED_TEST(NoAccessors) {
6921 v8::Isolate* isolate = CcTest::isolate();
6922 v8::HandleScope scope(isolate);
6923 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006924 templ->SetAccessor(v8_str("x"), static_cast<v8::AccessorGetterCallback>(NULL),
6925 NULL, v8_str("donut"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006926 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006927 CHECK(context->Global()
6928 ->Set(context.local(), v8_str("obj"),
6929 templ->NewInstance(context.local()).ToLocalChecked())
6930 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006931 Local<Script> script = v8_compile("obj.x = 4; obj.x");
6932 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006933 script->Run(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006934 }
6935}
6936
6937
Steve Blocka7e24c12009-10-30 11:49:00 +00006938THREADED_TEST(MultiContexts) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006939 v8::Isolate* isolate = CcTest::isolate();
6940 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006941 v8::Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6942 templ->Set(v8_str("dummy"),
6943 v8::FunctionTemplate::New(isolate, DummyCallHandler));
Steve Blocka7e24c12009-10-30 11:49:00 +00006944
6945 Local<String> password = v8_str("Password");
6946
6947 // Create an environment
6948 LocalContext context0(0, templ);
6949 context0->SetSecurityToken(password);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006950 v8::Local<v8::Object> global0 = context0->Global();
6951 CHECK(global0->Set(context0.local(), v8_str("custom"), v8_num(1234))
6952 .FromJust());
6953 CHECK_EQ(1234, global0->Get(context0.local(), v8_str("custom"))
6954 .ToLocalChecked()
6955 ->Int32Value(context0.local())
6956 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006957
6958 // Create an independent environment
6959 LocalContext context1(0, templ);
6960 context1->SetSecurityToken(password);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006961 v8::Local<v8::Object> global1 = context1->Global();
6962 CHECK(global1->Set(context1.local(), v8_str("custom"), v8_num(1234))
6963 .FromJust());
6964 CHECK(!global0->Equals(context1.local(), global1).FromJust());
6965 CHECK_EQ(1234, global0->Get(context1.local(), v8_str("custom"))
6966 .ToLocalChecked()
6967 ->Int32Value(context0.local())
6968 .FromJust());
6969 CHECK_EQ(1234, global1->Get(context1.local(), v8_str("custom"))
6970 .ToLocalChecked()
6971 ->Int32Value(context1.local())
6972 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006973
6974 // Now create a new context with the old global
6975 LocalContext context2(0, templ, global1);
6976 context2->SetSecurityToken(password);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006977 v8::Local<v8::Object> global2 = context2->Global();
6978 CHECK(global1->Equals(context2.local(), global2).FromJust());
6979 CHECK_EQ(0, global1->Get(context2.local(), v8_str("custom"))
6980 .ToLocalChecked()
6981 ->Int32Value(context1.local())
6982 .FromJust());
6983 CHECK_EQ(0, global2->Get(context2.local(), v8_str("custom"))
6984 .ToLocalChecked()
6985 ->Int32Value(context2.local())
6986 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006987}
6988
6989
6990THREADED_TEST(FunctionPrototypeAcrossContexts) {
6991 // Make sure that functions created by cloning boilerplates cannot
6992 // communicate through their __proto__ field.
6993
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006994 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006995
6996 LocalContext env0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006997 v8::Local<v8::Object> global0 = env0->Global();
6998 v8::Local<v8::Object> object0 = global0->Get(env0.local(), v8_str("Object"))
6999 .ToLocalChecked()
7000 .As<v8::Object>();
7001 v8::Local<v8::Object> tostring0 =
7002 object0->Get(env0.local(), v8_str("toString"))
7003 .ToLocalChecked()
7004 .As<v8::Object>();
7005 v8::Local<v8::Object> proto0 =
7006 tostring0->Get(env0.local(), v8_str("__proto__"))
7007 .ToLocalChecked()
7008 .As<v8::Object>();
7009 CHECK(proto0->Set(env0.local(), v8_str("custom"), v8_num(1234)).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007010
7011 LocalContext env1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007012 v8::Local<v8::Object> global1 = env1->Global();
7013 v8::Local<v8::Object> object1 = global1->Get(env1.local(), v8_str("Object"))
7014 .ToLocalChecked()
7015 .As<v8::Object>();
7016 v8::Local<v8::Object> tostring1 =
7017 object1->Get(env1.local(), v8_str("toString"))
7018 .ToLocalChecked()
7019 .As<v8::Object>();
7020 v8::Local<v8::Object> proto1 =
7021 tostring1->Get(env1.local(), v8_str("__proto__"))
7022 .ToLocalChecked()
7023 .As<v8::Object>();
7024 CHECK(!proto1->Has(env1.local(), v8_str("custom")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007025}
7026
7027
7028THREADED_TEST(Regress892105) {
7029 // Make sure that object and array literals created by cloning
7030 // boilerplates cannot communicate through their __proto__
7031 // field. This is rather difficult to check, but we try to add stuff
7032 // to Object.prototype and Array.prototype and create a new
7033 // environment. This should succeed.
7034
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007035 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007036
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007037 Local<String> source = v8_str(
7038 "Object.prototype.obj = 1234;"
7039 "Array.prototype.arr = 4567;"
7040 "8901");
Steve Blocka7e24c12009-10-30 11:49:00 +00007041
7042 LocalContext env0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007043 Local<Script> script0 = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007044 CHECK_EQ(8901.0, script0->Run(env0.local())
7045 .ToLocalChecked()
7046 ->NumberValue(env0.local())
7047 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007048
7049 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007050 Local<Script> script1 = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007051 CHECK_EQ(8901.0, script1->Run(env1.local())
7052 .ToLocalChecked()
7053 ->NumberValue(env1.local())
7054 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007055}
7056
7057
Steve Blocka7e24c12009-10-30 11:49:00 +00007058THREADED_TEST(UndetectableObject) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007059 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007060 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007061
7062 Local<v8::FunctionTemplate> desc =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007063 v8::FunctionTemplate::New(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007064 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
7065
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007066 Local<v8::Object> obj = desc->GetFunction(env.local())
7067 .ToLocalChecked()
7068 ->NewInstance(env.local())
7069 .ToLocalChecked();
7070 CHECK(
7071 env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007072
7073 ExpectString("undetectable.toString()", "[object Object]");
7074 ExpectString("typeof undetectable", "undefined");
7075 ExpectString("typeof(undetectable)", "undefined");
7076 ExpectBoolean("typeof undetectable == 'undefined'", true);
7077 ExpectBoolean("typeof undetectable == 'object'", false);
7078 ExpectBoolean("if (undetectable) { true; } else { false; }", false);
7079 ExpectBoolean("!undetectable", true);
7080
7081 ExpectObject("true&&undetectable", obj);
7082 ExpectBoolean("false&&undetectable", false);
7083 ExpectBoolean("true||undetectable", true);
7084 ExpectObject("false||undetectable", obj);
7085
7086 ExpectObject("undetectable&&true", obj);
7087 ExpectObject("undetectable&&false", obj);
7088 ExpectBoolean("undetectable||true", true);
7089 ExpectBoolean("undetectable||false", false);
7090
7091 ExpectBoolean("undetectable==null", true);
7092 ExpectBoolean("null==undetectable", true);
7093 ExpectBoolean("undetectable==undefined", true);
7094 ExpectBoolean("undefined==undetectable", true);
7095 ExpectBoolean("undetectable==undetectable", true);
7096
7097
7098 ExpectBoolean("undetectable===null", false);
7099 ExpectBoolean("null===undetectable", false);
7100 ExpectBoolean("undetectable===undefined", false);
7101 ExpectBoolean("undefined===undetectable", false);
7102 ExpectBoolean("undetectable===undetectable", true);
7103}
7104
7105
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007106THREADED_TEST(VoidLiteral) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007107 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007108 v8::Isolate* isolate = env->GetIsolate();
7109 v8::HandleScope scope(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007110
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007111 Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007112 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
7113
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007114 Local<v8::Object> obj = desc->GetFunction(env.local())
7115 .ToLocalChecked()
7116 ->NewInstance(env.local())
7117 .ToLocalChecked();
7118 CHECK(
7119 env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007120
7121 ExpectBoolean("undefined == void 0", true);
7122 ExpectBoolean("undetectable == void 0", true);
7123 ExpectBoolean("null == void 0", true);
7124 ExpectBoolean("undefined === void 0", true);
7125 ExpectBoolean("undetectable === void 0", false);
7126 ExpectBoolean("null === void 0", false);
7127
7128 ExpectBoolean("void 0 == undefined", true);
7129 ExpectBoolean("void 0 == undetectable", true);
7130 ExpectBoolean("void 0 == null", true);
7131 ExpectBoolean("void 0 === undefined", true);
7132 ExpectBoolean("void 0 === undetectable", false);
7133 ExpectBoolean("void 0 === null", false);
7134
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007135 ExpectString(
7136 "(function() {"
7137 " try {"
7138 " return x === void 0;"
7139 " } catch(e) {"
7140 " return e.toString();"
7141 " }"
7142 "})()",
7143 "ReferenceError: x is not defined");
7144 ExpectString(
7145 "(function() {"
7146 " try {"
7147 " return void 0 === x;"
7148 " } catch(e) {"
7149 " return e.toString();"
7150 " }"
7151 "})()",
7152 "ReferenceError: x is not defined");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007153}
7154
Steve Block8defd9f2010-07-08 12:39:36 +01007155
7156THREADED_TEST(ExtensibleOnUndetectable) {
Steve Block8defd9f2010-07-08 12:39:36 +01007157 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007158 v8::Isolate* isolate = env->GetIsolate();
7159 v8::HandleScope scope(isolate);
Steve Block8defd9f2010-07-08 12:39:36 +01007160
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007161 Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
Steve Block8defd9f2010-07-08 12:39:36 +01007162 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
7163
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007164 Local<v8::Object> obj = desc->GetFunction(env.local())
7165 .ToLocalChecked()
7166 ->NewInstance(env.local())
7167 .ToLocalChecked();
7168 CHECK(
7169 env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +01007170
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007171 Local<String> source = v8_str(
7172 "undetectable.x = 42;"
7173 "undetectable.x");
Steve Block8defd9f2010-07-08 12:39:36 +01007174
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007175 Local<Script> script = v8_compile(source);
Steve Block8defd9f2010-07-08 12:39:36 +01007176
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007177 CHECK(v8::Integer::New(isolate, 42)
7178 ->Equals(env.local(), script->Run(env.local()).ToLocalChecked())
7179 .FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +01007180
7181 ExpectBoolean("Object.isExtensible(undetectable)", true);
7182
7183 source = v8_str("Object.preventExtensions(undetectable);");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007184 script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007185 script->Run(env.local()).ToLocalChecked();
Steve Block8defd9f2010-07-08 12:39:36 +01007186 ExpectBoolean("Object.isExtensible(undetectable)", false);
7187
7188 source = v8_str("undetectable.y = 2000;");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007189 script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007190 script->Run(env.local()).ToLocalChecked();
Steve Block44f0eee2011-05-26 01:26:41 +01007191 ExpectBoolean("undetectable.y == undefined", true);
Steve Block8defd9f2010-07-08 12:39:36 +01007192}
7193
7194
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007195// The point of this test is type checking. We run it only so compilers
7196// don't complain about an unused function.
7197TEST(PersistentHandles) {
7198 LocalContext env;
7199 v8::Isolate* isolate = CcTest::isolate();
7200 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00007201 Local<String> str = v8_str("foo");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007202 v8::Persistent<String> p_str(isolate, str);
7203 p_str.Reset();
7204 Local<Script> scr = v8_compile("");
7205 v8::Persistent<Script> p_scr(isolate, scr);
7206 p_scr.Reset();
7207 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
7208 v8::Persistent<ObjectTemplate> p_templ(isolate, templ);
7209 p_templ.Reset();
Steve Blocka7e24c12009-10-30 11:49:00 +00007210}
7211
7212
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007213static void HandleLogDelegator(
7214 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007215 ApiTestFuzzer::Fuzz();
Steve Blocka7e24c12009-10-30 11:49:00 +00007216}
7217
7218
7219THREADED_TEST(GlobalObjectTemplate) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007220 v8::Isolate* isolate = CcTest::isolate();
7221 v8::HandleScope handle_scope(isolate);
7222 Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00007223 global_template->Set(v8_str("JSNI_Log"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007224 v8::FunctionTemplate::New(isolate, HandleLogDelegator));
7225 v8::Local<Context> context = Context::New(isolate, 0, global_template);
Steve Blocka7e24c12009-10-30 11:49:00 +00007226 Context::Scope context_scope(context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007227 CompileRun("JSNI_Log('LOG')");
Steve Blocka7e24c12009-10-30 11:49:00 +00007228}
7229
7230
7231static const char* kSimpleExtensionSource =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007232 "function Foo() {"
7233 " return 4;"
7234 "}";
Steve Blocka7e24c12009-10-30 11:49:00 +00007235
7236
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007237TEST(SimpleExtensions) {
7238 v8::HandleScope handle_scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007239 v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007240 const char* extension_names[] = {"simpletest"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007241 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007242 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Steve Blocka7e24c12009-10-30 11:49:00 +00007243 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007244 v8::Local<Value> result = CompileRun("Foo()");
7245 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
7246 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007247}
7248
7249
7250static const char* kStackTraceFromExtensionSource =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007251 "function foo() {"
7252 " throw new Error();"
7253 "}"
7254 "function bar() {"
7255 " foo();"
7256 "}";
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007257
7258
7259TEST(StackTraceInExtension) {
7260 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007261 v8::RegisterExtension(
7262 new Extension("stacktracetest", kStackTraceFromExtensionSource));
7263 const char* extension_names[] = {"stacktracetest"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007264 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007265 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007266 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007267 CompileRun(
7268 "function user() { bar(); }"
7269 "var error;"
7270 "try{ user(); } catch (e) { error = e; }");
7271 CHECK_EQ(-1, v8_run_int32value(v8_compile("error.stack.indexOf('foo')")));
7272 CHECK_EQ(-1, v8_run_int32value(v8_compile("error.stack.indexOf('bar')")));
7273 CHECK_NE(-1, v8_run_int32value(v8_compile("error.stack.indexOf('user')")));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007274}
7275
7276
7277TEST(NullExtensions) {
7278 v8::HandleScope handle_scope(CcTest::isolate());
7279 v8::RegisterExtension(new Extension("nulltest", NULL));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007280 const char* extension_names[] = {"nulltest"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007281 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007282 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007283 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007284 v8::Local<Value> result = CompileRun("1+3");
7285 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
7286 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007287}
7288
7289
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007290static const char* kEmbeddedExtensionSource =
7291 "function Ret54321(){return 54321;}~~@@$"
7292 "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
7293static const int kEmbeddedExtensionSourceValidLen = 34;
7294
7295
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007296TEST(ExtensionMissingSourceLength) {
7297 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007298 v8::RegisterExtension(
7299 new Extension("srclentest_fail", kEmbeddedExtensionSource));
7300 const char* extension_names[] = {"srclentest_fail"};
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007301 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007302 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
7303 CHECK(0 == *context);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007304}
7305
7306
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007307TEST(ExtensionWithSourceLength) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007308 for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
7309 source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007310 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007311 i::ScopedVector<char> extension_name(32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007312 i::SNPrintF(extension_name, "ext #%d", source_len);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007313 v8::RegisterExtension(new Extension(
7314 extension_name.start(), kEmbeddedExtensionSource, 0, 0, source_len));
7315 const char* extension_names[1] = {extension_name.start()};
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007316 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007317 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007318 if (source_len == kEmbeddedExtensionSourceValidLen) {
7319 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007320 v8::Local<Value> result = CompileRun("Ret54321()");
7321 CHECK(v8::Integer::New(CcTest::isolate(), 54321)
7322 ->Equals(context, result)
7323 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007324 } else {
7325 // Anything but exactly the right length should fail to compile.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007326 CHECK(0 == *context);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007327 }
7328 }
7329}
7330
7331
Steve Blocka7e24c12009-10-30 11:49:00 +00007332static const char* kEvalExtensionSource1 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007333 "function UseEval1() {"
7334 " var x = 42;"
7335 " return eval('x');"
7336 "}";
Steve Blocka7e24c12009-10-30 11:49:00 +00007337
7338
7339static const char* kEvalExtensionSource2 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007340 "(function() {"
7341 " var x = 42;"
7342 " function e() {"
7343 " return eval('x');"
7344 " }"
7345 " this.UseEval2 = e;"
7346 "})()";
Steve Blocka7e24c12009-10-30 11:49:00 +00007347
7348
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007349TEST(UseEvalFromExtension) {
7350 v8::HandleScope handle_scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007351 v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
7352 v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007353 const char* extension_names[] = {"evaltest1", "evaltest2"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007354 v8::ExtensionConfiguration extensions(2, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007355 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Steve Blocka7e24c12009-10-30 11:49:00 +00007356 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007357 v8::Local<Value> result = CompileRun("UseEval1()");
7358 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
7359 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007360 result = CompileRun("UseEval2()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007361 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
7362 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007363}
7364
7365
7366static const char* kWithExtensionSource1 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007367 "function UseWith1() {"
7368 " var x = 42;"
7369 " with({x:87}) { return x; }"
7370 "}";
Steve Blocka7e24c12009-10-30 11:49:00 +00007371
7372
7373static const char* kWithExtensionSource2 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007374 "(function() {"
7375 " var x = 42;"
7376 " function e() {"
7377 " with ({x:87}) { return x; }"
7378 " }"
7379 " this.UseWith2 = e;"
7380 "})()";
Steve Blocka7e24c12009-10-30 11:49:00 +00007381
7382
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007383TEST(UseWithFromExtension) {
7384 v8::HandleScope handle_scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007385 v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
7386 v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007387 const char* extension_names[] = {"withtest1", "withtest2"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007388 v8::ExtensionConfiguration extensions(2, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007389 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Steve Blocka7e24c12009-10-30 11:49:00 +00007390 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007391 v8::Local<Value> result = CompileRun("UseWith1()");
7392 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 87))
7393 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007394 result = CompileRun("UseWith2()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007395 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 87))
7396 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007397}
7398
7399
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007400TEST(AutoExtensions) {
7401 v8::HandleScope handle_scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007402 Extension* extension = new Extension("autotest", kSimpleExtensionSource);
7403 extension->set_auto_enable(true);
7404 v8::RegisterExtension(extension);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007405 v8::Local<Context> context = Context::New(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007406 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007407 v8::Local<Value> result = CompileRun("Foo()");
7408 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
7409 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007410}
7411
7412
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007413static const char* kSyntaxErrorInExtensionSource = "[";
Steve Blockd0582a62009-12-15 09:54:21 +00007414
7415
7416// Test that a syntax error in an extension does not cause a fatal
7417// error but results in an empty context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007418TEST(SyntaxErrorExtensions) {
7419 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007420 v8::RegisterExtension(
7421 new Extension("syntaxerror", kSyntaxErrorInExtensionSource));
7422 const char* extension_names[] = {"syntaxerror"};
Steve Blockd0582a62009-12-15 09:54:21 +00007423 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007424 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Steve Blockd0582a62009-12-15 09:54:21 +00007425 CHECK(context.IsEmpty());
7426}
7427
7428
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007429static const char* kExceptionInExtensionSource = "throw 42";
Steve Blockd0582a62009-12-15 09:54:21 +00007430
7431
7432// Test that an exception when installing an extension does not cause
7433// a fatal error but results in an empty context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007434TEST(ExceptionExtensions) {
7435 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007436 v8::RegisterExtension(
7437 new Extension("exception", kExceptionInExtensionSource));
7438 const char* extension_names[] = {"exception"};
Steve Blockd0582a62009-12-15 09:54:21 +00007439 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007440 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Steve Blockd0582a62009-12-15 09:54:21 +00007441 CHECK(context.IsEmpty());
7442}
7443
7444
Iain Merrick9ac36c92010-09-13 15:29:50 +01007445static const char* kNativeCallInExtensionSource =
7446 "function call_runtime_last_index_of(x) {"
7447 " return %StringLastIndexOf(x, 'bob', 10);"
7448 "}";
7449
7450
7451static const char* kNativeCallTest =
7452 "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
7453
7454// Test that a native runtime calls are supported in extensions.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007455TEST(NativeCallInExtensions) {
7456 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007457 v8::RegisterExtension(
7458 new Extension("nativecall", kNativeCallInExtensionSource));
7459 const char* extension_names[] = {"nativecall"};
Iain Merrick9ac36c92010-09-13 15:29:50 +01007460 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007461 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Iain Merrick9ac36c92010-09-13 15:29:50 +01007462 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007463 v8::Local<Value> result = CompileRun(kNativeCallTest);
7464 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 3))
7465 .FromJust());
Iain Merrick9ac36c92010-09-13 15:29:50 +01007466}
7467
7468
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007469class NativeFunctionExtension : public Extension {
7470 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007471 NativeFunctionExtension(const char* name, const char* source,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007472 v8::FunctionCallback fun = &Echo)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007473 : Extension(name, source), function_(fun) {}
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007474
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007475 virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
7476 v8::Isolate* isolate, v8::Local<v8::String> name) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007477 return v8::FunctionTemplate::New(isolate, function_);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007478 }
7479
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007480 static void Echo(const v8::FunctionCallbackInfo<v8::Value>& args) {
7481 if (args.Length() >= 1) args.GetReturnValue().Set(args[0]);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007482 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007483
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007484 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007485 v8::FunctionCallback function_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007486};
7487
7488
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007489TEST(NativeFunctionDeclaration) {
7490 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007491 const char* name = "nativedecl";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007492 v8::RegisterExtension(
7493 new NativeFunctionExtension(name, "native function foo();"));
7494 const char* extension_names[] = {name};
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007495 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007496 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007497 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007498 v8::Local<Value> result = CompileRun("foo(42);");
7499 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
7500 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007501}
7502
7503
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007504TEST(NativeFunctionDeclarationError) {
7505 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007506 const char* name = "nativedeclerr";
7507 // Syntax error in extension code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007508 v8::RegisterExtension(
7509 new NativeFunctionExtension(name, "native\nfunction foo();"));
7510 const char* extension_names[] = {name};
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007511 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007512 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007513 CHECK(context.IsEmpty());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007514}
7515
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007516
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007517TEST(NativeFunctionDeclarationErrorEscape) {
7518 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007519 const char* name = "nativedeclerresc";
7520 // Syntax error in extension code - escape code in "native" means that
7521 // it's not treated as a keyword.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007522 v8::RegisterExtension(
7523 new NativeFunctionExtension(name, "nativ\\u0065 function foo();"));
7524 const char* extension_names[] = {name};
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007525 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007526 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007527 CHECK(context.IsEmpty());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007528}
7529
7530
Steve Blocka7e24c12009-10-30 11:49:00 +00007531static void CheckDependencies(const char* name, const char* expected) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007532 v8::HandleScope handle_scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007533 v8::ExtensionConfiguration config(1, &name);
7534 LocalContext context(&config);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007535 CHECK(
7536 v8_str(expected)
7537 ->Equals(context.local(), context->Global()
7538 ->Get(context.local(), v8_str("loaded"))
7539 .ToLocalChecked())
7540 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007541}
7542
7543
7544/*
7545 * Configuration:
7546 *
7547 * /-- B <--\
7548 * A <- -- D <-- E
7549 * \-- C <--/
7550 */
7551THREADED_TEST(ExtensionDependency) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007552 static const char* kEDeps[] = {"D"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007553 v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007554 static const char* kDDeps[] = {"B", "C"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007555 v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007556 static const char* kBCDeps[] = {"A"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007557 v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
7558 v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
7559 v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
7560 CheckDependencies("A", "undefinedA");
7561 CheckDependencies("B", "undefinedAB");
7562 CheckDependencies("C", "undefinedAC");
7563 CheckDependencies("D", "undefinedABCD");
7564 CheckDependencies("E", "undefinedABCDE");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007565 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007566 static const char* exts[2] = {"C", "E"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007567 v8::ExtensionConfiguration config(2, exts);
7568 LocalContext context(&config);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007569 CHECK(
7570 v8_str("undefinedACBDE")
7571 ->Equals(context.local(), context->Global()
7572 ->Get(context.local(), v8_str("loaded"))
7573 .ToLocalChecked())
7574 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007575}
7576
7577
7578static const char* kExtensionTestScript =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007579 "native function A();"
7580 "native function B();"
7581 "native function C();"
7582 "function Foo(i) {"
7583 " if (i == 0) return A();"
7584 " if (i == 1) return B();"
7585 " if (i == 2) return C();"
7586 "}";
Steve Blocka7e24c12009-10-30 11:49:00 +00007587
7588
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007589static void CallFun(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007590 ApiTestFuzzer::Fuzz();
Leon Clarkee46be812010-01-19 14:06:41 +00007591 if (args.IsConstructCall()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007592 CHECK(args.This()
7593 ->Set(args.GetIsolate()->GetCurrentContext(), v8_str("data"),
7594 args.Data())
7595 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007596 args.GetReturnValue().SetNull();
7597 return;
Leon Clarkee46be812010-01-19 14:06:41 +00007598 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007599 args.GetReturnValue().Set(args.Data());
Steve Blocka7e24c12009-10-30 11:49:00 +00007600}
7601
7602
7603class FunctionExtension : public Extension {
7604 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007605 FunctionExtension() : Extension("functiontest", kExtensionTestScript) {}
7606 virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
7607 v8::Isolate* isolate, v8::Local<String> name);
Steve Blocka7e24c12009-10-30 11:49:00 +00007608};
7609
7610
7611static int lookup_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007612v8::Local<v8::FunctionTemplate> FunctionExtension::GetNativeFunctionTemplate(
7613 v8::Isolate* isolate, v8::Local<String> name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007614 lookup_count++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007615 if (name->Equals(isolate->GetCurrentContext(), v8_str("A")).FromJust()) {
7616 return v8::FunctionTemplate::New(isolate, CallFun,
7617 v8::Integer::New(isolate, 8));
7618 } else if (name->Equals(isolate->GetCurrentContext(), v8_str("B"))
7619 .FromJust()) {
7620 return v8::FunctionTemplate::New(isolate, CallFun,
7621 v8::Integer::New(isolate, 7));
7622 } else if (name->Equals(isolate->GetCurrentContext(), v8_str("C"))
7623 .FromJust()) {
7624 return v8::FunctionTemplate::New(isolate, CallFun,
7625 v8::Integer::New(isolate, 6));
Steve Blocka7e24c12009-10-30 11:49:00 +00007626 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007627 return v8::Local<v8::FunctionTemplate>();
Steve Blocka7e24c12009-10-30 11:49:00 +00007628 }
7629}
7630
7631
7632THREADED_TEST(FunctionLookup) {
7633 v8::RegisterExtension(new FunctionExtension());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007634 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007635 static const char* exts[1] = {"functiontest"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007636 v8::ExtensionConfiguration config(1, exts);
7637 LocalContext context(&config);
7638 CHECK_EQ(3, lookup_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007639 CHECK(v8::Integer::New(CcTest::isolate(), 8)
7640 ->Equals(context.local(), CompileRun("Foo(0)"))
7641 .FromJust());
7642 CHECK(v8::Integer::New(CcTest::isolate(), 7)
7643 ->Equals(context.local(), CompileRun("Foo(1)"))
7644 .FromJust());
7645 CHECK(v8::Integer::New(CcTest::isolate(), 6)
7646 ->Equals(context.local(), CompileRun("Foo(2)"))
7647 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007648}
7649
7650
Leon Clarkee46be812010-01-19 14:06:41 +00007651THREADED_TEST(NativeFunctionConstructCall) {
7652 v8::RegisterExtension(new FunctionExtension());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007653 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007654 static const char* exts[1] = {"functiontest"};
Leon Clarkee46be812010-01-19 14:06:41 +00007655 v8::ExtensionConfiguration config(1, exts);
7656 LocalContext context(&config);
Leon Clarked91b9f72010-01-27 17:25:45 +00007657 for (int i = 0; i < 10; i++) {
7658 // Run a few times to ensure that allocation of objects doesn't
7659 // change behavior of a constructor function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007660 CHECK(v8::Integer::New(CcTest::isolate(), 8)
7661 ->Equals(context.local(), CompileRun("(new A()).data"))
7662 .FromJust());
7663 CHECK(v8::Integer::New(CcTest::isolate(), 7)
7664 ->Equals(context.local(), CompileRun("(new B()).data"))
7665 .FromJust());
7666 CHECK(v8::Integer::New(CcTest::isolate(), 6)
7667 ->Equals(context.local(), CompileRun("(new C()).data"))
7668 .FromJust());
Leon Clarked91b9f72010-01-27 17:25:45 +00007669 }
Leon Clarkee46be812010-01-19 14:06:41 +00007670}
7671
7672
Steve Blocka7e24c12009-10-30 11:49:00 +00007673static const char* last_location;
7674static const char* last_message;
7675void StoringErrorCallback(const char* location, const char* message) {
7676 if (last_location == NULL) {
7677 last_location = location;
7678 last_message = message;
7679 }
7680}
7681
7682
7683// ErrorReporting creates a circular extensions configuration and
7684// tests that the fatal error handler gets called. This renders V8
7685// unusable and therefore this test cannot be run in parallel.
7686TEST(ErrorReporting) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007687 CcTest::isolate()->SetFatalErrorHandler(StoringErrorCallback);
7688 static const char* aDeps[] = {"B"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007689 v8::RegisterExtension(new Extension("A", "", 1, aDeps));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007690 static const char* bDeps[] = {"A"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007691 v8::RegisterExtension(new Extension("B", "", 1, bDeps));
7692 last_location = NULL;
7693 v8::ExtensionConfiguration config(1, bDeps);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007694 v8::Local<Context> context = Context::New(CcTest::isolate(), &config);
Steve Blocka7e24c12009-10-30 11:49:00 +00007695 CHECK(context.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007696 CHECK(last_location);
Steve Blocka7e24c12009-10-30 11:49:00 +00007697}
7698
7699
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007700static void MissingScriptInfoMessageListener(v8::Local<v8::Message> message,
7701 v8::Local<Value> data) {
7702 v8::Isolate* isolate = CcTest::isolate();
7703 Local<Context> context = isolate->GetCurrentContext();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007704 CHECK(message->GetScriptOrigin().ResourceName()->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007705 CHECK(v8::Undefined(isolate)
7706 ->Equals(context, message->GetScriptOrigin().ResourceName())
7707 .FromJust());
7708 message->GetLineNumber(context).FromJust();
7709 message->GetSourceLine(context).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00007710}
7711
7712
7713THREADED_TEST(ErrorWithMissingScriptInfo) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007714 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007715 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007716 context->GetIsolate()->AddMessageListener(MissingScriptInfoMessageListener);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007717 CompileRun("throw Error()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007718 context->GetIsolate()->RemoveMessageListeners(
7719 MissingScriptInfoMessageListener);
Steve Blocka7e24c12009-10-30 11:49:00 +00007720}
7721
7722
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007723struct FlagAndPersistent {
7724 bool flag;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007725 v8::Global<v8::Object> handle;
Steve Blocka7e24c12009-10-30 11:49:00 +00007726};
7727
Steve Blocka7e24c12009-10-30 11:49:00 +00007728
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007729static void SetFlag(const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007730 data.GetParameter()->flag = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007731 data.GetParameter()->handle.Reset();
Steve Blockd0582a62009-12-15 09:54:21 +00007732}
7733
Steve Blockd0582a62009-12-15 09:54:21 +00007734
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007735static void IndependentWeakHandle(bool global_gc, bool interlinked) {
7736 v8::Isolate* iso = CcTest::isolate();
7737 v8::HandleScope scope(iso);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007738 v8::Local<Context> context = Context::New(iso);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007739 Context::Scope context_scope(context);
7740
7741 FlagAndPersistent object_a, object_b;
7742
7743 intptr_t big_heap_size;
7744
7745 {
7746 v8::HandleScope handle_scope(iso);
7747 Local<Object> a(v8::Object::New(iso));
7748 Local<Object> b(v8::Object::New(iso));
7749 object_a.handle.Reset(iso, a);
7750 object_b.handle.Reset(iso, b);
7751 if (interlinked) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007752 a->Set(context, v8_str("x"), b).FromJust();
7753 b->Set(context, v8_str("x"), a).FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007754 }
7755 if (global_gc) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007756 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007757 } else {
7758 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
7759 }
7760 // We are relying on this creating a big flag array and reserving the space
7761 // up front.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007762 v8::Local<Value> big_array = CompileRun("new Array(5000)");
7763 a->Set(context, v8_str("y"), big_array).FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007764 big_heap_size = CcTest::heap()->SizeOfObjects();
7765 }
7766
7767 object_a.flag = false;
7768 object_b.flag = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007769 object_a.handle.SetWeak(&object_a, &SetFlag,
7770 v8::WeakCallbackType::kParameter);
7771 object_b.handle.SetWeak(&object_b, &SetFlag,
7772 v8::WeakCallbackType::kParameter);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007773 CHECK(!object_b.handle.IsIndependent());
7774 object_a.handle.MarkIndependent();
7775 object_b.handle.MarkIndependent();
7776 CHECK(object_b.handle.IsIndependent());
7777 if (global_gc) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007778 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007779 } else {
7780 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
7781 }
7782 // A single GC should be enough to reclaim the memory, since we are using
7783 // phantom handles.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007784 CHECK_LT(CcTest::heap()->SizeOfObjects(), big_heap_size - 20000);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007785 CHECK(object_a.flag);
7786 CHECK(object_b.flag);
7787}
7788
7789
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007790TEST(IndependentWeakHandle) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007791 IndependentWeakHandle(false, false);
7792 IndependentWeakHandle(false, true);
7793 IndependentWeakHandle(true, false);
7794 IndependentWeakHandle(true, true);
7795}
7796
7797
7798class Trivial {
7799 public:
7800 explicit Trivial(int x) : x_(x) {}
7801
7802 int x() { return x_; }
7803 void set_x(int x) { x_ = x; }
7804
7805 private:
7806 int x_;
7807};
7808
7809
7810class Trivial2 {
7811 public:
7812 Trivial2(int x, int y) : y_(y), x_(x) {}
7813
7814 int x() { return x_; }
7815 void set_x(int x) { x_ = x; }
7816
7817 int y() { return y_; }
7818 void set_y(int y) { y_ = y; }
7819
7820 private:
7821 int y_;
7822 int x_;
7823};
7824
7825
7826void CheckInternalFields(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007827 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
7828 v8::Persistent<v8::Object>* handle = data.GetParameter();
7829 handle->Reset();
7830 Trivial* t1 = reinterpret_cast<Trivial*>(data.GetInternalField(0));
7831 Trivial2* t2 = reinterpret_cast<Trivial2*>(data.GetInternalField(1));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007832 CHECK_EQ(42, t1->x());
7833 CHECK_EQ(103, t2->x());
7834 t1->set_x(1729);
7835 t2->set_x(33550336);
7836}
7837
7838
7839void InternalFieldCallback(bool global_gc) {
7840 LocalContext env;
7841 v8::Isolate* isolate = env->GetIsolate();
7842 v8::HandleScope scope(isolate);
7843
7844 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
7845 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
7846 Trivial* t1;
7847 Trivial2* t2;
7848 instance_templ->SetInternalFieldCount(2);
7849 {
7850 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007851 Local<v8::Object> obj = templ->GetFunction(env.local())
7852 .ToLocalChecked()
7853 ->NewInstance(env.local())
7854 .ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007855 v8::Persistent<v8::Object> handle(isolate, obj);
7856 CHECK_EQ(2, obj->InternalFieldCount());
7857 CHECK(obj->GetInternalField(0)->IsUndefined());
7858 t1 = new Trivial(42);
7859 t2 = new Trivial2(103, 9);
7860
7861 obj->SetAlignedPointerInInternalField(0, t1);
7862 t1 = reinterpret_cast<Trivial*>(obj->GetAlignedPointerFromInternalField(0));
7863 CHECK_EQ(42, t1->x());
7864
7865 obj->SetAlignedPointerInInternalField(1, t2);
7866 t2 =
7867 reinterpret_cast<Trivial2*>(obj->GetAlignedPointerFromInternalField(1));
7868 CHECK_EQ(103, t2->x());
7869
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007870 handle.SetWeak<v8::Persistent<v8::Object>>(
7871 &handle, CheckInternalFields, v8::WeakCallbackType::kInternalFields);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007872 if (!global_gc) {
7873 handle.MarkIndependent();
7874 }
7875 }
7876 if (global_gc) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007877 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007878 } else {
7879 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
7880 }
7881
7882 CHECK_EQ(1729, t1->x());
7883 CHECK_EQ(33550336, t2->x());
7884
7885 delete t1;
7886 delete t2;
7887}
7888
7889
7890THREADED_TEST(InternalFieldCallback) {
7891 InternalFieldCallback(false);
7892 InternalFieldCallback(true);
7893}
7894
7895
7896static void ResetUseValueAndSetFlag(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007897 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007898 // Blink will reset the handle, and then use the other handle, so they
7899 // can't use the same backing slot.
7900 data.GetParameter()->handle.Reset();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007901 data.GetParameter()->flag = true;
7902}
7903
7904
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007905void v8::internal::HeapTester::ResetWeakHandle(bool global_gc) {
7906 using v8::Context;
7907 using v8::Local;
7908 using v8::Object;
7909
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007910 v8::Isolate* iso = CcTest::isolate();
7911 v8::HandleScope scope(iso);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007912 v8::Local<Context> context = Context::New(iso);
Steve Blockd0582a62009-12-15 09:54:21 +00007913 Context::Scope context_scope(context);
7914
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007915 FlagAndPersistent object_a, object_b;
Steve Blockd0582a62009-12-15 09:54:21 +00007916
7917 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007918 v8::HandleScope handle_scope(iso);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007919 Local<Object> a(v8::Object::New(iso));
7920 Local<Object> b(v8::Object::New(iso));
7921 object_a.handle.Reset(iso, a);
7922 object_b.handle.Reset(iso, b);
7923 if (global_gc) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007924 CcTest::heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007925 } else {
7926 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
7927 }
Steve Blockd0582a62009-12-15 09:54:21 +00007928 }
7929
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007930 object_a.flag = false;
7931 object_b.flag = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007932 object_a.handle.SetWeak(&object_a, &ResetUseValueAndSetFlag,
7933 v8::WeakCallbackType::kParameter);
7934 object_b.handle.SetWeak(&object_b, &ResetUseValueAndSetFlag,
7935 v8::WeakCallbackType::kParameter);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007936 if (!global_gc) {
7937 object_a.handle.MarkIndependent();
7938 object_b.handle.MarkIndependent();
7939 CHECK(object_b.handle.IsIndependent());
7940 }
7941 if (global_gc) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007942 CcTest::heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007943 } else {
7944 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
7945 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007946 CHECK(object_a.flag);
7947 CHECK(object_b.flag);
Ben Murdoch257744e2011-11-30 15:57:28 +00007948}
Steve Blockd0582a62009-12-15 09:54:21 +00007949
Ben Murdoch257744e2011-11-30 15:57:28 +00007950
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007951THREADED_HEAP_TEST(ResetWeakHandle) {
7952 v8::internal::HeapTester::ResetWeakHandle(false);
7953 v8::internal::HeapTester::ResetWeakHandle(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007954}
7955
7956
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007957static void InvokeScavenge() { CcTest::heap()->CollectGarbage(i::NEW_SPACE); }
Ben Murdoch257744e2011-11-30 15:57:28 +00007958
7959
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007960static void InvokeMarkSweep() { CcTest::heap()->CollectAllGarbage(); }
Ben Murdoch257744e2011-11-30 15:57:28 +00007961
7962
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007963static void ForceScavenge2(
7964 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007965 data.GetParameter()->flag = true;
Ben Murdoch257744e2011-11-30 15:57:28 +00007966 InvokeScavenge();
7967}
7968
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007969static void ForceScavenge1(
7970 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007971 data.GetParameter()->handle.Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007972 data.SetSecondPassCallback(ForceScavenge2);
7973}
7974
7975
7976static void ForceMarkSweep2(
7977 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007978 data.GetParameter()->flag = true;
Ben Murdoch257744e2011-11-30 15:57:28 +00007979 InvokeMarkSweep();
7980}
7981
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007982static void ForceMarkSweep1(
7983 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
7984 data.GetParameter()->handle.Reset();
7985 data.SetSecondPassCallback(ForceMarkSweep2);
7986}
7987
Ben Murdoch257744e2011-11-30 15:57:28 +00007988
7989THREADED_TEST(GCFromWeakCallbacks) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007990 v8::Isolate* isolate = CcTest::isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007991 v8::Locker locker(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007992 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007993 v8::Local<Context> context = Context::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +00007994 Context::Scope context_scope(context);
7995
7996 static const int kNumberOfGCTypes = 2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007997 typedef v8::WeakCallbackInfo<FlagAndPersistent>::Callback Callback;
7998 Callback gc_forcing_callback[kNumberOfGCTypes] = {&ForceScavenge1,
7999 &ForceMarkSweep1};
Ben Murdoch257744e2011-11-30 15:57:28 +00008000
8001 typedef void (*GCInvoker)();
8002 GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
8003
8004 for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
8005 for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008006 FlagAndPersistent object;
Ben Murdoch257744e2011-11-30 15:57:28 +00008007 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008008 v8::HandleScope handle_scope(isolate);
8009 object.handle.Reset(isolate, v8::Object::New(isolate));
Ben Murdoch257744e2011-11-30 15:57:28 +00008010 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008011 object.flag = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008012 object.handle.SetWeak(&object, gc_forcing_callback[inner_gc],
8013 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008014 object.handle.MarkIndependent();
Ben Murdoch257744e2011-11-30 15:57:28 +00008015 invoke_gc[outer_gc]();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008016 EmptyMessageQueues(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008017 CHECK(object.flag);
Ben Murdoch257744e2011-11-30 15:57:28 +00008018 }
Steve Blockd0582a62009-12-15 09:54:21 +00008019 }
Ben Murdoch257744e2011-11-30 15:57:28 +00008020}
8021
8022
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008023v8::Local<Function> args_fun;
Steve Blocka7e24c12009-10-30 11:49:00 +00008024
8025
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008026static void ArgumentsTestCallback(
8027 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008028 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008029 v8::Isolate* isolate = args.GetIsolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008030 Local<Context> context = isolate->GetCurrentContext();
Steve Blocka7e24c12009-10-30 11:49:00 +00008031 CHECK_EQ(3, args.Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008032 CHECK(v8::Integer::New(isolate, 1)->Equals(context, args[0]).FromJust());
8033 CHECK(v8::Integer::New(isolate, 2)->Equals(context, args[1]).FromJust());
8034 CHECK(v8::Integer::New(isolate, 3)->Equals(context, args[2]).FromJust());
8035 CHECK(v8::Undefined(isolate)->Equals(context, args[3]).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008036 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008037 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +00008038}
8039
8040
8041THREADED_TEST(Arguments) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008042 v8::Isolate* isolate = CcTest::isolate();
8043 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008044 v8::Local<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008045 global->Set(v8_str("f"),
8046 v8::FunctionTemplate::New(isolate, ArgumentsTestCallback));
Steve Blocka7e24c12009-10-30 11:49:00 +00008047 LocalContext context(NULL, global);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008048 args_fun = context->Global()
8049 ->Get(context.local(), v8_str("f"))
8050 .ToLocalChecked()
8051 .As<Function>();
8052 v8_compile("f(1, 2, 3)")->Run(context.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00008053}
8054
8055
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008056static int p_getter_count;
8057static int p_getter_count2;
Steve Blocka7e24c12009-10-30 11:49:00 +00008058
8059
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008060static void PGetter(Local<Name> name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008061 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008062 ApiTestFuzzer::Fuzz();
8063 p_getter_count++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008064 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
8065 v8::Local<v8::Object> global = context->Global();
8066 CHECK(
8067 info.Holder()
8068 ->Equals(context, global->Get(context, v8_str("o1")).ToLocalChecked())
8069 .FromJust());
8070 if (name->Equals(context, v8_str("p1")).FromJust()) {
8071 CHECK(info.This()
8072 ->Equals(context,
8073 global->Get(context, v8_str("o1")).ToLocalChecked())
8074 .FromJust());
8075 } else if (name->Equals(context, v8_str("p2")).FromJust()) {
8076 CHECK(info.This()
8077 ->Equals(context,
8078 global->Get(context, v8_str("o2")).ToLocalChecked())
8079 .FromJust());
8080 } else if (name->Equals(context, v8_str("p3")).FromJust()) {
8081 CHECK(info.This()
8082 ->Equals(context,
8083 global->Get(context, v8_str("o3")).ToLocalChecked())
8084 .FromJust());
8085 } else if (name->Equals(context, v8_str("p4")).FromJust()) {
8086 CHECK(info.This()
8087 ->Equals(context,
8088 global->Get(context, v8_str("o4")).ToLocalChecked())
8089 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008090 }
Steve Blocka7e24c12009-10-30 11:49:00 +00008091}
8092
8093
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008094static void RunHolderTest(v8::Local<v8::ObjectTemplate> obj) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008095 ApiTestFuzzer::Fuzz();
8096 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008097 CHECK(context->Global()
8098 ->Set(context.local(), v8_str("o1"),
8099 obj->NewInstance(context.local()).ToLocalChecked())
8100 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008101 CompileRun(
8102 "o1.__proto__ = { };"
8103 "var o2 = { __proto__: o1 };"
8104 "var o3 = { __proto__: o2 };"
8105 "var o4 = { __proto__: o3 };"
8106 "for (var i = 0; i < 10; i++) o4.p4;"
8107 "for (var i = 0; i < 10; i++) o3.p3;"
8108 "for (var i = 0; i < 10; i++) o2.p2;"
8109 "for (var i = 0; i < 10; i++) o1.p1;");
8110}
8111
8112
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008113static void PGetter2(Local<Name> name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008114 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008115 ApiTestFuzzer::Fuzz();
8116 p_getter_count2++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008117 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
8118 v8::Local<v8::Object> global = context->Global();
8119 CHECK(
8120 info.Holder()
8121 ->Equals(context, global->Get(context, v8_str("o1")).ToLocalChecked())
8122 .FromJust());
8123 if (name->Equals(context, v8_str("p1")).FromJust()) {
8124 CHECK(info.This()
8125 ->Equals(context,
8126 global->Get(context, v8_str("o1")).ToLocalChecked())
8127 .FromJust());
8128 } else if (name->Equals(context, v8_str("p2")).FromJust()) {
8129 CHECK(info.This()
8130 ->Equals(context,
8131 global->Get(context, v8_str("o2")).ToLocalChecked())
8132 .FromJust());
8133 } else if (name->Equals(context, v8_str("p3")).FromJust()) {
8134 CHECK(info.This()
8135 ->Equals(context,
8136 global->Get(context, v8_str("o3")).ToLocalChecked())
8137 .FromJust());
8138 } else if (name->Equals(context, v8_str("p4")).FromJust()) {
8139 CHECK(info.This()
8140 ->Equals(context,
8141 global->Get(context, v8_str("o4")).ToLocalChecked())
8142 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008143 }
Steve Blocka7e24c12009-10-30 11:49:00 +00008144}
8145
8146
8147THREADED_TEST(GetterHolders) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008148 v8::Isolate* isolate = CcTest::isolate();
8149 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008150 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00008151 obj->SetAccessor(v8_str("p1"), PGetter);
8152 obj->SetAccessor(v8_str("p2"), PGetter);
8153 obj->SetAccessor(v8_str("p3"), PGetter);
8154 obj->SetAccessor(v8_str("p4"), PGetter);
8155 p_getter_count = 0;
8156 RunHolderTest(obj);
8157 CHECK_EQ(40, p_getter_count);
8158}
8159
8160
8161THREADED_TEST(PreInterceptorHolders) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008162 v8::Isolate* isolate = CcTest::isolate();
8163 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008164 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008165 obj->SetHandler(v8::NamedPropertyHandlerConfiguration(PGetter2));
Steve Blocka7e24c12009-10-30 11:49:00 +00008166 p_getter_count2 = 0;
8167 RunHolderTest(obj);
8168 CHECK_EQ(40, p_getter_count2);
8169}
8170
8171
8172THREADED_TEST(ObjectInstantiation) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008173 v8::Isolate* isolate = CcTest::isolate();
8174 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008175 v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00008176 templ->SetAccessor(v8_str("t"), PGetter2);
8177 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008178 CHECK(context->Global()
8179 ->Set(context.local(), v8_str("o"),
8180 templ->NewInstance(context.local()).ToLocalChecked())
8181 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008182 for (int i = 0; i < 100; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008183 v8::HandleScope inner_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008184 v8::Local<v8::Object> obj =
8185 templ->NewInstance(context.local()).ToLocalChecked();
8186 CHECK(!obj->Equals(context.local(), context->Global()
8187 ->Get(context.local(), v8_str("o"))
8188 .ToLocalChecked())
8189 .FromJust());
8190 CHECK(
8191 context->Global()->Set(context.local(), v8_str("o2"), obj).FromJust());
8192 v8::Local<Value> value = CompileRun("o.__proto__ === o2.__proto__");
8193 CHECK(v8::True(isolate)->Equals(context.local(), value).FromJust());
8194 CHECK(context->Global()->Set(context.local(), v8_str("o"), obj).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008195 }
8196}
8197
8198
Ben Murdochb0fe1622011-05-05 13:52:32 +01008199static int StrCmp16(uint16_t* a, uint16_t* b) {
8200 while (true) {
8201 if (*a == 0 && *b == 0) return 0;
8202 if (*a != *b) return 0 + *a - *b;
8203 a++;
8204 b++;
8205 }
8206}
8207
8208
8209static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
8210 while (true) {
8211 if (n-- == 0) return 0;
8212 if (*a == 0 && *b == 0) return 0;
8213 if (*a != *b) return 0 + *a - *b;
8214 a++;
8215 b++;
8216 }
8217}
8218
8219
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008220int GetUtf8Length(Local<String> str) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008221 int len = str->Utf8Length();
8222 if (len < 0) {
8223 i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008224 i::String::Flatten(istr);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008225 len = str->Utf8Length();
8226 }
8227 return len;
8228}
8229
8230
Steve Blocka7e24c12009-10-30 11:49:00 +00008231THREADED_TEST(StringWrite) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008232 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008233 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008234 v8::Local<String> str = v8_str("abcde");
Ben Murdochb0fe1622011-05-05 13:52:32 +01008235 // abc<Icelandic eth><Unicode snowman>.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008236 v8::Local<String> str2 = v8_str("abc\303\260\342\230\203");
8237 v8::Local<String> str3 =
8238 v8::String::NewFromUtf8(context->GetIsolate(), "abc\0def",
8239 v8::NewStringType::kNormal, 7)
8240 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008241 // "ab" + lead surrogate + "cd" + trail surrogate + "ef"
8242 uint16_t orphans[8] = { 0x61, 0x62, 0xd800, 0x63, 0x64, 0xdc00, 0x65, 0x66 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008243 v8::Local<String> orphans_str =
8244 v8::String::NewFromTwoByte(context->GetIsolate(), orphans,
8245 v8::NewStringType::kNormal, 8)
8246 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008247 // single lead surrogate
8248 uint16_t lead[1] = { 0xd800 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008249 v8::Local<String> lead_str =
8250 v8::String::NewFromTwoByte(context->GetIsolate(), lead,
8251 v8::NewStringType::kNormal, 1)
8252 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008253 // single trail surrogate
8254 uint16_t trail[1] = { 0xdc00 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008255 v8::Local<String> trail_str =
8256 v8::String::NewFromTwoByte(context->GetIsolate(), trail,
8257 v8::NewStringType::kNormal, 1)
8258 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008259 // surrogate pair
8260 uint16_t pair[2] = { 0xd800, 0xdc00 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008261 v8::Local<String> pair_str =
8262 v8::String::NewFromTwoByte(context->GetIsolate(), pair,
8263 v8::NewStringType::kNormal, 2)
8264 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008265 const int kStride = 4; // Must match stride in for loops in JS below.
8266 CompileRun(
8267 "var left = '';"
8268 "for (var i = 0; i < 0xd800; i += 4) {"
8269 " left = left + String.fromCharCode(i);"
8270 "}");
8271 CompileRun(
8272 "var right = '';"
8273 "for (var i = 0; i < 0xd800; i += 4) {"
8274 " right = String.fromCharCode(i) + right;"
8275 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008276 v8::Local<v8::Object> global = context->Global();
8277 Local<String> left_tree = global->Get(context.local(), v8_str("left"))
8278 .ToLocalChecked()
8279 .As<String>();
8280 Local<String> right_tree = global->Get(context.local(), v8_str("right"))
8281 .ToLocalChecked()
8282 .As<String>();
Ben Murdochb0fe1622011-05-05 13:52:32 +01008283
8284 CHECK_EQ(5, str2->Length());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008285 CHECK_EQ(0xd800 / kStride, left_tree->Length());
8286 CHECK_EQ(0xd800 / kStride, right_tree->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +00008287
8288 char buf[100];
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008289 char utf8buf[0xd800 * 3];
Ben Murdochb0fe1622011-05-05 13:52:32 +01008290 uint16_t wbuf[100];
Steve Blocka7e24c12009-10-30 11:49:00 +00008291 int len;
Ben Murdochb0fe1622011-05-05 13:52:32 +01008292 int charlen;
8293
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008294 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008295 len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008296 CHECK_EQ(9, len);
8297 CHECK_EQ(5, charlen);
8298 CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008299
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008300 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008301 len = str2->WriteUtf8(utf8buf, 8, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008302 CHECK_EQ(8, len);
8303 CHECK_EQ(5, charlen);
8304 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008305
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008306 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008307 len = str2->WriteUtf8(utf8buf, 7, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008308 CHECK_EQ(5, len);
8309 CHECK_EQ(4, charlen);
8310 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008311
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008312 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008313 len = str2->WriteUtf8(utf8buf, 6, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008314 CHECK_EQ(5, len);
8315 CHECK_EQ(4, charlen);
8316 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008317
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008318 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008319 len = str2->WriteUtf8(utf8buf, 5, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008320 CHECK_EQ(5, len);
8321 CHECK_EQ(4, charlen);
8322 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008323
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008324 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008325 len = str2->WriteUtf8(utf8buf, 4, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008326 CHECK_EQ(3, len);
8327 CHECK_EQ(3, charlen);
8328 CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008329
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008330 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008331 len = str2->WriteUtf8(utf8buf, 3, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008332 CHECK_EQ(3, len);
8333 CHECK_EQ(3, charlen);
8334 CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008335
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008336 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008337 len = str2->WriteUtf8(utf8buf, 2, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008338 CHECK_EQ(2, len);
8339 CHECK_EQ(2, charlen);
8340 CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
Steve Blocka7e24c12009-10-30 11:49:00 +00008341
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008342 // allow orphan surrogates by default
8343 memset(utf8buf, 0x1, 1000);
8344 len = orphans_str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
8345 CHECK_EQ(13, len);
8346 CHECK_EQ(8, charlen);
8347 CHECK_EQ(0, strcmp(utf8buf, "ab\355\240\200cd\355\260\200ef"));
8348
8349 // replace orphan surrogates with unicode replacement character
8350 memset(utf8buf, 0x1, 1000);
8351 len = orphans_str->WriteUtf8(utf8buf,
8352 sizeof(utf8buf),
8353 &charlen,
8354 String::REPLACE_INVALID_UTF8);
8355 CHECK_EQ(13, len);
8356 CHECK_EQ(8, charlen);
8357 CHECK_EQ(0, strcmp(utf8buf, "ab\357\277\275cd\357\277\275ef"));
8358
8359 // replace single lead surrogate with unicode replacement character
8360 memset(utf8buf, 0x1, 1000);
8361 len = lead_str->WriteUtf8(utf8buf,
8362 sizeof(utf8buf),
8363 &charlen,
8364 String::REPLACE_INVALID_UTF8);
8365 CHECK_EQ(4, len);
8366 CHECK_EQ(1, charlen);
8367 CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
8368
8369 // replace single trail surrogate with unicode replacement character
8370 memset(utf8buf, 0x1, 1000);
8371 len = trail_str->WriteUtf8(utf8buf,
8372 sizeof(utf8buf),
8373 &charlen,
8374 String::REPLACE_INVALID_UTF8);
8375 CHECK_EQ(4, len);
8376 CHECK_EQ(1, charlen);
8377 CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
8378
8379 // do not replace / write anything if surrogate pair does not fit the buffer
8380 // space
8381 memset(utf8buf, 0x1, 1000);
8382 len = pair_str->WriteUtf8(utf8buf,
8383 3,
8384 &charlen,
8385 String::REPLACE_INVALID_UTF8);
8386 CHECK_EQ(0, len);
8387 CHECK_EQ(0, charlen);
8388
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008389 memset(utf8buf, 0x1, sizeof(utf8buf));
8390 len = GetUtf8Length(left_tree);
8391 int utf8_expected =
8392 (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride;
8393 CHECK_EQ(utf8_expected, len);
8394 len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
8395 CHECK_EQ(utf8_expected, len);
8396 CHECK_EQ(0xd800 / kStride, charlen);
8397 CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
8398 CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
8399 CHECK_EQ(0xc0 - kStride,
8400 static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
8401 CHECK_EQ(1, utf8buf[utf8_expected]);
8402
8403 memset(utf8buf, 0x1, sizeof(utf8buf));
8404 len = GetUtf8Length(right_tree);
8405 CHECK_EQ(utf8_expected, len);
8406 len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
8407 CHECK_EQ(utf8_expected, len);
8408 CHECK_EQ(0xd800 / kStride, charlen);
8409 CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0]));
8410 CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1]));
8411 CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2]));
8412 CHECK_EQ(1, utf8buf[utf8_expected]);
8413
Steve Blocka7e24c12009-10-30 11:49:00 +00008414 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008415 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008416 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
Steve Block44f0eee2011-05-26 01:26:41 +01008417 CHECK_EQ(5, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008418 len = str->Write(wbuf);
Steve Block44f0eee2011-05-26 01:26:41 +01008419 CHECK_EQ(5, len);
8420 CHECK_EQ(0, strcmp("abcde", buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008421 uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
Steve Block44f0eee2011-05-26 01:26:41 +01008422 CHECK_EQ(0, StrCmp16(answer1, wbuf));
Steve Blocka7e24c12009-10-30 11:49:00 +00008423
8424 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008425 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008426 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 4);
Steve Block44f0eee2011-05-26 01:26:41 +01008427 CHECK_EQ(4, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008428 len = str->Write(wbuf, 0, 4);
Steve Block44f0eee2011-05-26 01:26:41 +01008429 CHECK_EQ(4, len);
8430 CHECK_EQ(0, strncmp("abcd\1", buf, 5));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008431 uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
Steve Block44f0eee2011-05-26 01:26:41 +01008432 CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
Steve Blocka7e24c12009-10-30 11:49:00 +00008433
8434 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008435 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008436 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 5);
Steve Block44f0eee2011-05-26 01:26:41 +01008437 CHECK_EQ(5, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008438 len = str->Write(wbuf, 0, 5);
Steve Block44f0eee2011-05-26 01:26:41 +01008439 CHECK_EQ(5, len);
8440 CHECK_EQ(0, strncmp("abcde\1", buf, 6));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008441 uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
Steve Block44f0eee2011-05-26 01:26:41 +01008442 CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
Steve Blocka7e24c12009-10-30 11:49:00 +00008443
8444 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008445 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008446 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 6);
Steve Block44f0eee2011-05-26 01:26:41 +01008447 CHECK_EQ(5, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008448 len = str->Write(wbuf, 0, 6);
Steve Block44f0eee2011-05-26 01:26:41 +01008449 CHECK_EQ(5, len);
8450 CHECK_EQ(0, strcmp("abcde", buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008451 uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
Steve Block44f0eee2011-05-26 01:26:41 +01008452 CHECK_EQ(0, StrCmp16(answer4, wbuf));
Steve Blocka7e24c12009-10-30 11:49:00 +00008453
8454 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008455 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008456 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, -1);
Steve Block44f0eee2011-05-26 01:26:41 +01008457 CHECK_EQ(1, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008458 len = str->Write(wbuf, 4, -1);
Steve Block44f0eee2011-05-26 01:26:41 +01008459 CHECK_EQ(1, len);
8460 CHECK_EQ(0, strcmp("e", buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008461 uint16_t answer5[] = {'e', '\0'};
Steve Block44f0eee2011-05-26 01:26:41 +01008462 CHECK_EQ(0, StrCmp16(answer5, wbuf));
Steve Blocka7e24c12009-10-30 11:49:00 +00008463
8464 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008465 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008466 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 6);
Steve Block44f0eee2011-05-26 01:26:41 +01008467 CHECK_EQ(1, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008468 len = str->Write(wbuf, 4, 6);
Steve Block44f0eee2011-05-26 01:26:41 +01008469 CHECK_EQ(1, len);
8470 CHECK_EQ(0, strcmp("e", buf));
8471 CHECK_EQ(0, StrCmp16(answer5, wbuf));
Steve Blocka7e24c12009-10-30 11:49:00 +00008472
8473 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008474 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008475 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 1);
Steve Block44f0eee2011-05-26 01:26:41 +01008476 CHECK_EQ(1, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008477 len = str->Write(wbuf, 4, 1);
Steve Block44f0eee2011-05-26 01:26:41 +01008478 CHECK_EQ(1, len);
8479 CHECK_EQ(0, strncmp("e\1", buf, 2));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008480 uint16_t answer6[] = {'e', 0x101};
Steve Block44f0eee2011-05-26 01:26:41 +01008481 CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008482
8483 memset(buf, 0x1, sizeof(buf));
8484 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008485 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 3, 1);
Steve Block44f0eee2011-05-26 01:26:41 +01008486 CHECK_EQ(1, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008487 len = str->Write(wbuf, 3, 1);
Steve Block44f0eee2011-05-26 01:26:41 +01008488 CHECK_EQ(1, len);
8489 CHECK_EQ(0, strncmp("d\1", buf, 2));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008490 uint16_t answer7[] = {'d', 0x101};
Steve Block44f0eee2011-05-26 01:26:41 +01008491 CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
Ben Murdoch69a99ed2011-11-30 16:03:39 +00008492
8493 memset(wbuf, 0x1, sizeof(wbuf));
8494 wbuf[5] = 'X';
8495 len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION);
8496 CHECK_EQ(5, len);
8497 CHECK_EQ('X', wbuf[5]);
8498 uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
8499 uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
8500 CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
8501 CHECK_NE(0, StrCmp16(answer8b, wbuf));
8502 wbuf[5] = '\0';
8503 CHECK_EQ(0, StrCmp16(answer8b, wbuf));
8504
8505 memset(buf, 0x1, sizeof(buf));
8506 buf[5] = 'X';
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008507 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf),
8508 0,
8509 6,
8510 String::NO_NULL_TERMINATION);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00008511 CHECK_EQ(5, len);
8512 CHECK_EQ('X', buf[5]);
8513 CHECK_EQ(0, strncmp("abcde", buf, 5));
8514 CHECK_NE(0, strcmp("abcde", buf));
8515 buf[5] = '\0';
8516 CHECK_EQ(0, strcmp("abcde", buf));
8517
8518 memset(utf8buf, 0x1, sizeof(utf8buf));
8519 utf8buf[8] = 'X';
8520 len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
8521 String::NO_NULL_TERMINATION);
8522 CHECK_EQ(8, len);
8523 CHECK_EQ('X', utf8buf[8]);
8524 CHECK_EQ(5, charlen);
8525 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
8526 CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
8527 utf8buf[8] = '\0';
8528 CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008529
8530 memset(utf8buf, 0x1, sizeof(utf8buf));
8531 utf8buf[5] = 'X';
8532 len = str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
8533 String::NO_NULL_TERMINATION);
8534 CHECK_EQ(5, len);
8535 CHECK_EQ('X', utf8buf[5]); // Test that the sixth character is untouched.
8536 CHECK_EQ(5, charlen);
8537 utf8buf[5] = '\0';
8538 CHECK_EQ(0, strcmp(utf8buf, "abcde"));
8539
8540 memset(buf, 0x1, sizeof(buf));
8541 len = str3->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
8542 CHECK_EQ(7, len);
8543 CHECK_EQ(0, strcmp("abc", buf));
8544 CHECK_EQ(0, buf[3]);
8545 CHECK_EQ(0, strcmp("def", buf + 4));
8546
8547 CHECK_EQ(0, str->WriteOneByte(NULL, 0, 0, String::NO_NULL_TERMINATION));
8548 CHECK_EQ(0, str->WriteUtf8(NULL, 0, 0, String::NO_NULL_TERMINATION));
8549 CHECK_EQ(0, str->Write(NULL, 0, 0, String::NO_NULL_TERMINATION));
Steve Blocka7e24c12009-10-30 11:49:00 +00008550}
8551
8552
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008553static void Utf16Helper(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008554 LocalContext& context, // NOLINT
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008555 const char* name,
8556 const char* lengths_name,
8557 int len) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008558 Local<v8::Array> a = Local<v8::Array>::Cast(
8559 context->Global()->Get(context.local(), v8_str(name)).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008560 Local<v8::Array> alens =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008561 Local<v8::Array>::Cast(context->Global()
8562 ->Get(context.local(), v8_str(lengths_name))
8563 .ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008564 for (int i = 0; i < len; i++) {
8565 Local<v8::String> string =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008566 Local<v8::String>::Cast(a->Get(context.local(), i).ToLocalChecked());
8567 Local<v8::Number> expected_len = Local<v8::Number>::Cast(
8568 alens->Get(context.local(), i).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008569 int length = GetUtf8Length(string);
8570 CHECK_EQ(static_cast<int>(expected_len->Value()), length);
8571 }
8572}
8573
8574
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008575THREADED_TEST(Utf16) {
8576 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008577 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008578 CompileRun(
8579 "var pad = '01234567890123456789';"
8580 "var p = [];"
8581 "var plens = [20, 3, 3];"
8582 "p.push('01234567890123456789');"
8583 "var lead = 0xd800;"
8584 "var trail = 0xdc00;"
8585 "p.push(String.fromCharCode(0xd800));"
8586 "p.push(String.fromCharCode(0xdc00));"
8587 "var a = [];"
8588 "var b = [];"
8589 "var c = [];"
8590 "var alens = [];"
8591 "for (var i = 0; i < 3; i++) {"
8592 " p[1] = String.fromCharCode(lead++);"
8593 " for (var j = 0; j < 3; j++) {"
8594 " p[2] = String.fromCharCode(trail++);"
8595 " a.push(p[i] + p[j]);"
8596 " b.push(p[i] + p[j]);"
8597 " c.push(p[i] + p[j]);"
8598 " alens.push(plens[i] + plens[j]);"
8599 " }"
8600 "}"
8601 "alens[5] -= 2;" // Here the surrogate pairs match up.
8602 "var a2 = [];"
8603 "var b2 = [];"
8604 "var c2 = [];"
8605 "var a2lens = [];"
8606 "for (var m = 0; m < 9; m++) {"
8607 " for (var n = 0; n < 9; n++) {"
8608 " a2.push(a[m] + a[n]);"
8609 " b2.push(b[m] + b[n]);"
8610 " var newc = 'x' + c[m] + c[n] + 'y';"
8611 " c2.push(newc.substring(1, newc.length - 1));"
8612 " var utf = alens[m] + alens[n];" // And here.
8613 // The 'n's that start with 0xdc.. are 6-8
8614 // The 'm's that end with 0xd8.. are 1, 4 and 7
8615 " if ((m % 3) == 1 && n >= 6) utf -= 2;"
8616 " a2lens.push(utf);"
8617 " }"
8618 "}");
8619 Utf16Helper(context, "a", "alens", 9);
8620 Utf16Helper(context, "a2", "a2lens", 81);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008621}
8622
8623
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008624static bool SameSymbol(Local<String> s1, Local<String> s2) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008625 i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1));
8626 i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2));
8627 return *is1 == *is2;
8628}
8629
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008630
8631THREADED_TEST(Utf16Symbol) {
8632 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008633 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008634
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008635 Local<String> symbol1 =
8636 v8::String::NewFromUtf8(context->GetIsolate(), "abc",
8637 v8::NewStringType::kInternalized)
8638 .ToLocalChecked();
8639 Local<String> symbol2 =
8640 v8::String::NewFromUtf8(context->GetIsolate(), "abc",
8641 v8::NewStringType::kInternalized)
8642 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008643 CHECK(SameSymbol(symbol1, symbol2));
8644
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008645 CompileRun(
8646 "var sym0 = 'benedictus';"
8647 "var sym0b = 'S\303\270ren';"
8648 "var sym1 = '\355\240\201\355\260\207';"
8649 "var sym2 = '\360\220\220\210';"
8650 "var sym3 = 'x\355\240\201\355\260\207';"
8651 "var sym4 = 'x\360\220\220\210';"
8652 "if (sym1.length != 2) throw sym1;"
8653 "if (sym1.charCodeAt(1) != 0xdc07) throw sym1.charCodeAt(1);"
8654 "if (sym2.length != 2) throw sym2;"
8655 "if (sym2.charCodeAt(1) != 0xdc08) throw sym2.charCodeAt(2);"
8656 "if (sym3.length != 3) throw sym3;"
8657 "if (sym3.charCodeAt(2) != 0xdc07) throw sym1.charCodeAt(2);"
8658 "if (sym4.length != 3) throw sym4;"
8659 "if (sym4.charCodeAt(2) != 0xdc08) throw sym2.charCodeAt(2);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008660 Local<String> sym0 =
8661 v8::String::NewFromUtf8(context->GetIsolate(), "benedictus",
8662 v8::NewStringType::kInternalized)
8663 .ToLocalChecked();
8664 Local<String> sym0b =
8665 v8::String::NewFromUtf8(context->GetIsolate(), "S\303\270ren",
8666 v8::NewStringType::kInternalized)
8667 .ToLocalChecked();
8668 Local<String> sym1 =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008669 v8::String::NewFromUtf8(context->GetIsolate(), "\355\240\201\355\260\207",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008670 v8::NewStringType::kInternalized)
8671 .ToLocalChecked();
8672 Local<String> sym2 =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008673 v8::String::NewFromUtf8(context->GetIsolate(), "\360\220\220\210",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008674 v8::NewStringType::kInternalized)
8675 .ToLocalChecked();
8676 Local<String> sym3 = v8::String::NewFromUtf8(context->GetIsolate(),
8677 "x\355\240\201\355\260\207",
8678 v8::NewStringType::kInternalized)
8679 .ToLocalChecked();
8680 Local<String> sym4 =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008681 v8::String::NewFromUtf8(context->GetIsolate(), "x\360\220\220\210",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008682 v8::NewStringType::kInternalized)
8683 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008684 v8::Local<v8::Object> global = context->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008685 Local<Value> s0 =
8686 global->Get(context.local(), v8_str("sym0")).ToLocalChecked();
8687 Local<Value> s0b =
8688 global->Get(context.local(), v8_str("sym0b")).ToLocalChecked();
8689 Local<Value> s1 =
8690 global->Get(context.local(), v8_str("sym1")).ToLocalChecked();
8691 Local<Value> s2 =
8692 global->Get(context.local(), v8_str("sym2")).ToLocalChecked();
8693 Local<Value> s3 =
8694 global->Get(context.local(), v8_str("sym3")).ToLocalChecked();
8695 Local<Value> s4 =
8696 global->Get(context.local(), v8_str("sym4")).ToLocalChecked();
8697 CHECK(SameSymbol(sym0, Local<String>::Cast(s0)));
8698 CHECK(SameSymbol(sym0b, Local<String>::Cast(s0b)));
8699 CHECK(SameSymbol(sym1, Local<String>::Cast(s1)));
8700 CHECK(SameSymbol(sym2, Local<String>::Cast(s2)));
8701 CHECK(SameSymbol(sym3, Local<String>::Cast(s3)));
8702 CHECK(SameSymbol(sym4, Local<String>::Cast(s4)));
8703}
8704
8705
8706THREADED_TEST(Utf16MissingTrailing) {
8707 LocalContext context;
8708 v8::HandleScope scope(context->GetIsolate());
8709
8710 // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
8711 int size = 1024 * 64;
8712 uint8_t* buffer = new uint8_t[size];
8713 for (int i = 0; i < size; i += 4) {
8714 buffer[i] = 0xf0;
8715 buffer[i + 1] = 0x9d;
8716 buffer[i + 2] = 0x80;
8717 buffer[i + 3] = 0x9e;
8718 }
8719
8720 // Now invoke the decoder without last 3 bytes
8721 v8::Local<v8::String> str =
8722 v8::String::NewFromUtf8(
8723 context->GetIsolate(), reinterpret_cast<char*>(buffer),
8724 v8::NewStringType::kNormal, size - 3).ToLocalChecked();
8725 USE(str);
8726 delete[] buffer;
8727}
8728
8729
8730THREADED_TEST(Utf16Trailing3Byte) {
8731 LocalContext context;
8732 v8::HandleScope scope(context->GetIsolate());
8733
8734 // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
8735 int size = 1024 * 63;
8736 uint8_t* buffer = new uint8_t[size];
8737 for (int i = 0; i < size; i += 3) {
8738 buffer[i] = 0xe2;
8739 buffer[i + 1] = 0x80;
8740 buffer[i + 2] = 0xa6;
8741 }
8742
8743 // Now invoke the decoder without last 3 bytes
8744 v8::Local<v8::String> str =
8745 v8::String::NewFromUtf8(
8746 context->GetIsolate(), reinterpret_cast<char*>(buffer),
8747 v8::NewStringType::kNormal, size).ToLocalChecked();
8748
8749 v8::String::Value value(str);
8750 CHECK_EQ(value.length(), size / 3);
8751 CHECK_EQ((*value)[value.length() - 1], 0x2026);
8752
8753 delete[] buffer;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008754}
8755
8756
Steve Blocka7e24c12009-10-30 11:49:00 +00008757THREADED_TEST(ToArrayIndex) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008758 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008759 v8::Isolate* isolate = context->GetIsolate();
8760 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00008761
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008762 v8::Local<String> str = v8_str("42");
8763 v8::MaybeLocal<v8::Uint32> index = str->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008764 CHECK(!index.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008765 CHECK_EQ(42.0,
8766 index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008767 str = v8_str("42asdf");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008768 index = str->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008769 CHECK(index.IsEmpty());
8770 str = v8_str("-42");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008771 index = str->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008772 CHECK(index.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008773 str = v8_str("4294967294");
8774 index = str->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008775 CHECK(!index.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008776 CHECK_EQ(4294967294.0,
8777 index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
8778 v8::Local<v8::Number> num = v8::Number::New(isolate, 1);
8779 index = num->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008780 CHECK(!index.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008781 CHECK_EQ(1.0,
8782 index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008783 num = v8::Number::New(isolate, -1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008784 index = num->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008785 CHECK(index.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008786 v8::Local<v8::Object> obj = v8::Object::New(isolate);
8787 index = obj->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008788 CHECK(index.IsEmpty());
8789}
8790
8791
8792THREADED_TEST(ErrorConstruction) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008793 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008794 v8::HandleScope scope(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00008795
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008796 v8::Local<String> foo = v8_str("foo");
8797 v8::Local<String> message = v8_str("message");
8798 v8::Local<Value> range_error = v8::Exception::RangeError(foo);
Steve Blocka7e24c12009-10-30 11:49:00 +00008799 CHECK(range_error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008800 CHECK(range_error.As<v8::Object>()
8801 ->Get(context.local(), message)
8802 .ToLocalChecked()
8803 ->Equals(context.local(), foo)
8804 .FromJust());
8805 v8::Local<Value> reference_error = v8::Exception::ReferenceError(foo);
Steve Blocka7e24c12009-10-30 11:49:00 +00008806 CHECK(reference_error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008807 CHECK(reference_error.As<v8::Object>()
8808 ->Get(context.local(), message)
8809 .ToLocalChecked()
8810 ->Equals(context.local(), foo)
8811 .FromJust());
8812 v8::Local<Value> syntax_error = v8::Exception::SyntaxError(foo);
Steve Blocka7e24c12009-10-30 11:49:00 +00008813 CHECK(syntax_error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008814 CHECK(syntax_error.As<v8::Object>()
8815 ->Get(context.local(), message)
8816 .ToLocalChecked()
8817 ->Equals(context.local(), foo)
8818 .FromJust());
8819 v8::Local<Value> type_error = v8::Exception::TypeError(foo);
Steve Blocka7e24c12009-10-30 11:49:00 +00008820 CHECK(type_error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008821 CHECK(type_error.As<v8::Object>()
8822 ->Get(context.local(), message)
8823 .ToLocalChecked()
8824 ->Equals(context.local(), foo)
8825 .FromJust());
8826 v8::Local<Value> error = v8::Exception::Error(foo);
Steve Blocka7e24c12009-10-30 11:49:00 +00008827 CHECK(error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008828 CHECK(error.As<v8::Object>()
8829 ->Get(context.local(), message)
8830 .ToLocalChecked()
8831 ->Equals(context.local(), foo)
8832 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008833}
8834
8835
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008836static void ThrowV8Exception(const v8::FunctionCallbackInfo<v8::Value>& info) {
8837 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008838 v8::Local<String> foo = v8_str("foo");
8839 v8::Local<String> message = v8_str("message");
8840 v8::Local<Value> error = v8::Exception::Error(foo);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008841 CHECK(error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008842 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
8843 CHECK(error.As<v8::Object>()
8844 ->Get(context, message)
8845 .ToLocalChecked()
8846 ->Equals(context, foo)
8847 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008848 info.GetIsolate()->ThrowException(error);
8849 info.GetReturnValue().SetUndefined();
8850}
8851
8852
8853THREADED_TEST(ExceptionCreateMessage) {
8854 LocalContext context;
8855 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008856 v8::Local<String> foo_str = v8_str("foo");
8857 v8::Local<String> message_str = v8_str("message");
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008858
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008859 context->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008860
8861 Local<v8::FunctionTemplate> fun =
8862 v8::FunctionTemplate::New(context->GetIsolate(), ThrowV8Exception);
8863 v8::Local<v8::Object> global = context->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008864 CHECK(global->Set(context.local(), v8_str("throwV8Exception"),
8865 fun->GetFunction(context.local()).ToLocalChecked())
8866 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008867
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008868 TryCatch try_catch(context->GetIsolate());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008869 CompileRun(
8870 "function f1() {\n"
8871 " throwV8Exception();\n"
8872 "};\n"
8873 "f1();");
8874 CHECK(try_catch.HasCaught());
8875
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008876 v8::Local<v8::Value> error = try_catch.Exception();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008877 CHECK(error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008878 CHECK(error.As<v8::Object>()
8879 ->Get(context.local(), message_str)
8880 .ToLocalChecked()
8881 ->Equals(context.local(), foo_str)
8882 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008883
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008884 v8::Local<v8::Message> message =
8885 v8::Exception::CreateMessage(context->GetIsolate(), error);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008886 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008887 CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
8888 CHECK_EQ(2, message->GetStartColumn(context.local()).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008889
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008890 v8::Local<v8::StackTrace> stackTrace = message->GetStackTrace();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008891 CHECK(!stackTrace.IsEmpty());
8892 CHECK_EQ(2, stackTrace->GetFrameCount());
8893
8894 stackTrace = v8::Exception::GetStackTrace(error);
8895 CHECK(!stackTrace.IsEmpty());
8896 CHECK_EQ(2, stackTrace->GetFrameCount());
8897
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008898 context->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(false);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008899
8900 // Now check message location when SetCaptureStackTraceForUncaughtExceptions
8901 // is false.
8902 try_catch.Reset();
8903
8904 CompileRun(
8905 "function f2() {\n"
8906 " return throwV8Exception();\n"
8907 "};\n"
8908 "f2();");
8909 CHECK(try_catch.HasCaught());
8910
8911 error = try_catch.Exception();
8912 CHECK(error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008913 CHECK(error.As<v8::Object>()
8914 ->Get(context.local(), message_str)
8915 .ToLocalChecked()
8916 ->Equals(context.local(), foo_str)
8917 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008918
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008919 message = v8::Exception::CreateMessage(context->GetIsolate(), error);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008920 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008921 CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
8922 CHECK_EQ(9, message->GetStartColumn(context.local()).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008923
8924 // Should be empty stack trace.
8925 stackTrace = message->GetStackTrace();
8926 CHECK(stackTrace.IsEmpty());
8927 CHECK(v8::Exception::GetStackTrace(error).IsEmpty());
8928}
8929
8930
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008931THREADED_TEST(ExceptionCreateMessageLength) {
8932 LocalContext context;
8933 v8::HandleScope scope(context->GetIsolate());
8934
8935 // Test that the message is not truncated.
8936 TryCatch try_catch(context->GetIsolate());
8937 CompileRun(
8938 "var message = 'm';"
8939 "while (message.length < 1000) message += message;"
8940 "throw message;");
8941 CHECK(try_catch.HasCaught());
8942
8943 CHECK_LT(1000, try_catch.Message()->Get()->Length());
8944}
8945
8946
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008947static void YGetter(Local<String> name,
8948 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008949 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008950 info.GetReturnValue().Set(v8_num(10));
Steve Blocka7e24c12009-10-30 11:49:00 +00008951}
8952
8953
8954static void YSetter(Local<String> name,
8955 Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008956 const v8::PropertyCallbackInfo<void>& info) {
8957 Local<Object> this_obj = Local<Object>::Cast(info.This());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008958 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
8959 if (this_obj->Has(context, name).FromJust())
8960 this_obj->Delete(context, name).FromJust();
8961 CHECK(this_obj->Set(context, name, value).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008962}
8963
8964
8965THREADED_TEST(DeleteAccessor) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008966 v8::Isolate* isolate = CcTest::isolate();
8967 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008968 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00008969 obj->SetAccessor(v8_str("y"), YGetter, YSetter);
8970 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008971 v8::Local<v8::Object> holder =
8972 obj->NewInstance(context.local()).ToLocalChecked();
8973 CHECK(context->Global()
8974 ->Set(context.local(), v8_str("holder"), holder)
8975 .FromJust());
8976 v8::Local<Value> result =
8977 CompileRun("holder.y = 11; holder.y = 12; holder.y");
8978 CHECK_EQ(12u, result->Uint32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008979}
8980
8981
Steve Blocka7e24c12009-10-30 11:49:00 +00008982static int trouble_nesting = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008983static void TroubleCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008984 ApiTestFuzzer::Fuzz();
8985 trouble_nesting++;
8986
8987 // Call a JS function that throws an uncaught exception.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008988 Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
8989 Local<v8::Object> arg_this = context->Global();
8990 Local<Value> trouble_callee =
8991 (trouble_nesting == 3)
8992 ? arg_this->Get(context, v8_str("trouble_callee")).ToLocalChecked()
8993 : arg_this->Get(context, v8_str("trouble_caller")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00008994 CHECK(trouble_callee->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008995 args.GetReturnValue().Set(Function::Cast(*trouble_callee)
8996 ->Call(context, arg_this, 0, NULL)
8997 .FromMaybe(v8::Local<v8::Value>()));
Steve Blocka7e24c12009-10-30 11:49:00 +00008998}
8999
9000
9001static int report_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009002static void ApiUncaughtExceptionTestListener(v8::Local<v8::Message>,
9003 v8::Local<Value>) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009004 report_count++;
9005}
9006
9007
9008// Counts uncaught exceptions, but other tests running in parallel
9009// also have uncaught exceptions.
9010TEST(ApiUncaughtException) {
9011 report_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00009012 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009013 v8::Isolate* isolate = env->GetIsolate();
9014 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009015 isolate->AddMessageListener(ApiUncaughtExceptionTestListener);
Steve Blocka7e24c12009-10-30 11:49:00 +00009016
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009017 Local<v8::FunctionTemplate> fun =
9018 v8::FunctionTemplate::New(isolate, TroubleCallback);
Steve Blocka7e24c12009-10-30 11:49:00 +00009019 v8::Local<v8::Object> global = env->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009020 CHECK(global->Set(env.local(), v8_str("trouble"),
9021 fun->GetFunction(env.local()).ToLocalChecked())
9022 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009023
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009024 CompileRun(
9025 "function trouble_callee() {"
9026 " var x = null;"
9027 " return x.foo;"
9028 "};"
9029 "function trouble_caller() {"
9030 " trouble();"
9031 "};");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009032 Local<Value> trouble =
9033 global->Get(env.local(), v8_str("trouble")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009034 CHECK(trouble->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009035 Local<Value> trouble_callee =
9036 global->Get(env.local(), v8_str("trouble_callee")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009037 CHECK(trouble_callee->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009038 Local<Value> trouble_caller =
9039 global->Get(env.local(), v8_str("trouble_caller")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009040 CHECK(trouble_caller->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009041 Function::Cast(*trouble_caller)
9042 ->Call(env.local(), global, 0, NULL)
9043 .FromMaybe(v8::Local<v8::Value>());
Steve Blocka7e24c12009-10-30 11:49:00 +00009044 CHECK_EQ(1, report_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009045 isolate->RemoveMessageListeners(ApiUncaughtExceptionTestListener);
Steve Blocka7e24c12009-10-30 11:49:00 +00009046}
9047
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009048
9049TEST(ApiUncaughtExceptionInObjectObserve) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009050 v8::internal::FLAG_harmony_object_observe = true;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009051 v8::internal::FLAG_stack_size = 150;
9052 report_count = 0;
9053 LocalContext env;
9054 v8::Isolate* isolate = env->GetIsolate();
9055 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009056 isolate->AddMessageListener(ApiUncaughtExceptionTestListener);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009057 CompileRun(
9058 "var obj = {};"
9059 "var observe_count = 0;"
9060 "function observer1() { ++observe_count; };"
9061 "function observer2() { ++observe_count; };"
9062 "function observer_throws() { throw new Error(); };"
9063 "function stack_overflow() { return (function f(x) { f(x+1); })(0); };"
9064 "Object.observe(obj, observer_throws.bind());"
9065 "Object.observe(obj, observer1);"
9066 "Object.observe(obj, stack_overflow);"
9067 "Object.observe(obj, observer2);"
9068 "Object.observe(obj, observer_throws.bind());"
9069 "obj.foo = 'bar';");
9070 CHECK_EQ(3, report_count);
9071 ExpectInt32("observe_count", 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009072 isolate->RemoveMessageListeners(ApiUncaughtExceptionTestListener);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009073}
9074
9075
Leon Clarke4515c472010-02-03 11:58:03 +00009076static const char* script_resource_name = "ExceptionInNativeScript.js";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009077static void ExceptionInNativeScriptTestListener(v8::Local<v8::Message> message,
9078 v8::Local<Value>) {
9079 v8::Local<v8::Value> name_val = message->GetScriptOrigin().ResourceName();
Leon Clarke4515c472010-02-03 11:58:03 +00009080 CHECK(!name_val.IsEmpty() && name_val->IsString());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009081 v8::String::Utf8Value name(message->GetScriptOrigin().ResourceName());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009082 CHECK_EQ(0, strcmp(script_resource_name, *name));
9083 v8::Local<v8::Context> context =
9084 v8::Isolate::GetCurrent()->GetCurrentContext();
9085 CHECK_EQ(3, message->GetLineNumber(context).FromJust());
9086 v8::String::Utf8Value source_line(
9087 message->GetSourceLine(context).ToLocalChecked());
9088 CHECK_EQ(0, strcmp(" new o.foo();", *source_line));
Leon Clarke4515c472010-02-03 11:58:03 +00009089}
9090
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009091
Leon Clarke4515c472010-02-03 11:58:03 +00009092TEST(ExceptionInNativeScript) {
Leon Clarke4515c472010-02-03 11:58:03 +00009093 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009094 v8::Isolate* isolate = env->GetIsolate();
9095 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009096 isolate->AddMessageListener(ExceptionInNativeScriptTestListener);
Leon Clarke4515c472010-02-03 11:58:03 +00009097
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009098 Local<v8::FunctionTemplate> fun =
9099 v8::FunctionTemplate::New(isolate, TroubleCallback);
Leon Clarke4515c472010-02-03 11:58:03 +00009100 v8::Local<v8::Object> global = env->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009101 CHECK(global->Set(env.local(), v8_str("trouble"),
9102 fun->GetFunction(env.local()).ToLocalChecked())
9103 .FromJust());
Leon Clarke4515c472010-02-03 11:58:03 +00009104
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009105 CompileRunWithOrigin(
9106 "function trouble() {\n"
9107 " var o = {};\n"
9108 " new o.foo();\n"
9109 "};",
9110 script_resource_name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009111 Local<Value> trouble =
9112 global->Get(env.local(), v8_str("trouble")).ToLocalChecked();
Leon Clarke4515c472010-02-03 11:58:03 +00009113 CHECK(trouble->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009114 CHECK(Function::Cast(*trouble)->Call(env.local(), global, 0, NULL).IsEmpty());
9115 isolate->RemoveMessageListeners(ExceptionInNativeScriptTestListener);
Leon Clarke4515c472010-02-03 11:58:03 +00009116}
9117
Steve Blocka7e24c12009-10-30 11:49:00 +00009118
9119TEST(CompilationErrorUsingTryCatchHandler) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009120 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009121 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009122 v8::TryCatch try_catch(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009123 v8_compile("This doesn't &*&@#$&*^ compile.");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009124 CHECK(*try_catch.Exception());
Steve Blocka7e24c12009-10-30 11:49:00 +00009125 CHECK(try_catch.HasCaught());
9126}
9127
9128
9129TEST(TryCatchFinallyUsingTryCatchHandler) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009130 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009131 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009132 v8::TryCatch try_catch(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009133 CompileRun("try { throw ''; } catch (e) {}");
Steve Blocka7e24c12009-10-30 11:49:00 +00009134 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009135 CompileRun("try { throw ''; } finally {}");
Steve Blocka7e24c12009-10-30 11:49:00 +00009136 CHECK(try_catch.HasCaught());
9137 try_catch.Reset();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009138 CompileRun(
9139 "(function() {"
9140 "try { throw ''; } finally { return; }"
9141 "})()");
Steve Blocka7e24c12009-10-30 11:49:00 +00009142 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009143 CompileRun(
9144 "(function()"
9145 " { try { throw ''; } finally { throw 0; }"
9146 "})()");
Steve Blocka7e24c12009-10-30 11:49:00 +00009147 CHECK(try_catch.HasCaught());
9148}
9149
9150
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009151void CEvaluate(const v8::FunctionCallbackInfo<v8::Value>& args) {
9152 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009153 CompileRun(args[0]
9154 ->ToString(args.GetIsolate()->GetCurrentContext())
9155 .ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009156}
9157
9158
9159TEST(TryCatchFinallyStoresMessageUsingTryCatchHandler) {
9160 v8::Isolate* isolate = CcTest::isolate();
9161 v8::HandleScope scope(isolate);
9162 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
9163 templ->Set(v8_str("CEvaluate"),
9164 v8::FunctionTemplate::New(isolate, CEvaluate));
9165 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009166 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009167 CompileRun("try {"
9168 " CEvaluate('throw 1;');"
9169 "} finally {"
9170 "}");
9171 CHECK(try_catch.HasCaught());
9172 CHECK(!try_catch.Message().IsEmpty());
9173 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009174 CHECK_EQ(0, strcmp(*exception_value, "1"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009175 try_catch.Reset();
9176 CompileRun("try {"
9177 " CEvaluate('throw 1;');"
9178 "} finally {"
9179 " throw 2;"
9180 "}");
9181 CHECK(try_catch.HasCaught());
9182 CHECK(!try_catch.Message().IsEmpty());
9183 String::Utf8Value finally_exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009184 CHECK_EQ(0, strcmp(*finally_exception_value, "2"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009185}
9186
9187
9188// For use within the TestSecurityHandler() test.
9189static bool g_security_callback_result = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009190static bool SecurityTestCallback(Local<v8::Context> accessing_context,
Ben Murdoch097c5b22016-05-18 11:27:45 +01009191 Local<v8::Object> accessed_object,
9192 Local<v8::Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009193 printf("a\n");
Ben Murdoch097c5b22016-05-18 11:27:45 +01009194 CHECK(!data.IsEmpty() && data->IsInt32());
9195 CHECK_EQ(42, data->Int32Value(accessing_context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009196 return g_security_callback_result;
9197}
9198
9199
Steve Blocka7e24c12009-10-30 11:49:00 +00009200// SecurityHandler can't be run twice
9201TEST(SecurityHandler) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009202 v8::Isolate* isolate = CcTest::isolate();
9203 v8::HandleScope scope0(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009204 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009205 v8::ObjectTemplate::New(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01009206 global_template->SetAccessCheckCallback(SecurityTestCallback, v8_num(42));
Steve Blocka7e24c12009-10-30 11:49:00 +00009207 // Create an environment
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009208 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
Steve Blocka7e24c12009-10-30 11:49:00 +00009209 context0->Enter();
9210
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009211 v8::Local<v8::Object> global0 = context0->Global();
9212 v8::Local<Script> script0 = v8_compile("foo = 111");
9213 script0->Run(context0).ToLocalChecked();
9214 CHECK(global0->Set(context0, v8_str("0"), v8_num(999)).FromJust());
9215 v8::Local<Value> foo0 =
9216 global0->Get(context0, v8_str("foo")).ToLocalChecked();
9217 CHECK_EQ(111, foo0->Int32Value(context0).FromJust());
9218 v8::Local<Value> z0 = global0->Get(context0, v8_str("0")).ToLocalChecked();
9219 CHECK_EQ(999, z0->Int32Value(context0).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009220
9221 // Create another environment, should fail security checks.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009222 v8::HandleScope scope1(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00009223
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009224 v8::Local<Context> context1 = Context::New(isolate, NULL, global_template);
Steve Blocka7e24c12009-10-30 11:49:00 +00009225 context1->Enter();
9226
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009227 v8::Local<v8::Object> global1 = context1->Global();
9228 global1->Set(context1, v8_str("othercontext"), global0).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00009229 // This set will fail the security check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009230 v8::Local<Script> script1 =
9231 v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
9232 CHECK(script1->Run(context1).IsEmpty());
9233 g_security_callback_result = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00009234 // This read will pass the security check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009235 v8::Local<Value> foo1 =
9236 global0->Get(context1, v8_str("foo")).ToLocalChecked();
9237 CHECK_EQ(111, foo1->Int32Value(context0).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009238 // This read will pass the security check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009239 v8::Local<Value> z1 = global0->Get(context1, v8_str("0")).ToLocalChecked();
9240 CHECK_EQ(999, z1->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009241
9242 // Create another environment, should pass security checks.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009243 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009244 v8::HandleScope scope2(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00009245 LocalContext context2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009246 v8::Local<v8::Object> global2 = context2->Global();
9247 CHECK(global2->Set(context2.local(), v8_str("othercontext"), global0)
9248 .FromJust());
9249 v8::Local<Script> script2 =
Steve Blocka7e24c12009-10-30 11:49:00 +00009250 v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009251 script2->Run(context2.local()).ToLocalChecked();
9252 v8::Local<Value> foo2 =
9253 global0->Get(context2.local(), v8_str("foo")).ToLocalChecked();
9254 CHECK_EQ(333, foo2->Int32Value(context2.local()).FromJust());
9255 v8::Local<Value> z2 =
9256 global0->Get(context2.local(), v8_str("0")).ToLocalChecked();
9257 CHECK_EQ(888, z2->Int32Value(context2.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009258 }
9259
9260 context1->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +00009261 context0->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +00009262}
9263
9264
9265THREADED_TEST(SecurityChecks) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009266 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009267 v8::HandleScope handle_scope(env1->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009268 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009269
9270 Local<Value> foo = v8_str("foo");
9271 Local<Value> bar = v8_str("bar");
9272
9273 // Set to the same domain.
9274 env1->SetSecurityToken(foo);
9275
9276 // Create a function in env1.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009277 CompileRun("spy=function(){return spy;}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009278 Local<Value> spy =
9279 env1->Global()->Get(env1.local(), v8_str("spy")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009280 CHECK(spy->IsFunction());
9281
9282 // Create another function accessing global objects.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009283 CompileRun("spy2=function(){return new this.Array();}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009284 Local<Value> spy2 =
9285 env1->Global()->Get(env1.local(), v8_str("spy2")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009286 CHECK(spy2->IsFunction());
9287
9288 // Switch to env2 in the same domain and invoke spy on env2.
9289 {
9290 env2->SetSecurityToken(foo);
9291 // Enter env2
9292 Context::Scope scope_env2(env2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009293 Local<Value> result = Function::Cast(*spy)
9294 ->Call(env2, env2->Global(), 0, NULL)
9295 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009296 CHECK(result->IsFunction());
9297 }
9298
9299 {
9300 env2->SetSecurityToken(bar);
9301 Context::Scope scope_env2(env2);
9302
9303 // Call cross_domain_call, it should throw an exception
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009304 v8::TryCatch try_catch(env1->GetIsolate());
9305 CHECK(Function::Cast(*spy2)->Call(env2, env2->Global(), 0, NULL).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009306 CHECK(try_catch.HasCaught());
9307 }
Steve Blocka7e24c12009-10-30 11:49:00 +00009308}
9309
9310
9311// Regression test case for issue 1183439.
9312THREADED_TEST(SecurityChecksForPrototypeChain) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009313 LocalContext current;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009314 v8::HandleScope scope(current->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009315 v8::Local<Context> other = Context::New(current->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009316
9317 // Change context to be able to get to the Object function in the
9318 // other context without hitting the security checks.
9319 v8::Local<Value> other_object;
9320 { Context::Scope scope(other);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009321 other_object =
9322 other->Global()->Get(other, v8_str("Object")).ToLocalChecked();
9323 CHECK(other->Global()->Set(other, v8_num(42), v8_num(87)).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009324 }
9325
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009326 CHECK(current->Global()
9327 ->Set(current.local(), v8_str("other"), other->Global())
9328 .FromJust());
9329 CHECK(v8_compile("other")
9330 ->Run(current.local())
9331 .ToLocalChecked()
9332 ->Equals(current.local(), other->Global())
9333 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009334
9335 // Make sure the security check fails here and we get an undefined
9336 // result instead of getting the Object function. Repeat in a loop
9337 // to make sure to exercise the IC code.
9338 v8::Local<Script> access_other0 = v8_compile("other.Object");
9339 v8::Local<Script> access_other1 = v8_compile("other[42]");
9340 for (int i = 0; i < 5; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009341 CHECK(access_other0->Run(current.local()).IsEmpty());
9342 CHECK(access_other1->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009343 }
9344
9345 // Create an object that has 'other' in its prototype chain and make
9346 // sure we cannot access the Object function indirectly through
9347 // that. Repeat in a loop to make sure to exercise the IC code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009348 v8_compile(
9349 "function F() { };"
9350 "F.prototype = other;"
9351 "var f = new F();")
9352 ->Run(current.local())
9353 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009354 v8::Local<Script> access_f0 = v8_compile("f.Object");
9355 v8::Local<Script> access_f1 = v8_compile("f[42]");
9356 for (int j = 0; j < 5; j++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009357 CHECK(access_f0->Run(current.local()).IsEmpty());
9358 CHECK(access_f1->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009359 }
9360
9361 // Now it gets hairy: Set the prototype for the other global object
9362 // to be the current global object. The prototype chain for 'f' now
9363 // goes through 'other' but ends up in the current global object.
9364 { Context::Scope scope(other);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009365 CHECK(other->Global()
9366 ->Set(other, v8_str("__proto__"), current->Global())
9367 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009368 }
9369 // Set a named and an index property on the current global
9370 // object. To force the lookup to go through the other global object,
9371 // the properties must not exist in the other global object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009372 CHECK(current->Global()
9373 ->Set(current.local(), v8_str("foo"), v8_num(100))
9374 .FromJust());
9375 CHECK(current->Global()
9376 ->Set(current.local(), v8_num(99), v8_num(101))
9377 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009378 // Try to read the properties from f and make sure that the access
9379 // gets stopped by the security checks on the other global object.
9380 Local<Script> access_f2 = v8_compile("f.foo");
9381 Local<Script> access_f3 = v8_compile("f[99]");
9382 for (int k = 0; k < 5; k++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009383 CHECK(access_f2->Run(current.local()).IsEmpty());
9384 CHECK(access_f3->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009385 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009386}
9387
9388
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009389static bool security_check_with_gc_called;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009390
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009391static bool SecurityTestCallbackWithGC(Local<v8::Context> accessing_context,
Ben Murdoch097c5b22016-05-18 11:27:45 +01009392 Local<v8::Object> accessed_object,
9393 Local<v8::Value> data) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009394 CcTest::heap()->CollectAllGarbage();
9395 security_check_with_gc_called = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009396 return true;
9397}
9398
9399
9400TEST(SecurityTestGCAllowed) {
9401 v8::Isolate* isolate = CcTest::isolate();
9402 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009403 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009404 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009405 object_template->SetAccessCheckCallback(SecurityTestCallbackWithGC);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009406
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009407 v8::Local<Context> context = Context::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009408 v8::Context::Scope context_scope(context);
9409
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009410 CHECK(context->Global()
9411 ->Set(context, v8_str("obj"),
9412 object_template->NewInstance(context).ToLocalChecked())
9413 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009414
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009415 security_check_with_gc_called = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009416 CompileRun("obj[0] = new String(1002);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009417 CHECK(security_check_with_gc_called);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009418
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009419 security_check_with_gc_called = false;
9420 CHECK(CompileRun("obj[0]")
9421 ->ToString(context)
9422 .ToLocalChecked()
9423 ->Equals(context, v8_str("1002"))
9424 .FromJust());
9425 CHECK(security_check_with_gc_called);
Steve Blocka7e24c12009-10-30 11:49:00 +00009426}
9427
9428
9429THREADED_TEST(CrossDomainDelete) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009430 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009431 v8::HandleScope handle_scope(env1->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009432 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009433
9434 Local<Value> foo = v8_str("foo");
9435 Local<Value> bar = v8_str("bar");
9436
9437 // Set to the same domain.
9438 env1->SetSecurityToken(foo);
9439 env2->SetSecurityToken(foo);
9440
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009441 CHECK(
9442 env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
9443 CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009444
9445 // Change env2 to a different domain and delete env1.prop.
9446 env2->SetSecurityToken(bar);
9447 {
9448 Context::Scope scope_env2(env2);
9449 Local<Value> result =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009450 CompileRun("delete env1.prop");
9451 CHECK(result.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009452 }
9453
9454 // Check that env1.prop still exists.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009455 Local<Value> v =
9456 env1->Global()->Get(env1.local(), v8_str("prop")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009457 CHECK(v->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009458 CHECK_EQ(3, v->Int32Value(env1.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009459}
9460
9461
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009462THREADED_TEST(CrossDomainPropertyIsEnumerable) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009463 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009464 v8::HandleScope handle_scope(env1->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009465 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009466
9467 Local<Value> foo = v8_str("foo");
9468 Local<Value> bar = v8_str("bar");
9469
9470 // Set to the same domain.
9471 env1->SetSecurityToken(foo);
9472 env2->SetSecurityToken(foo);
9473
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009474 CHECK(
9475 env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
9476 CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009477
9478 // env1.prop is enumerable in env2.
9479 Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
9480 {
9481 Context::Scope scope_env2(env2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009482 Local<Value> result = CompileRun(test);
Steve Blocka7e24c12009-10-30 11:49:00 +00009483 CHECK(result->IsTrue());
9484 }
9485
9486 // Change env2 to a different domain and test again.
9487 env2->SetSecurityToken(bar);
9488 {
9489 Context::Scope scope_env2(env2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009490 Local<Value> result = CompileRun(test);
9491 CHECK(result.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009492 }
Steve Blocka7e24c12009-10-30 11:49:00 +00009493}
9494
9495
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009496THREADED_TEST(CrossDomainFor) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009497 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009498 v8::HandleScope handle_scope(env1->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009499 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009500
9501 Local<Value> foo = v8_str("foo");
9502 Local<Value> bar = v8_str("bar");
9503
9504 // Set to the same domain.
9505 env1->SetSecurityToken(foo);
9506 env2->SetSecurityToken(foo);
9507
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009508 CHECK(
9509 env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
9510 CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
9511
9512 // Change env2 to a different domain and set env1's global object
9513 // as the __proto__ of an object in env2 and enumerate properties
9514 // in for-in. It shouldn't enumerate properties on env1's global
9515 // object. It shouldn't throw either, just silently ignore them.
9516 env2->SetSecurityToken(bar);
9517 {
9518 Context::Scope scope_env2(env2);
9519 Local<Value> result = CompileRun(
9520 "(function() {"
9521 " try {"
9522 " for (var p in env1) {"
9523 " if (p == 'prop') return false;"
9524 " }"
9525 " return true;"
9526 " } catch (e) {"
9527 " return false;"
9528 " }"
9529 "})()");
9530 CHECK(result->IsTrue());
9531 }
9532}
9533
9534
9535THREADED_TEST(CrossDomainForInOnPrototype) {
9536 LocalContext env1;
9537 v8::HandleScope handle_scope(env1->GetIsolate());
9538 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
9539
9540 Local<Value> foo = v8_str("foo");
9541 Local<Value> bar = v8_str("bar");
9542
9543 // Set to the same domain.
9544 env1->SetSecurityToken(foo);
9545 env2->SetSecurityToken(foo);
9546
9547 CHECK(
9548 env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
9549 CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009550
9551 // Change env2 to a different domain and set env1's global object
9552 // as the __proto__ of an object in env2 and enumerate properties
9553 // in for-in. It shouldn't enumerate properties on env1's global
9554 // object.
9555 env2->SetSecurityToken(bar);
9556 {
9557 Context::Scope scope_env2(env2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009558 Local<Value> result = CompileRun(
9559 "(function() {"
9560 " var obj = { '__proto__': env1 };"
9561 " try {"
9562 " for (var p in obj) {"
9563 " if (p == 'prop') return false;"
9564 " }"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009565 " return true;"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009566 " } catch (e) {"
9567 " return false;"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009568 " }"
9569 "})()");
Steve Blocka7e24c12009-10-30 11:49:00 +00009570 CHECK(result->IsTrue());
9571 }
Steve Blocka7e24c12009-10-30 11:49:00 +00009572}
9573
9574
9575TEST(ContextDetachGlobal) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009576 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009577 v8::HandleScope handle_scope(env1->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009578 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009579
Steve Blocka7e24c12009-10-30 11:49:00 +00009580
9581 Local<Value> foo = v8_str("foo");
9582
9583 // Set to the same domain.
9584 env1->SetSecurityToken(foo);
9585 env2->SetSecurityToken(foo);
9586
9587 // Enter env2
9588 env2->Enter();
9589
Andrei Popescu74b3c142010-03-29 12:03:09 +01009590 // Create a function in env2 and add a reference to it in env1.
Steve Blocka7e24c12009-10-30 11:49:00 +00009591 Local<v8::Object> global2 = env2->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009592 CHECK(global2->Set(env2, v8_str("prop"),
9593 v8::Integer::New(env2->GetIsolate(), 1))
9594 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009595 CompileRun("function getProp() {return prop;}");
9596
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009597 CHECK(env1->Global()
9598 ->Set(env1.local(), v8_str("getProp"),
9599 global2->Get(env2, v8_str("getProp")).ToLocalChecked())
9600 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009601
Andrei Popescu74b3c142010-03-29 12:03:09 +01009602 // Detach env2's global, and reuse the global object of env2
Steve Blocka7e24c12009-10-30 11:49:00 +00009603 env2->Exit();
9604 env2->DetachGlobal();
Steve Blocka7e24c12009-10-30 11:49:00 +00009605
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009606 v8::Local<Context> env3 = Context::New(
9607 env1->GetIsolate(), 0, v8::Local<v8::ObjectTemplate>(), global2);
Steve Blocka7e24c12009-10-30 11:49:00 +00009608 env3->SetSecurityToken(v8_str("bar"));
Steve Blocka7e24c12009-10-30 11:49:00 +00009609
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009610 env3->Enter();
Steve Blocka7e24c12009-10-30 11:49:00 +00009611 Local<v8::Object> global3 = env3->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009612 CHECK(global2->Equals(env3, global3).FromJust());
9613 CHECK(global3->Get(env3, v8_str("prop")).ToLocalChecked()->IsUndefined());
9614 CHECK(global3->Get(env3, v8_str("getProp")).ToLocalChecked()->IsUndefined());
9615 CHECK(global3->Set(env3, v8_str("prop"),
9616 v8::Integer::New(env3->GetIsolate(), -1))
9617 .FromJust());
9618 CHECK(global3->Set(env3, v8_str("prop2"),
9619 v8::Integer::New(env3->GetIsolate(), 2))
9620 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009621 env3->Exit();
9622
9623 // Call getProp in env1, and it should return the value 1
9624 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009625 Local<v8::Object> global1 = env1->Global();
9626 Local<Value> get_prop =
9627 global1->Get(env1.local(), v8_str("getProp")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009628 CHECK(get_prop->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009629 v8::TryCatch try_catch(env1->GetIsolate());
9630 Local<Value> r = Function::Cast(*get_prop)
9631 ->Call(env1.local(), global1, 0, NULL)
9632 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009633 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009634 CHECK_EQ(1, r->Int32Value(env1.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009635 }
9636
9637 // Check that env3 is not accessible from env1
9638 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009639 v8::MaybeLocal<Value> r = global3->Get(env1.local(), v8_str("prop2"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009640 CHECK(r.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009641 }
Steve Blocka7e24c12009-10-30 11:49:00 +00009642}
9643
9644
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009645TEST(DetachGlobal) {
Andrei Popescu74b3c142010-03-29 12:03:09 +01009646 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009647 v8::HandleScope scope(env1->GetIsolate());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009648
9649 // Create second environment.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009650 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009651
9652 Local<Value> foo = v8_str("foo");
9653
9654 // Set same security token for env1 and env2.
9655 env1->SetSecurityToken(foo);
9656 env2->SetSecurityToken(foo);
9657
9658 // Create a property on the global object in env2.
9659 {
9660 v8::Context::Scope scope(env2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009661 CHECK(env2->Global()
9662 ->Set(env2, v8_str("p"), v8::Integer::New(env2->GetIsolate(), 42))
9663 .FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009664 }
9665
9666 // Create a reference to env2 global from env1 global.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009667 CHECK(env1->Global()
9668 ->Set(env1.local(), v8_str("other"), env2->Global())
9669 .FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009670
9671 // Check that we have access to other.p in env2 from env1.
9672 Local<Value> result = CompileRun("other.p");
9673 CHECK(result->IsInt32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009674 CHECK_EQ(42, result->Int32Value(env1.local()).FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009675
9676 // Hold on to global from env2 and detach global from env2.
9677 Local<v8::Object> global2 = env2->Global();
9678 env2->DetachGlobal();
9679
9680 // Check that the global has been detached. No other.p property can
9681 // be found.
9682 result = CompileRun("other.p");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009683 CHECK(result.IsEmpty());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009684
9685 // Reuse global2 for env3.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009686 v8::Local<Context> env3 = Context::New(
9687 env1->GetIsolate(), 0, v8::Local<v8::ObjectTemplate>(), global2);
9688 CHECK(global2->Equals(env1.local(), env3->Global()).FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009689
9690 // Start by using the same security token for env3 as for env1 and env2.
9691 env3->SetSecurityToken(foo);
9692
9693 // Create a property on the global object in env3.
9694 {
9695 v8::Context::Scope scope(env3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009696 CHECK(env3->Global()
9697 ->Set(env3, v8_str("p"), v8::Integer::New(env3->GetIsolate(), 24))
9698 .FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009699 }
9700
9701 // Check that other.p is now the property in env3 and that we have access.
9702 result = CompileRun("other.p");
9703 CHECK(result->IsInt32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009704 CHECK_EQ(24, result->Int32Value(env3).FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009705
9706 // Change security token for env3 to something different from env1 and env2.
9707 env3->SetSecurityToken(v8_str("bar"));
9708
9709 // Check that we do not have access to other.p in env1. |other| is now
9710 // the global object for env3 which has a different security token,
9711 // so access should be blocked.
9712 result = CompileRun("other.p");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009713 CHECK(result.IsEmpty());
9714}
Andrei Popescu74b3c142010-03-29 12:03:09 +01009715
Andrei Popescu74b3c142010-03-29 12:03:09 +01009716
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009717void GetThisX(const v8::FunctionCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009718 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009719 info.GetReturnValue().Set(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009720 context->Global()->Get(context, v8_str("x")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009721}
Andrei Popescu74b3c142010-03-29 12:03:09 +01009722
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009723
9724TEST(DetachedAccesses) {
9725 LocalContext env1;
9726 v8::HandleScope scope(env1->GetIsolate());
9727
9728 // Create second environment.
9729 Local<ObjectTemplate> inner_global_template =
9730 FunctionTemplate::New(env1->GetIsolate())->InstanceTemplate();
9731 inner_global_template ->SetAccessorProperty(
9732 v8_str("this_x"), FunctionTemplate::New(env1->GetIsolate(), GetThisX));
9733 v8::Local<Context> env2 =
9734 Context::New(env1->GetIsolate(), NULL, inner_global_template);
9735
9736 Local<Value> foo = v8_str("foo");
9737
9738 // Set same security token for env1 and env2.
9739 env1->SetSecurityToken(foo);
9740 env2->SetSecurityToken(foo);
9741
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009742 CHECK(env1->Global()
9743 ->Set(env1.local(), v8_str("x"), v8_str("env1_x"))
9744 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009745
9746 {
9747 v8::Context::Scope scope(env2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009748 CHECK(env2->Global()->Set(env2, v8_str("x"), v8_str("env2_x")).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009749 CompileRun(
9750 "function bound_x() { return x; }"
9751 "function get_x() { return this.x; }"
9752 "function get_x_w() { return (function() {return this.x;})(); }");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009753 CHECK(env1->Global()
9754 ->Set(env1.local(), v8_str("bound_x"), CompileRun("bound_x"))
9755 .FromJust());
9756 CHECK(env1->Global()
9757 ->Set(env1.local(), v8_str("get_x"), CompileRun("get_x"))
9758 .FromJust());
9759 CHECK(env1->Global()
9760 ->Set(env1.local(), v8_str("get_x_w"), CompileRun("get_x_w"))
9761 .FromJust());
9762 env1->Global()
9763 ->Set(env1.local(), v8_str("this_x"),
9764 CompileRun("Object.getOwnPropertyDescriptor(this, 'this_x').get"))
9765 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009766 }
9767
9768 Local<Object> env2_global = env2->Global();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009769 env2->DetachGlobal();
9770
9771 Local<Value> result;
9772 result = CompileRun("bound_x()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009773 CHECK(v8_str("env2_x")->Equals(env1.local(), result).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009774 result = CompileRun("get_x()");
9775 CHECK(result.IsEmpty());
9776 result = CompileRun("get_x_w()");
9777 CHECK(result.IsEmpty());
9778 result = CompileRun("this_x()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009779 CHECK(v8_str("env2_x")->Equals(env1.local(), result).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009780
9781 // Reattach env2's proxy
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009782 env2 = Context::New(env1->GetIsolate(), 0, v8::Local<v8::ObjectTemplate>(),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009783 env2_global);
9784 env2->SetSecurityToken(foo);
9785 {
9786 v8::Context::Scope scope(env2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009787 CHECK(env2->Global()->Set(env2, v8_str("x"), v8_str("env3_x")).FromJust());
9788 CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009789 result = CompileRun(
9790 "results = [];"
9791 "for (var i = 0; i < 4; i++ ) {"
9792 " results.push(env1.bound_x());"
9793 " results.push(env1.get_x());"
9794 " results.push(env1.get_x_w());"
9795 " results.push(env1.this_x());"
9796 "}"
9797 "results");
9798 Local<v8::Array> results = Local<v8::Array>::Cast(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009799 CHECK_EQ(16u, results->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009800 for (int i = 0; i < 16; i += 4) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009801 CHECK(v8_str("env2_x")
9802 ->Equals(env2, results->Get(env2, i + 0).ToLocalChecked())
9803 .FromJust());
9804 CHECK(v8_str("env1_x")
9805 ->Equals(env2, results->Get(env2, i + 1).ToLocalChecked())
9806 .FromJust());
9807 CHECK(v8_str("env3_x")
9808 ->Equals(env2, results->Get(env2, i + 2).ToLocalChecked())
9809 .FromJust());
9810 CHECK(v8_str("env2_x")
9811 ->Equals(env2, results->Get(env2, i + 3).ToLocalChecked())
9812 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009813 }
9814 }
9815
9816 result = CompileRun(
9817 "results = [];"
9818 "for (var i = 0; i < 4; i++ ) {"
9819 " results.push(bound_x());"
9820 " results.push(get_x());"
9821 " results.push(get_x_w());"
9822 " results.push(this_x());"
9823 "}"
9824 "results");
9825 Local<v8::Array> results = Local<v8::Array>::Cast(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009826 CHECK_EQ(16u, results->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009827 for (int i = 0; i < 16; i += 4) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009828 CHECK(v8_str("env2_x")
9829 ->Equals(env1.local(),
9830 results->Get(env1.local(), i + 0).ToLocalChecked())
9831 .FromJust());
9832 CHECK(v8_str("env3_x")
9833 ->Equals(env1.local(),
9834 results->Get(env1.local(), i + 1).ToLocalChecked())
9835 .FromJust());
9836 CHECK(v8_str("env3_x")
9837 ->Equals(env1.local(),
9838 results->Get(env1.local(), i + 2).ToLocalChecked())
9839 .FromJust());
9840 CHECK(v8_str("env2_x")
9841 ->Equals(env1.local(),
9842 results->Get(env1.local(), i + 3).ToLocalChecked())
9843 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009844 }
9845
9846 result = CompileRun(
9847 "results = [];"
9848 "for (var i = 0; i < 4; i++ ) {"
9849 " results.push(this.bound_x());"
9850 " results.push(this.get_x());"
9851 " results.push(this.get_x_w());"
9852 " results.push(this.this_x());"
9853 "}"
9854 "results");
9855 results = Local<v8::Array>::Cast(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009856 CHECK_EQ(16u, results->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009857 for (int i = 0; i < 16; i += 4) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009858 CHECK(v8_str("env2_x")
9859 ->Equals(env1.local(),
9860 results->Get(env1.local(), i + 0).ToLocalChecked())
9861 .FromJust());
9862 CHECK(v8_str("env1_x")
9863 ->Equals(env1.local(),
9864 results->Get(env1.local(), i + 1).ToLocalChecked())
9865 .FromJust());
9866 CHECK(v8_str("env3_x")
9867 ->Equals(env1.local(),
9868 results->Get(env1.local(), i + 2).ToLocalChecked())
9869 .FromJust());
9870 CHECK(v8_str("env2_x")
9871 ->Equals(env1.local(),
9872 results->Get(env1.local(), i + 3).ToLocalChecked())
9873 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009874 }
Andrei Popescu74b3c142010-03-29 12:03:09 +01009875}
9876
9877
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009878static bool allowed_access = false;
9879static bool AccessBlocker(Local<v8::Context> accessing_context,
Ben Murdoch097c5b22016-05-18 11:27:45 +01009880 Local<v8::Object> accessed_object,
9881 Local<v8::Value> data) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009882 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
9883 return context->Global()->Equals(context, accessed_object).FromJust() ||
9884 allowed_access;
Steve Blocka7e24c12009-10-30 11:49:00 +00009885}
9886
9887
9888static int g_echo_value = -1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009889
9890
9891static void EchoGetter(
9892 Local<String> name,
9893 const v8::PropertyCallbackInfo<v8::Value>& info) {
9894 info.GetReturnValue().Set(v8_num(g_echo_value));
Steve Blocka7e24c12009-10-30 11:49:00 +00009895}
9896
9897
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009898static void EchoSetter(Local<String> name, Local<Value> value,
9899 const v8::PropertyCallbackInfo<void>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009900 if (value->IsNumber())
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009901 g_echo_value =
9902 value->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00009903}
9904
9905
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009906static void UnreachableGetter(
9907 Local<String> name,
9908 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009909 CHECK(false); // This function should not be called..
Steve Blocka7e24c12009-10-30 11:49:00 +00009910}
9911
9912
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009913static void UnreachableSetter(Local<String>,
9914 Local<Value>,
9915 const v8::PropertyCallbackInfo<void>&) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009916 CHECK(false); // This function should nto be called.
9917}
9918
9919
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009920static void UnreachableFunction(
9921 const v8::FunctionCallbackInfo<v8::Value>& info) {
9922 CHECK(false); // This function should not be called..
9923}
9924
9925
Steve Block1e0659c2011-05-24 12:43:12 +01009926TEST(AccessControl) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009927 v8::Isolate* isolate = CcTest::isolate();
9928 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009929 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009930 v8::ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00009931
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009932 global_template->SetAccessCheckCallback(AccessBlocker);
Steve Blocka7e24c12009-10-30 11:49:00 +00009933
9934 // Add an accessor accessible by cross-domain JS code.
9935 global_template->SetAccessor(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009936 v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
Steve Blocka7e24c12009-10-30 11:49:00 +00009937 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
9938
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009939
Steve Blocka7e24c12009-10-30 11:49:00 +00009940 // Add an accessor that is not accessible by cross-domain JS code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009941 global_template->SetAccessor(v8_str("blocked_prop"), UnreachableGetter,
9942 UnreachableSetter, v8::Local<Value>(),
Steve Blocka7e24c12009-10-30 11:49:00 +00009943 v8::DEFAULT);
9944
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009945 global_template->SetAccessorProperty(
9946 v8_str("blocked_js_prop"),
9947 v8::FunctionTemplate::New(isolate, UnreachableFunction),
9948 v8::FunctionTemplate::New(isolate, UnreachableFunction),
9949 v8::None,
9950 v8::DEFAULT);
9951
Steve Blocka7e24c12009-10-30 11:49:00 +00009952 // Create an environment
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009953 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
Steve Blocka7e24c12009-10-30 11:49:00 +00009954 context0->Enter();
9955
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009956 v8::Local<v8::Object> global0 = context0->Global();
Steve Blocka7e24c12009-10-30 11:49:00 +00009957
Steve Block1e0659c2011-05-24 12:43:12 +01009958 // Define a property with JS getter and setter.
9959 CompileRun(
9960 "function getter() { return 'getter'; };\n"
9961 "function setter() { return 'setter'; }\n"
9962 "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
9963
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009964 Local<Value> getter =
9965 global0->Get(context0, v8_str("getter")).ToLocalChecked();
9966 Local<Value> setter =
9967 global0->Get(context0, v8_str("setter")).ToLocalChecked();
Steve Block1e0659c2011-05-24 12:43:12 +01009968
9969 // And define normal element.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009970 CHECK(global0->Set(context0, 239, v8_str("239")).FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +01009971
9972 // Define an element with JS getter and setter.
9973 CompileRun(
9974 "function el_getter() { return 'el_getter'; };\n"
9975 "function el_setter() { return 'el_setter'; };\n"
9976 "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
9977
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009978 Local<Value> el_getter =
9979 global0->Get(context0, v8_str("el_getter")).ToLocalChecked();
9980 Local<Value> el_setter =
9981 global0->Get(context0, v8_str("el_setter")).ToLocalChecked();
Steve Block1e0659c2011-05-24 12:43:12 +01009982
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009983 v8::HandleScope scope1(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00009984
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009985 v8::Local<Context> context1 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00009986 context1->Enter();
9987
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009988 v8::Local<v8::Object> global1 = context1->Global();
9989 CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009990
Steve Block1e0659c2011-05-24 12:43:12 +01009991 // Access blocked property.
9992 CompileRun("other.blocked_prop = 1");
9993
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009994 CHECK(CompileRun("other.blocked_prop").IsEmpty());
9995 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
9996 .IsEmpty());
9997 CHECK(
9998 CompileRun("propertyIsEnumerable.call(other, 'blocked_prop')").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +01009999
10000 // Access blocked element.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010001 CHECK(CompileRun("other[239] = 1").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +010010002
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010003 CHECK(CompileRun("other[239]").IsEmpty());
10004 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '239')").IsEmpty());
10005 CHECK(CompileRun("propertyIsEnumerable.call(other, '239')").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +010010006
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010007 allowed_access = true;
10008 // Now we can enumerate the property.
Steve Block1e0659c2011-05-24 12:43:12 +010010009 ExpectTrue("propertyIsEnumerable.call(other, '239')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010010 allowed_access = false;
Steve Block1e0659c2011-05-24 12:43:12 +010010011
10012 // Access a property with JS accessor.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010013 CHECK(CompileRun("other.js_accessor_p = 2").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +010010014
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010015 CHECK(CompileRun("other.js_accessor_p").IsEmpty());
10016 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'js_accessor_p')")
10017 .IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +010010018
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010019 allowed_access = true;
Steve Block1e0659c2011-05-24 12:43:12 +010010020
10021 ExpectString("other.js_accessor_p", "getter");
10022 ExpectObject(
10023 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
Steve Block1e0659c2011-05-24 12:43:12 +010010024 ExpectObject(
10025 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
10026 ExpectUndefined(
10027 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
10028
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010029 allowed_access = false;
Steve Block1e0659c2011-05-24 12:43:12 +010010030
10031 // Access an element with JS accessor.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010032 CHECK(CompileRun("other[42] = 2").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +010010033
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010034 CHECK(CompileRun("other[42]").IsEmpty());
10035 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '42')").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +010010036
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010037 allowed_access = true;
Steve Block1e0659c2011-05-24 12:43:12 +010010038
10039 ExpectString("other[42]", "el_getter");
10040 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
Steve Block1e0659c2011-05-24 12:43:12 +010010041 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
10042 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
10043
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010044 allowed_access = false;
Steve Block1e0659c2011-05-24 12:43:12 +010010045
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010046 v8::Local<Value> value;
Steve Blocka7e24c12009-10-30 11:49:00 +000010047
Steve Blocka7e24c12009-10-30 11:49:00 +000010048 // Access accessible property
Steve Block1e0659c2011-05-24 12:43:12 +010010049 value = CompileRun("other.accessible_prop = 3");
Steve Blocka7e24c12009-10-30 11:49:00 +000010050 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010051 CHECK_EQ(3, value->Int32Value(context1).FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +000010052 CHECK_EQ(3, g_echo_value);
Steve Blocka7e24c12009-10-30 11:49:00 +000010053
Steve Block1e0659c2011-05-24 12:43:12 +010010054 value = CompileRun("other.accessible_prop");
Steve Blocka7e24c12009-10-30 11:49:00 +000010055 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010056 CHECK_EQ(3, value->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010057
Steve Block1e0659c2011-05-24 12:43:12 +010010058 value = CompileRun(
10059 "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
10060 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010061 CHECK_EQ(3, value->Int32Value(context1).FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +010010062
10063 value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
Steve Blocka7e24c12009-10-30 11:49:00 +000010064 CHECK(value->IsTrue());
10065
10066 // Enumeration doesn't enumerate accessors from inaccessible objects in
10067 // the prototype chain even if the accessors are in themselves accessible.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010068 // Enumeration doesn't throw, it silently ignores what it can't access.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010069 value = CompileRun(
10070 "(function() {"
10071 " var obj = { '__proto__': other };"
10072 " try {"
10073 " for (var p in obj) {"
10074 " if (p == 'accessible_prop' ||"
10075 " p == 'blocked_js_prop' ||"
10076 " p == 'blocked_js_prop') {"
10077 " return false;"
10078 " }"
10079 " }"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010080 " return true;"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010081 " } catch (e) {"
10082 " return false;"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010083 " }"
10084 "})()");
Steve Block1e0659c2011-05-24 12:43:12 +010010085 CHECK(value->IsTrue());
Steve Blocka7e24c12009-10-30 11:49:00 +000010086
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010087 // Test that preventExtensions fails on a non-accessible object even if that
10088 // object is already non-extensible.
10089 CHECK(global1->Set(context1, v8_str("checked_object"),
10090 global_template->NewInstance(context1).ToLocalChecked())
10091 .FromJust());
10092 allowed_access = true;
10093 CompileRun("Object.preventExtensions(checked_object)");
10094 ExpectFalse("Object.isExtensible(checked_object)");
10095 allowed_access = false;
10096 CHECK(CompileRun("Object.preventExtensions(checked_object)").IsEmpty());
10097
Steve Blocka7e24c12009-10-30 11:49:00 +000010098 context1->Exit();
10099 context0->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +000010100}
10101
10102
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010103TEST(AccessControlES5) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010104 v8::Isolate* isolate = CcTest::isolate();
10105 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010106 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010107 v8::ObjectTemplate::New(isolate);
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010108
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010109 global_template->SetAccessCheckCallback(AccessBlocker);
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010110
Steve Block44f0eee2011-05-26 01:26:41 +010010111 // Add accessible accessor.
10112 global_template->SetAccessor(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010113 v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
Steve Block44f0eee2011-05-26 01:26:41 +010010114 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
10115
10116
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010117 // Add an accessor that is not accessible by cross-domain JS code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010118 global_template->SetAccessor(v8_str("blocked_prop"), UnreachableGetter,
10119 UnreachableSetter, v8::Local<Value>(),
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010120 v8::DEFAULT);
10121
10122 // Create an environment
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010123 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010124 context0->Enter();
10125
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010126 v8::Local<v8::Object> global0 = context0->Global();
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010127
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010128 v8::Local<Context> context1 = Context::New(isolate);
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010129 context1->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010130 v8::Local<v8::Object> global1 = context1->Global();
10131 CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010132
10133 // Regression test for issue 1154.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010134 CHECK(CompileRun("Object.keys(other).length == 1")
10135 ->BooleanValue(context1)
10136 .FromJust());
10137 CHECK(CompileRun("Object.keys(other)[0] == 'accessible_prop'")
10138 ->BooleanValue(context1)
10139 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010140 CHECK(CompileRun("other.blocked_prop").IsEmpty());
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010141
10142 // Regression test for issue 1027.
10143 CompileRun("Object.defineProperty(\n"
10144 " other, 'blocked_prop', {configurable: false})");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010145 CHECK(CompileRun("other.blocked_prop").IsEmpty());
10146 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
10147 .IsEmpty());
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010148
10149 // Regression test for issue 1171.
10150 ExpectTrue("Object.isExtensible(other)");
10151 CompileRun("Object.preventExtensions(other)");
10152 ExpectTrue("Object.isExtensible(other)");
10153
10154 // Object.seal and Object.freeze.
10155 CompileRun("Object.freeze(other)");
10156 ExpectTrue("Object.isExtensible(other)");
10157
10158 CompileRun("Object.seal(other)");
10159 ExpectTrue("Object.isExtensible(other)");
Steve Block44f0eee2011-05-26 01:26:41 +010010160
10161 // Regression test for issue 1250.
10162 // Make sure that we can set the accessible accessors value using normal
10163 // assignment.
10164 CompileRun("other.accessible_prop = 42");
10165 CHECK_EQ(42, g_echo_value);
10166
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010167 // [[DefineOwnProperty]] always throws for access-checked objects.
10168 CHECK(
10169 CompileRun("Object.defineProperty(other, 'accessible_prop', {value: 43})")
10170 .IsEmpty());
10171 CHECK(CompileRun("other.accessible_prop == 42")->IsTrue());
10172 CHECK_EQ(42, g_echo_value); // Make sure we didn't call the setter.
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010173}
10174
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010175static bool AccessAlwaysBlocked(Local<v8::Context> accessing_context,
Ben Murdoch097c5b22016-05-18 11:27:45 +010010176 Local<v8::Object> global,
10177 Local<v8::Value> data) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010178 i::PrintF("Access blocked.\n");
Leon Clarke4515c472010-02-03 11:58:03 +000010179 return false;
10180}
10181
10182
10183THREADED_TEST(AccessControlGetOwnPropertyNames) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010184 v8::Isolate* isolate = CcTest::isolate();
10185 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010186 v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
Leon Clarke4515c472010-02-03 11:58:03 +000010187
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010188 obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010189 obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
10190
10191 // Add an accessor accessible by cross-domain JS code.
10192 obj_template->SetAccessor(
10193 v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
10194 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
Leon Clarke4515c472010-02-03 11:58:03 +000010195
10196 // Create an environment
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010197 v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
Leon Clarke4515c472010-02-03 11:58:03 +000010198 context0->Enter();
10199
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010200 v8::Local<v8::Object> global0 = context0->Global();
Leon Clarke4515c472010-02-03 11:58:03 +000010201
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010202 v8::HandleScope scope1(CcTest::isolate());
Leon Clarke4515c472010-02-03 11:58:03 +000010203
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010204 v8::Local<Context> context1 = Context::New(isolate);
Leon Clarke4515c472010-02-03 11:58:03 +000010205 context1->Enter();
10206
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010207 v8::Local<v8::Object> global1 = context1->Global();
10208 CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
10209 CHECK(global1->Set(context1, v8_str("object"),
10210 obj_template->NewInstance(context1).ToLocalChecked())
10211 .FromJust());
Leon Clarke4515c472010-02-03 11:58:03 +000010212
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010213 v8::Local<Value> value;
Leon Clarke4515c472010-02-03 11:58:03 +000010214
10215 // Attempt to get the property names of the other global object and
10216 // of an object that requires access checks. Accessing the other
10217 // global object should be blocked by access checks on the global
10218 // proxy object. Accessing the object that requires access checks
10219 // is blocked by the access checks on the object itself.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010220 value = CompileRun(
10221 "var names = Object.getOwnPropertyNames(other);"
10222 "names.length == 1 && names[0] == 'accessible_prop';");
10223 CHECK(value->BooleanValue(context1).FromJust());
Leon Clarke4515c472010-02-03 11:58:03 +000010224
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010225 value = CompileRun(
10226 "var names = Object.getOwnPropertyNames(object);"
10227 "names.length == 1 && names[0] == 'accessible_prop';");
10228 CHECK(value->BooleanValue(context1).FromJust());
Leon Clarke4515c472010-02-03 11:58:03 +000010229
10230 context1->Exit();
10231 context0->Exit();
Leon Clarke4515c472010-02-03 11:58:03 +000010232}
10233
10234
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010235TEST(Regress470113) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010236 v8::Isolate* isolate = CcTest::isolate();
10237 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010238 v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
10239 obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010240 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010241 CHECK(env->Global()
10242 ->Set(env.local(), v8_str("prohibited"),
10243 obj_template->NewInstance(env.local()).ToLocalChecked())
10244 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010245
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010246 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010247 v8::TryCatch try_catch(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010248 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010249 "'use strict';\n"
10250 "class C extends Object {\n"
10251 " m() { super.powned = 'Powned!'; }\n"
10252 "}\n"
10253 "let c = new C();\n"
10254 "c.m.call(prohibited)");
10255
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010256 CHECK(try_catch.HasCaught());
10257 }
Steve Block8defd9f2010-07-08 12:39:36 +010010258}
10259
10260
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010261static void ConstTenGetter(Local<String> name,
10262 const v8::PropertyCallbackInfo<v8::Value>& info) {
10263 info.GetReturnValue().Set(v8_num(10));
Steve Blocka7e24c12009-10-30 11:49:00 +000010264}
10265
10266
10267THREADED_TEST(CrossDomainAccessors) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010268 v8::Isolate* isolate = CcTest::isolate();
10269 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010270
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010271 v8::Local<v8::FunctionTemplate> func_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010272 v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010273
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010274 v8::Local<v8::ObjectTemplate> global_template =
Steve Blocka7e24c12009-10-30 11:49:00 +000010275 func_template->InstanceTemplate();
10276
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010277 v8::Local<v8::ObjectTemplate> proto_template =
Steve Blocka7e24c12009-10-30 11:49:00 +000010278 func_template->PrototypeTemplate();
10279
10280 // Add an accessor to proto that's accessible by cross-domain JS code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010281 proto_template->SetAccessor(v8_str("accessible"), ConstTenGetter, 0,
10282 v8::Local<Value>(), v8::ALL_CAN_READ);
Steve Blocka7e24c12009-10-30 11:49:00 +000010283
10284 // Add an accessor that is not accessible by cross-domain JS code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010285 global_template->SetAccessor(v8_str("unreachable"), UnreachableGetter, 0,
10286 v8::Local<Value>(), v8::DEFAULT);
Steve Blocka7e24c12009-10-30 11:49:00 +000010287
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010288 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
Steve Blocka7e24c12009-10-30 11:49:00 +000010289 context0->Enter();
10290
10291 Local<v8::Object> global = context0->Global();
10292 // Add a normal property that shadows 'accessible'
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010293 CHECK(global->Set(context0, v8_str("accessible"), v8_num(11)).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010294
10295 // Enter a new context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010296 v8::HandleScope scope1(CcTest::isolate());
10297 v8::Local<Context> context1 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010298 context1->Enter();
10299
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010300 v8::Local<v8::Object> global1 = context1->Global();
10301 CHECK(global1->Set(context1, v8_str("other"), global).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010302
10303 // Should return 10, instead of 11
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010304 v8::Local<Value> value =
10305 v8_compile("other.accessible")->Run(context1).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000010306 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010307 CHECK_EQ(10, value->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010308
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010309 v8::MaybeLocal<v8::Value> maybe_value =
10310 v8_compile("other.unreachable")->Run(context1);
10311 CHECK(maybe_value.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000010312
10313 context1->Exit();
10314 context0->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +000010315}
10316
10317
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010318static int access_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +000010319
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010320static bool AccessCounter(Local<v8::Context> accessing_context,
Ben Murdoch097c5b22016-05-18 11:27:45 +010010321 Local<v8::Object> accessed_object,
10322 Local<v8::Value> data) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010323 access_count++;
Steve Blocka7e24c12009-10-30 11:49:00 +000010324 return true;
10325}
10326
10327
10328// This one is too easily disturbed by other tests.
10329TEST(AccessControlIC) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010330 access_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +000010331
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010332 v8::Isolate* isolate = CcTest::isolate();
10333 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010334
10335 // Create an environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010336 v8::Local<Context> context0 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010337 context0->Enter();
10338
10339 // Create an object that requires access-check functions to be
10340 // called for cross-domain access.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010341 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010342 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010343 object_template->SetAccessCheckCallback(AccessCounter);
10344 Local<v8::Object> object =
10345 object_template->NewInstance(context0).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000010346
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010347 v8::HandleScope scope1(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010348
10349 // Create another environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010350 v8::Local<Context> context1 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010351 context1->Enter();
10352
10353 // Make easy access to the object from the other environment.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010354 v8::Local<v8::Object> global1 = context1->Global();
10355 CHECK(global1->Set(context1, v8_str("obj"), object).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010356
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010357 v8::Local<Value> value;
Steve Blocka7e24c12009-10-30 11:49:00 +000010358
10359 // Check that the named access-control function is called every time.
10360 CompileRun("function testProp(obj) {"
10361 " for (var i = 0; i < 10; i++) obj.prop = 1;"
10362 " for (var j = 0; j < 10; j++) obj.prop;"
10363 " return obj.prop"
10364 "}");
10365 value = CompileRun("testProp(obj)");
10366 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010367 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10368 CHECK_EQ(21, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010369
10370 // Check that the named access-control function is called every time.
10371 CompileRun("var p = 'prop';"
10372 "function testKeyed(obj) {"
10373 " for (var i = 0; i < 10; i++) obj[p] = 1;"
10374 " for (var j = 0; j < 10; j++) obj[p];"
10375 " return obj[p];"
10376 "}");
10377 // Use obj which requires access checks. No inline caching is used
10378 // in that case.
10379 value = CompileRun("testKeyed(obj)");
10380 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010381 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10382 CHECK_EQ(42, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010383 // Force the inline caches into generic state and try again.
10384 CompileRun("testKeyed({ a: 0 })");
10385 CompileRun("testKeyed({ b: 0 })");
10386 value = CompileRun("testKeyed(obj)");
10387 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010388 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10389 CHECK_EQ(63, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010390
10391 // Check that the indexed access-control function is called every time.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010392 access_count = 0;
10393
Steve Blocka7e24c12009-10-30 11:49:00 +000010394 CompileRun("function testIndexed(obj) {"
10395 " for (var i = 0; i < 10; i++) obj[0] = 1;"
10396 " for (var j = 0; j < 10; j++) obj[0];"
10397 " return obj[0]"
10398 "}");
10399 value = CompileRun("testIndexed(obj)");
10400 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010401 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10402 CHECK_EQ(21, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010403 // Force the inline caches into generic state.
10404 CompileRun("testIndexed(new Array(1))");
10405 // Test that the indexed access check is called.
10406 value = CompileRun("testIndexed(obj)");
10407 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010408 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10409 CHECK_EQ(42, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010410
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010411 access_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +000010412 // Check that the named access check is called when invoking
10413 // functions on an object that requires access checks.
10414 CompileRun("obj.f = function() {}");
10415 CompileRun("function testCallNormal(obj) {"
10416 " for (var i = 0; i < 10; i++) obj.f();"
10417 "}");
10418 CompileRun("testCallNormal(obj)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010419 printf("%i\n", access_count);
10420 CHECK_EQ(11, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010421
10422 // Force obj into slow case.
10423 value = CompileRun("delete obj.prop");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010424 CHECK(value->BooleanValue(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010425 // Force inline caches into dictionary probing mode.
10426 CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
10427 // Test that the named access check is called.
10428 value = CompileRun("testProp(obj);");
10429 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010430 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10431 CHECK_EQ(33, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010432
10433 // Force the call inline cache into dictionary probing mode.
10434 CompileRun("o.f = function() {}; testCallNormal(o)");
10435 // Test that the named access check is still called for each
10436 // invocation of the function.
10437 value = CompileRun("testCallNormal(obj)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010438 CHECK_EQ(43, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010439
10440 context1->Exit();
10441 context0->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +000010442}
10443
10444
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010445THREADED_TEST(Version) { v8::V8::GetVersion(); }
Steve Blocka7e24c12009-10-30 11:49:00 +000010446
10447
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010448static void InstanceFunctionCallback(
10449 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010450 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010451 args.GetReturnValue().Set(v8_num(12));
Steve Blocka7e24c12009-10-30 11:49:00 +000010452}
10453
10454
10455THREADED_TEST(InstanceProperties) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010456 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010457 v8::Isolate* isolate = context->GetIsolate();
10458 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010459
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010460 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010461 Local<ObjectTemplate> instance = t->InstanceTemplate();
10462
10463 instance->Set(v8_str("x"), v8_num(42));
10464 instance->Set(v8_str("f"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010465 v8::FunctionTemplate::New(isolate, InstanceFunctionCallback));
Steve Blocka7e24c12009-10-30 11:49:00 +000010466
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010467 Local<Value> o = t->GetFunction(context.local())
10468 .ToLocalChecked()
10469 ->NewInstance(context.local())
10470 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000010471
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010472 CHECK(context->Global()->Set(context.local(), v8_str("i"), o).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010473 Local<Value> value = CompileRun("i.x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010474 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010475
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010476 value = CompileRun("i.f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010477 CHECK_EQ(12, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010478}
10479
10480
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010481static void GlobalObjectInstancePropertiesGet(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010482 Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>&) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010483 ApiTestFuzzer::Fuzz();
Steve Blocka7e24c12009-10-30 11:49:00 +000010484}
10485
10486
10487THREADED_TEST(GlobalObjectInstanceProperties) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010488 v8::Isolate* isolate = CcTest::isolate();
10489 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010490
10491 Local<Value> global_object;
10492
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010493 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010494 t->InstanceTemplate()->SetHandler(
10495 v8::NamedPropertyHandlerConfiguration(GlobalObjectInstancePropertiesGet));
Steve Blocka7e24c12009-10-30 11:49:00 +000010496 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10497 instance_template->Set(v8_str("x"), v8_num(42));
10498 instance_template->Set(v8_str("f"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010499 v8::FunctionTemplate::New(isolate,
10500 InstanceFunctionCallback));
Steve Blocka7e24c12009-10-30 11:49:00 +000010501
Ben Murdochb0fe1622011-05-05 13:52:32 +010010502 // The script to check how Crankshaft compiles missing global function
10503 // invocations. function g is not defined and should throw on call.
10504 const char* script =
10505 "function wrapper(call) {"
10506 " var x = 0, y = 1;"
10507 " for (var i = 0; i < 1000; i++) {"
10508 " x += i * 100;"
10509 " y += i * 100;"
10510 " }"
10511 " if (call) g();"
10512 "}"
10513 "for (var i = 0; i < 17; i++) wrapper(false);"
10514 "var thrown = 0;"
10515 "try { wrapper(true); } catch (e) { thrown = 1; };"
10516 "thrown";
10517
Steve Blocka7e24c12009-10-30 11:49:00 +000010518 {
10519 LocalContext env(NULL, instance_template);
10520 // Hold on to the global object so it can be used again in another
10521 // environment initialization.
10522 global_object = env->Global();
10523
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010524 Local<Value> value = CompileRun("x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010525 CHECK_EQ(42, value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010526 value = CompileRun("f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010527 CHECK_EQ(12, value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010528 value = CompileRun(script);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010529 CHECK_EQ(1, value->Int32Value(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010530 }
10531
10532 {
10533 // Create new environment reusing the global object.
10534 LocalContext env(NULL, instance_template, global_object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010535 Local<Value> value = CompileRun("x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010536 CHECK_EQ(42, value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010537 value = CompileRun("f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010538 CHECK_EQ(12, value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010539 value = CompileRun(script);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010540 CHECK_EQ(1, value->Int32Value(env.local()).FromJust());
Ben Murdochb0fe1622011-05-05 13:52:32 +010010541 }
10542}
10543
10544
10545THREADED_TEST(CallKnownGlobalReceiver) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010546 v8::Isolate* isolate = CcTest::isolate();
10547 v8::HandleScope handle_scope(isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +010010548
10549 Local<Value> global_object;
10550
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010551 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +010010552 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10553
10554 // The script to check that we leave global object not
10555 // global object proxy on stack when we deoptimize from inside
10556 // arguments evaluation.
10557 // To provoke error we need to both force deoptimization
10558 // from arguments evaluation and to force CallIC to take
10559 // CallIC_Miss code path that can't cope with global proxy.
10560 const char* script =
10561 "function bar(x, y) { try { } finally { } }"
10562 "function baz(x) { try { } finally { } }"
10563 "function bom(x) { try { } finally { } }"
10564 "function foo(x) { bar([x], bom(2)); }"
10565 "for (var i = 0; i < 10000; i++) foo(1);"
10566 "foo";
10567
10568 Local<Value> foo;
10569 {
10570 LocalContext env(NULL, instance_template);
10571 // Hold on to the global object so it can be used again in another
10572 // environment initialization.
10573 global_object = env->Global();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010574 foo = CompileRun(script);
Ben Murdochb0fe1622011-05-05 13:52:32 +010010575 }
10576
10577 {
10578 // Create new environment reusing the global object.
10579 LocalContext env(NULL, instance_template, global_object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010580 CHECK(env->Global()->Set(env.local(), v8_str("foo"), foo).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010581 CompileRun("foo()");
Steve Blocka7e24c12009-10-30 11:49:00 +000010582 }
10583}
10584
10585
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010586static void ShadowFunctionCallback(
10587 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010588 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010589 args.GetReturnValue().Set(v8_num(42));
Steve Blocka7e24c12009-10-30 11:49:00 +000010590}
10591
10592
10593static int shadow_y;
10594static int shadow_y_setter_call_count;
10595static int shadow_y_getter_call_count;
10596
10597
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010598static void ShadowYSetter(Local<String>,
10599 Local<Value>,
10600 const v8::PropertyCallbackInfo<void>&) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010601 shadow_y_setter_call_count++;
10602 shadow_y = 42;
10603}
10604
10605
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010606static void ShadowYGetter(Local<String> name,
10607 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010608 ApiTestFuzzer::Fuzz();
10609 shadow_y_getter_call_count++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010610 info.GetReturnValue().Set(v8_num(shadow_y));
Steve Blocka7e24c12009-10-30 11:49:00 +000010611}
10612
10613
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010614static void ShadowIndexedGet(uint32_t index,
10615 const v8::PropertyCallbackInfo<v8::Value>&) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010616}
10617
10618
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010619static void ShadowNamedGet(Local<Name> key,
10620 const v8::PropertyCallbackInfo<v8::Value>&) {}
Steve Blocka7e24c12009-10-30 11:49:00 +000010621
10622
10623THREADED_TEST(ShadowObject) {
10624 shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010625 v8::Isolate* isolate = CcTest::isolate();
10626 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010627
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010628 Local<ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010629 LocalContext context(NULL, global_template);
10630
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010631 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010632 t->InstanceTemplate()->SetHandler(
10633 v8::NamedPropertyHandlerConfiguration(ShadowNamedGet));
10634 t->InstanceTemplate()->SetHandler(
10635 v8::IndexedPropertyHandlerConfiguration(ShadowIndexedGet));
Steve Blocka7e24c12009-10-30 11:49:00 +000010636 Local<ObjectTemplate> proto = t->PrototypeTemplate();
10637 Local<ObjectTemplate> instance = t->InstanceTemplate();
10638
Steve Blocka7e24c12009-10-30 11:49:00 +000010639 proto->Set(v8_str("f"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010640 v8::FunctionTemplate::New(isolate,
10641 ShadowFunctionCallback,
10642 Local<Value>()));
Steve Blocka7e24c12009-10-30 11:49:00 +000010643 proto->Set(v8_str("x"), v8_num(12));
10644
10645 instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
10646
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010647 Local<Value> o = t->GetFunction(context.local())
10648 .ToLocalChecked()
10649 ->NewInstance(context.local())
10650 .ToLocalChecked();
10651 CHECK(context->Global()
10652 ->Set(context.local(), v8_str("__proto__"), o)
10653 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010654
10655 Local<Value> value =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010656 CompileRun("this.propertyIsEnumerable(0)");
Steve Blocka7e24c12009-10-30 11:49:00 +000010657 CHECK(value->IsBoolean());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010658 CHECK(!value->BooleanValue(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010659
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010660 value = CompileRun("x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010661 CHECK_EQ(12, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010662
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010663 value = CompileRun("f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010664 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010665
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010666 CompileRun("y = 43");
Steve Blocka7e24c12009-10-30 11:49:00 +000010667 CHECK_EQ(1, shadow_y_setter_call_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010668 value = CompileRun("y");
Steve Blocka7e24c12009-10-30 11:49:00 +000010669 CHECK_EQ(1, shadow_y_getter_call_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010670 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010671}
10672
10673
10674THREADED_TEST(HiddenPrototype) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010675 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010676 v8::Isolate* isolate = context->GetIsolate();
10677 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010678
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010679 Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010680 t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010681 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010682 t1->SetHiddenPrototype(true);
10683 t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010684 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010685 t2->SetHiddenPrototype(true);
10686 t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010687 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010688 t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
10689
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010690 Local<v8::Object> o0 = t0->GetFunction(context.local())
10691 .ToLocalChecked()
10692 ->NewInstance(context.local())
10693 .ToLocalChecked();
10694 Local<v8::Object> o1 = t1->GetFunction(context.local())
10695 .ToLocalChecked()
10696 ->NewInstance(context.local())
10697 .ToLocalChecked();
10698 Local<v8::Object> o2 = t2->GetFunction(context.local())
10699 .ToLocalChecked()
10700 ->NewInstance(context.local())
10701 .ToLocalChecked();
10702 Local<v8::Object> o3 = t3->GetFunction(context.local())
10703 .ToLocalChecked()
10704 ->NewInstance(context.local())
10705 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000010706
10707 // Setting the prototype on an object skips hidden prototypes.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010708 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10709 .ToLocalChecked()
10710 ->Int32Value(context.local())
10711 .FromJust());
10712 CHECK(o0->Set(context.local(), v8_str("__proto__"), o1).FromJust());
10713 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10714 .ToLocalChecked()
10715 ->Int32Value(context.local())
10716 .FromJust());
10717 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10718 .ToLocalChecked()
10719 ->Int32Value(context.local())
10720 .FromJust());
10721 CHECK(o0->Set(context.local(), v8_str("__proto__"), o2).FromJust());
10722 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10723 .ToLocalChecked()
10724 ->Int32Value(context.local())
10725 .FromJust());
10726 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10727 .ToLocalChecked()
10728 ->Int32Value(context.local())
10729 .FromJust());
10730 CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
10731 .ToLocalChecked()
10732 ->Int32Value(context.local())
10733 .FromJust());
10734 CHECK(o0->Set(context.local(), v8_str("__proto__"), o3).FromJust());
10735 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10736 .ToLocalChecked()
10737 ->Int32Value(context.local())
10738 .FromJust());
10739 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10740 .ToLocalChecked()
10741 ->Int32Value(context.local())
10742 .FromJust());
10743 CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
10744 .ToLocalChecked()
10745 ->Int32Value(context.local())
10746 .FromJust());
10747 CHECK_EQ(3, o0->Get(context.local(), v8_str("u"))
10748 .ToLocalChecked()
10749 ->Int32Value(context.local())
10750 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010751
10752 // Getting the prototype of o0 should get the first visible one
10753 // which is o3. Therefore, z should not be defined on the prototype
10754 // object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010755 Local<Value> proto =
10756 o0->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000010757 CHECK(proto->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010758 CHECK(proto.As<v8::Object>()
10759 ->Get(context.local(), v8_str("z"))
10760 .ToLocalChecked()
10761 ->IsUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +000010762}
10763
10764
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010765THREADED_TEST(HiddenPrototypeSet) {
Andrei Popescu402d9372010-02-26 13:31:12 +000010766 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010767 v8::Isolate* isolate = context->GetIsolate();
10768 v8::HandleScope handle_scope(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000010769
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010770 Local<v8::FunctionTemplate> ot = v8::FunctionTemplate::New(isolate);
10771 Local<v8::FunctionTemplate> ht = v8::FunctionTemplate::New(isolate);
10772 ht->SetHiddenPrototype(true);
10773 Local<v8::FunctionTemplate> pt = v8::FunctionTemplate::New(isolate);
10774 ht->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
10775
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010776 Local<v8::Object> o = ot->GetFunction(context.local())
10777 .ToLocalChecked()
10778 ->NewInstance(context.local())
10779 .ToLocalChecked();
10780 Local<v8::Object> h = ht->GetFunction(context.local())
10781 .ToLocalChecked()
10782 ->NewInstance(context.local())
10783 .ToLocalChecked();
10784 Local<v8::Object> p = pt->GetFunction(context.local())
10785 .ToLocalChecked()
10786 ->NewInstance(context.local())
10787 .ToLocalChecked();
10788 CHECK(o->Set(context.local(), v8_str("__proto__"), h).FromJust());
10789 CHECK(h->Set(context.local(), v8_str("__proto__"), p).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010790
10791 // Setting a property that exists on the hidden prototype goes there.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010792 CHECK(o->Set(context.local(), v8_str("x"), v8_num(7)).FromJust());
10793 CHECK_EQ(7, o->Get(context.local(), v8_str("x"))
10794 .ToLocalChecked()
10795 ->Int32Value(context.local())
10796 .FromJust());
10797 CHECK_EQ(7, h->Get(context.local(), v8_str("x"))
10798 .ToLocalChecked()
10799 ->Int32Value(context.local())
10800 .FromJust());
10801 CHECK(p->Get(context.local(), v8_str("x")).ToLocalChecked()->IsUndefined());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010802
10803 // Setting a new property should not be forwarded to the hidden prototype.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010804 CHECK(o->Set(context.local(), v8_str("y"), v8_num(6)).FromJust());
10805 CHECK_EQ(6, o->Get(context.local(), v8_str("y"))
10806 .ToLocalChecked()
10807 ->Int32Value(context.local())
10808 .FromJust());
10809 CHECK(h->Get(context.local(), v8_str("y")).ToLocalChecked()->IsUndefined());
10810 CHECK(p->Get(context.local(), v8_str("y")).ToLocalChecked()->IsUndefined());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010811
10812 // Setting a property that only exists on a prototype of the hidden prototype
10813 // is treated normally again.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010814 CHECK(p->Set(context.local(), v8_str("z"), v8_num(8)).FromJust());
10815 CHECK_EQ(8, o->Get(context.local(), v8_str("z"))
10816 .ToLocalChecked()
10817 ->Int32Value(context.local())
10818 .FromJust());
10819 CHECK_EQ(8, h->Get(context.local(), v8_str("z"))
10820 .ToLocalChecked()
10821 ->Int32Value(context.local())
10822 .FromJust());
10823 CHECK_EQ(8, p->Get(context.local(), v8_str("z"))
10824 .ToLocalChecked()
10825 ->Int32Value(context.local())
10826 .FromJust());
10827 CHECK(o->Set(context.local(), v8_str("z"), v8_num(9)).FromJust());
10828 CHECK_EQ(9, o->Get(context.local(), v8_str("z"))
10829 .ToLocalChecked()
10830 ->Int32Value(context.local())
10831 .FromJust());
10832 CHECK_EQ(8, h->Get(context.local(), v8_str("z"))
10833 .ToLocalChecked()
10834 ->Int32Value(context.local())
10835 .FromJust());
10836 CHECK_EQ(8, p->Get(context.local(), v8_str("z"))
10837 .ToLocalChecked()
10838 ->Int32Value(context.local())
10839 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010840}
10841
10842
10843// Regression test for issue 2457.
10844THREADED_TEST(HiddenPrototypeIdentityHash) {
10845 LocalContext context;
10846 v8::HandleScope handle_scope(context->GetIsolate());
10847
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010848 Local<FunctionTemplate> t = FunctionTemplate::New(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010849 t->SetHiddenPrototype(true);
10850 t->InstanceTemplate()->Set(v8_str("foo"), v8_num(75));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010851 Local<Object> p = t->GetFunction(context.local())
10852 .ToLocalChecked()
10853 ->NewInstance(context.local())
10854 .ToLocalChecked();
10855 Local<Object> o = Object::New(context->GetIsolate());
10856 CHECK(o->SetPrototype(context.local(), p).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010857
10858 int hash = o->GetIdentityHash();
10859 USE(hash);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010860 CHECK(o->Set(context.local(), v8_str("foo"), v8_num(42)).FromJust());
10861 CHECK_EQ(hash, o->GetIdentityHash());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010862}
10863
10864
10865THREADED_TEST(SetPrototype) {
10866 LocalContext context;
10867 v8::Isolate* isolate = context->GetIsolate();
10868 v8::HandleScope handle_scope(isolate);
10869
10870 Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000010871 t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010872 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000010873 t1->SetHiddenPrototype(true);
10874 t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010875 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000010876 t2->SetHiddenPrototype(true);
10877 t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010878 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000010879 t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
10880
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010881 Local<v8::Object> o0 = t0->GetFunction(context.local())
10882 .ToLocalChecked()
10883 ->NewInstance(context.local())
10884 .ToLocalChecked();
10885 Local<v8::Object> o1 = t1->GetFunction(context.local())
10886 .ToLocalChecked()
10887 ->NewInstance(context.local())
10888 .ToLocalChecked();
10889 Local<v8::Object> o2 = t2->GetFunction(context.local())
10890 .ToLocalChecked()
10891 ->NewInstance(context.local())
10892 .ToLocalChecked();
10893 Local<v8::Object> o3 = t3->GetFunction(context.local())
10894 .ToLocalChecked()
10895 ->NewInstance(context.local())
10896 .ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000010897
10898 // Setting the prototype on an object does not skip hidden prototypes.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010899 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10900 .ToLocalChecked()
10901 ->Int32Value(context.local())
10902 .FromJust());
10903 CHECK(o0->SetPrototype(context.local(), o1).FromJust());
10904 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10905 .ToLocalChecked()
10906 ->Int32Value(context.local())
10907 .FromJust());
10908 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10909 .ToLocalChecked()
10910 ->Int32Value(context.local())
10911 .FromJust());
10912 CHECK(o1->SetPrototype(context.local(), o2).FromJust());
10913 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10914 .ToLocalChecked()
10915 ->Int32Value(context.local())
10916 .FromJust());
10917 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10918 .ToLocalChecked()
10919 ->Int32Value(context.local())
10920 .FromJust());
10921 CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
10922 .ToLocalChecked()
10923 ->Int32Value(context.local())
10924 .FromJust());
10925 CHECK(o2->SetPrototype(context.local(), o3).FromJust());
10926 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10927 .ToLocalChecked()
10928 ->Int32Value(context.local())
10929 .FromJust());
10930 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10931 .ToLocalChecked()
10932 ->Int32Value(context.local())
10933 .FromJust());
10934 CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
10935 .ToLocalChecked()
10936 ->Int32Value(context.local())
10937 .FromJust());
10938 CHECK_EQ(3, o0->Get(context.local(), v8_str("u"))
10939 .ToLocalChecked()
10940 ->Int32Value(context.local())
10941 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000010942
10943 // Getting the prototype of o0 should get the first visible one
10944 // which is o3. Therefore, z should not be defined on the prototype
10945 // object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010946 Local<Value> proto =
10947 o0->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000010948 CHECK(proto->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010949 CHECK(proto.As<v8::Object>()->Equals(context.local(), o3).FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000010950
10951 // However, Object::GetPrototype ignores hidden prototype.
10952 Local<Value> proto0 = o0->GetPrototype();
10953 CHECK(proto0->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010954 CHECK(proto0.As<v8::Object>()->Equals(context.local(), o1).FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000010955
10956 Local<Value> proto1 = o1->GetPrototype();
10957 CHECK(proto1->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010958 CHECK(proto1.As<v8::Object>()->Equals(context.local(), o2).FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000010959
10960 Local<Value> proto2 = o2->GetPrototype();
10961 CHECK(proto2->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010962 CHECK(proto2.As<v8::Object>()->Equals(context.local(), o3).FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000010963}
10964
10965
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010966// Getting property names of an object with a prototype chain that
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010967// triggers dictionary elements in GetOwnPropertyNames() shouldn't
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010968// crash the runtime.
10969THREADED_TEST(Regress91517) {
10970 i::FLAG_allow_natives_syntax = true;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010971 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010972 v8::Isolate* isolate = context->GetIsolate();
10973 v8::HandleScope handle_scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010974
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010975 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010976 t1->SetHiddenPrototype(true);
10977 t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010978 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010979 t2->SetHiddenPrototype(true);
10980 t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
Ben Murdoch097c5b22016-05-18 11:27:45 +010010981 t2->InstanceTemplate()->Set(v8_str("objects"),
10982 v8::ObjectTemplate::New(isolate));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010983 t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010984 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010985 t3->SetHiddenPrototype(true);
10986 t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010987 Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010988 t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
10989
10990 // Force dictionary-based properties.
10991 i::ScopedVector<char> name_buf(1024);
10992 for (int i = 1; i <= 1000; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010993 i::SNPrintF(name_buf, "sdf%d", i);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010994 t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
10995 }
10996
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010997 Local<v8::Object> o1 = t1->GetFunction(context.local())
10998 .ToLocalChecked()
10999 ->NewInstance(context.local())
11000 .ToLocalChecked();
11001 Local<v8::Object> o2 = t2->GetFunction(context.local())
11002 .ToLocalChecked()
11003 ->NewInstance(context.local())
11004 .ToLocalChecked();
11005 Local<v8::Object> o3 = t3->GetFunction(context.local())
11006 .ToLocalChecked()
11007 ->NewInstance(context.local())
11008 .ToLocalChecked();
11009 Local<v8::Object> o4 = t4->GetFunction(context.local())
11010 .ToLocalChecked()
11011 ->NewInstance(context.local())
11012 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011013
11014 // Create prototype chain of hidden prototypes.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011015 CHECK(o4->SetPrototype(context.local(), o3).FromJust());
11016 CHECK(o3->SetPrototype(context.local(), o2).FromJust());
11017 CHECK(o2->SetPrototype(context.local(), o1).FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011018
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011019 // Call the runtime version of GetOwnPropertyNames() on the natively
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011020 // created object through JavaScript.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011021 CHECK(context->Global()->Set(context.local(), v8_str("obj"), o4).FromJust());
11022 // PROPERTY_FILTER_NONE = 0
11023 CompileRun("var names = %GetOwnPropertyKeys(obj, 0);");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011024
11025 ExpectInt32("names.length", 1006);
11026 ExpectTrue("names.indexOf(\"baz\") >= 0");
11027 ExpectTrue("names.indexOf(\"boo\") >= 0");
11028 ExpectTrue("names.indexOf(\"foo\") >= 0");
11029 ExpectTrue("names.indexOf(\"fuz1\") >= 0");
Ben Murdoch097c5b22016-05-18 11:27:45 +010011030 ExpectTrue("names.indexOf(\"objects\") >= 0");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011031 ExpectTrue("names.indexOf(\"fuz2\") >= 0");
11032 ExpectFalse("names[1005] == undefined");
11033}
11034
11035
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011036// Getting property names of an object with a hidden and inherited
11037// prototype should not duplicate the accessor properties inherited.
11038THREADED_TEST(Regress269562) {
11039 i::FLAG_allow_natives_syntax = true;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000011040 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011041 v8::HandleScope handle_scope(context->GetIsolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000011042
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011043 Local<v8::FunctionTemplate> t1 =
11044 v8::FunctionTemplate::New(context->GetIsolate());
11045 t1->SetHiddenPrototype(true);
11046
11047 Local<v8::ObjectTemplate> i1 = t1->InstanceTemplate();
11048 i1->SetAccessor(v8_str("foo"),
11049 SimpleAccessorGetter, SimpleAccessorSetter);
11050 i1->SetAccessor(v8_str("bar"),
11051 SimpleAccessorGetter, SimpleAccessorSetter);
11052 i1->SetAccessor(v8_str("baz"),
11053 SimpleAccessorGetter, SimpleAccessorSetter);
11054 i1->Set(v8_str("n1"), v8_num(1));
11055 i1->Set(v8_str("n2"), v8_num(2));
11056
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011057 Local<v8::Object> o1 = t1->GetFunction(context.local())
11058 .ToLocalChecked()
11059 ->NewInstance(context.local())
11060 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011061 Local<v8::FunctionTemplate> t2 =
11062 v8::FunctionTemplate::New(context->GetIsolate());
11063 t2->SetHiddenPrototype(true);
11064
11065 // Inherit from t1 and mark prototype as hidden.
11066 t2->Inherit(t1);
11067 t2->InstanceTemplate()->Set(v8_str("mine"), v8_num(4));
11068
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011069 Local<v8::Object> o2 = t2->GetFunction(context.local())
11070 .ToLocalChecked()
11071 ->NewInstance(context.local())
11072 .ToLocalChecked();
11073 CHECK(o2->SetPrototype(context.local(), o1).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011074
11075 v8::Local<v8::Symbol> sym =
11076 v8::Symbol::New(context->GetIsolate(), v8_str("s1"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011077 CHECK(o1->Set(context.local(), sym, v8_num(3)).FromJust());
11078 o1->SetPrivate(context.local(),
11079 v8::Private::New(context->GetIsolate(), v8_str("h1")),
11080 v8::Integer::New(context->GetIsolate(), 2013))
11081 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011082
11083 // Call the runtime version of GetOwnPropertyNames() on
11084 // the natively created object through JavaScript.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011085 CHECK(context->Global()->Set(context.local(), v8_str("obj"), o2).FromJust());
11086 CHECK(context->Global()->Set(context.local(), v8_str("sym"), sym).FromJust());
11087 // PROPERTY_FILTER_NONE = 0
11088 CompileRun("var names = %GetOwnPropertyKeys(obj, 0);");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011089
11090 ExpectInt32("names.length", 7);
11091 ExpectTrue("names.indexOf(\"foo\") >= 0");
11092 ExpectTrue("names.indexOf(\"bar\") >= 0");
11093 ExpectTrue("names.indexOf(\"baz\") >= 0");
11094 ExpectTrue("names.indexOf(\"n1\") >= 0");
11095 ExpectTrue("names.indexOf(\"n2\") >= 0");
11096 ExpectTrue("names.indexOf(sym) >= 0");
11097 ExpectTrue("names.indexOf(\"mine\") >= 0");
11098}
11099
11100
11101THREADED_TEST(FunctionReadOnlyPrototype) {
11102 LocalContext context;
11103 v8::Isolate* isolate = context->GetIsolate();
11104 v8::HandleScope handle_scope(isolate);
11105
11106 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
11107 t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
Ben Murdoch69a99ed2011-11-30 16:03:39 +000011108 t1->ReadOnlyPrototype();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011109 CHECK(context->Global()
11110 ->Set(context.local(), v8_str("func1"),
11111 t1->GetFunction(context.local()).ToLocalChecked())
11112 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000011113 // Configured value of ReadOnly flag.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011114 CHECK(
11115 CompileRun(
11116 "(function() {"
11117 " descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
11118 " return (descriptor['writable'] == false);"
11119 "})()")
11120 ->BooleanValue(context.local())
11121 .FromJust());
11122 CHECK_EQ(
11123 42,
11124 CompileRun("func1.prototype.x")->Int32Value(context.local()).FromJust());
11125 CHECK_EQ(42, CompileRun("func1.prototype = {}; func1.prototype.x")
11126 ->Int32Value(context.local())
11127 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000011128
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011129 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
11130 t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011131 CHECK(context->Global()
11132 ->Set(context.local(), v8_str("func2"),
11133 t2->GetFunction(context.local()).ToLocalChecked())
11134 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000011135 // Default value of ReadOnly flag.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011136 CHECK(
11137 CompileRun(
11138 "(function() {"
11139 " descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
11140 " return (descriptor['writable'] == true);"
11141 "})()")
11142 ->BooleanValue(context.local())
11143 .FromJust());
11144 CHECK_EQ(
11145 42,
11146 CompileRun("func2.prototype.x")->Int32Value(context.local()).FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000011147}
11148
11149
Andrei Popescu402d9372010-02-26 13:31:12 +000011150THREADED_TEST(SetPrototypeThrows) {
Andrei Popescu402d9372010-02-26 13:31:12 +000011151 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011152 v8::Isolate* isolate = context->GetIsolate();
11153 v8::HandleScope handle_scope(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000011154
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011155 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000011156
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011157 Local<v8::Object> o0 = t->GetFunction(context.local())
11158 .ToLocalChecked()
11159 ->NewInstance(context.local())
11160 .ToLocalChecked();
11161 Local<v8::Object> o1 = t->GetFunction(context.local())
11162 .ToLocalChecked()
11163 ->NewInstance(context.local())
11164 .ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000011165
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011166 CHECK(o0->SetPrototype(context.local(), o1).FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000011167 // If setting the prototype leads to the cycle, SetPrototype should
11168 // return false and keep VM in sane state.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011169 v8::TryCatch try_catch(isolate);
11170 CHECK(o1->SetPrototype(context.local(), o0).IsNothing());
Andrei Popescu402d9372010-02-26 13:31:12 +000011171 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011172 CHECK(!CcTest::i_isolate()->has_pending_exception());
Andrei Popescu402d9372010-02-26 13:31:12 +000011173
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011174 CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")
11175 ->Int32Value(context.local())
11176 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000011177}
11178
11179
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011180THREADED_TEST(FunctionRemovePrototype) {
Steve Blocka7e24c12009-10-30 11:49:00 +000011181 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011182 v8::Isolate* isolate = context->GetIsolate();
11183 v8::HandleScope handle_scope(isolate);
11184
11185 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
11186 t1->RemovePrototype();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011187 Local<v8::Function> fun = t1->GetFunction(context.local()).ToLocalChecked();
11188 CHECK(context->Global()->Set(context.local(), v8_str("fun"), fun).FromJust());
11189 CHECK(!CompileRun("'prototype' in fun")
11190 ->BooleanValue(context.local())
11191 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011192
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011193 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011194 CompileRun("new fun()");
11195 CHECK(try_catch.HasCaught());
11196
11197 try_catch.Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011198 CHECK(fun->NewInstance(context.local()).IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011199 CHECK(try_catch.HasCaught());
11200}
11201
11202
11203THREADED_TEST(GetterSetterExceptions) {
11204 LocalContext context;
11205 v8::Isolate* isolate = context->GetIsolate();
11206 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011207 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011208 "function Foo() { };"
11209 "function Throw() { throw 5; };"
11210 "var x = { };"
11211 "x.__defineSetter__('set', Throw);"
11212 "x.__defineGetter__('get', Throw);");
11213 Local<v8::Object> x = Local<v8::Object>::Cast(
11214 context->Global()->Get(context.local(), v8_str("x")).ToLocalChecked());
11215 v8::TryCatch try_catch(isolate);
11216 CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
11217 .IsNothing());
11218 CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
11219 CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
11220 .IsNothing());
11221 CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
11222 CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
11223 .IsNothing());
11224 CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
11225 CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
11226 .IsNothing());
11227 CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000011228}
11229
11230
11231THREADED_TEST(Constructor) {
Steve Blocka7e24c12009-10-30 11:49:00 +000011232 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011233 v8::Isolate* isolate = context->GetIsolate();
11234 v8::HandleScope handle_scope(isolate);
11235 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011236 templ->SetClassName(v8_str("Fun"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011237 Local<Function> cons = templ->GetFunction(context.local()).ToLocalChecked();
11238 CHECK(
11239 context->Global()->Set(context.local(), v8_str("Fun"), cons).FromJust());
11240 Local<v8::Object> inst = cons->NewInstance(context.local()).ToLocalChecked();
11241 i::Handle<i::JSReceiver> obj(v8::Utils::OpenHandle(*inst));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011242 CHECK(obj->IsJSObject());
Steve Blocka7e24c12009-10-30 11:49:00 +000011243 Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011244 CHECK(value->BooleanValue(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011245}
11246
Ben Murdoch257744e2011-11-30 15:57:28 +000011247
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011248static void ConstructorCallback(
11249 const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch257744e2011-11-30 15:57:28 +000011250 ApiTestFuzzer::Fuzz();
11251 Local<Object> This;
11252
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011253 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
Ben Murdoch257744e2011-11-30 15:57:28 +000011254 if (args.IsConstructCall()) {
11255 Local<Object> Holder = args.Holder();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011256 This = Object::New(args.GetIsolate());
Ben Murdoch257744e2011-11-30 15:57:28 +000011257 Local<Value> proto = Holder->GetPrototype();
11258 if (proto->IsObject()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011259 This->SetPrototype(context, proto).FromJust();
Ben Murdoch257744e2011-11-30 15:57:28 +000011260 }
11261 } else {
11262 This = args.This();
11263 }
11264
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011265 This->Set(context, v8_str("a"), args[0]).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011266 args.GetReturnValue().Set(This);
Ben Murdoch257744e2011-11-30 15:57:28 +000011267}
11268
11269
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011270static void FakeConstructorCallback(
11271 const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch257744e2011-11-30 15:57:28 +000011272 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011273 args.GetReturnValue().Set(args[0]);
Ben Murdoch257744e2011-11-30 15:57:28 +000011274}
11275
11276
11277THREADED_TEST(ConstructorForObject) {
Ben Murdoch257744e2011-11-30 15:57:28 +000011278 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011279 v8::Isolate* isolate = context->GetIsolate();
11280 v8::HandleScope handle_scope(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011281
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011282 {
11283 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011284 instance_template->SetCallAsFunctionHandler(ConstructorCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011285 Local<Object> instance =
11286 instance_template->NewInstance(context.local()).ToLocalChecked();
11287 CHECK(context->Global()
11288 ->Set(context.local(), v8_str("obj"), instance)
11289 .FromJust());
11290 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011291 Local<Value> value;
11292 CHECK(!try_catch.HasCaught());
11293
11294 // Call the Object's constructor with a 32-bit signed integer.
11295 value = CompileRun("(function() { var o = new obj(28); return o.a; })()");
11296 CHECK(!try_catch.HasCaught());
11297 CHECK(value->IsInt32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011298 CHECK_EQ(28, value->Int32Value(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011299
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011300 Local<Value> args1[] = {v8_num(28)};
11301 Local<Value> value_obj1 =
11302 instance->CallAsConstructor(context.local(), 1, args1).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011303 CHECK(value_obj1->IsObject());
11304 Local<Object> object1 = Local<Object>::Cast(value_obj1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011305 value = object1->Get(context.local(), v8_str("a")).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011306 CHECK(value->IsInt32());
11307 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011308 CHECK_EQ(28, value->Int32Value(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011309
11310 // Call the Object's constructor with a String.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011311 value =
11312 CompileRun("(function() { var o = new obj('tipli'); return o.a; })()");
Ben Murdoch257744e2011-11-30 15:57:28 +000011313 CHECK(!try_catch.HasCaught());
11314 CHECK(value->IsString());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011315 String::Utf8Value string_value1(
11316 value->ToString(context.local()).ToLocalChecked());
11317 CHECK_EQ(0, strcmp("tipli", *string_value1));
Ben Murdoch257744e2011-11-30 15:57:28 +000011318
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011319 Local<Value> args2[] = {v8_str("tipli")};
11320 Local<Value> value_obj2 =
11321 instance->CallAsConstructor(context.local(), 1, args2).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011322 CHECK(value_obj2->IsObject());
11323 Local<Object> object2 = Local<Object>::Cast(value_obj2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011324 value = object2->Get(context.local(), v8_str("a")).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011325 CHECK(!try_catch.HasCaught());
11326 CHECK(value->IsString());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011327 String::Utf8Value string_value2(
11328 value->ToString(context.local()).ToLocalChecked());
11329 CHECK_EQ(0, strcmp("tipli", *string_value2));
Ben Murdoch257744e2011-11-30 15:57:28 +000011330
11331 // Call the Object's constructor with a Boolean.
11332 value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
11333 CHECK(!try_catch.HasCaught());
11334 CHECK(value->IsBoolean());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011335 CHECK_EQ(true, value->BooleanValue(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011336
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011337 Local<Value> args3[] = {v8::True(isolate)};
11338 Local<Value> value_obj3 =
11339 instance->CallAsConstructor(context.local(), 1, args3).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011340 CHECK(value_obj3->IsObject());
11341 Local<Object> object3 = Local<Object>::Cast(value_obj3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011342 value = object3->Get(context.local(), v8_str("a")).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011343 CHECK(!try_catch.HasCaught());
11344 CHECK(value->IsBoolean());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011345 CHECK_EQ(true, value->BooleanValue(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011346
11347 // Call the Object's constructor with undefined.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011348 Local<Value> args4[] = {v8::Undefined(isolate)};
11349 Local<Value> value_obj4 =
11350 instance->CallAsConstructor(context.local(), 1, args4).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011351 CHECK(value_obj4->IsObject());
11352 Local<Object> object4 = Local<Object>::Cast(value_obj4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011353 value = object4->Get(context.local(), v8_str("a")).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011354 CHECK(!try_catch.HasCaught());
11355 CHECK(value->IsUndefined());
11356
11357 // Call the Object's constructor with null.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011358 Local<Value> args5[] = {v8::Null(isolate)};
11359 Local<Value> value_obj5 =
11360 instance->CallAsConstructor(context.local(), 1, args5).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011361 CHECK(value_obj5->IsObject());
11362 Local<Object> object5 = Local<Object>::Cast(value_obj5);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011363 value = object5->Get(context.local(), v8_str("a")).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011364 CHECK(!try_catch.HasCaught());
11365 CHECK(value->IsNull());
11366 }
11367
11368 // Check exception handling when there is no constructor set for the Object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011369 {
11370 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
11371 Local<Object> instance =
11372 instance_template->NewInstance(context.local()).ToLocalChecked();
11373 CHECK(context->Global()
11374 ->Set(context.local(), v8_str("obj2"), instance)
11375 .FromJust());
11376 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011377 Local<Value> value;
11378 CHECK(!try_catch.HasCaught());
11379
11380 value = CompileRun("new obj2(28)");
11381 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011382 String::Utf8Value exception_value1(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011383 CHECK_EQ(0,
11384 strcmp("TypeError: obj2 is not a constructor", *exception_value1));
Ben Murdoch257744e2011-11-30 15:57:28 +000011385 try_catch.Reset();
11386
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011387 Local<Value> args[] = {v8_num(29)};
11388 CHECK(instance->CallAsConstructor(context.local(), 1, args).IsEmpty());
Ben Murdoch257744e2011-11-30 15:57:28 +000011389 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011390 String::Utf8Value exception_value2(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011391 CHECK_EQ(
11392 0, strcmp("TypeError: object is not a constructor", *exception_value2));
Ben Murdoch257744e2011-11-30 15:57:28 +000011393 try_catch.Reset();
11394 }
11395
11396 // Check the case when constructor throws exception.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011397 {
11398 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011399 instance_template->SetCallAsFunctionHandler(ThrowValue);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011400 Local<Object> instance =
11401 instance_template->NewInstance(context.local()).ToLocalChecked();
11402 CHECK(context->Global()
11403 ->Set(context.local(), v8_str("obj3"), instance)
11404 .FromJust());
11405 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011406 Local<Value> value;
11407 CHECK(!try_catch.HasCaught());
11408
11409 value = CompileRun("new obj3(22)");
11410 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011411 String::Utf8Value exception_value1(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011412 CHECK_EQ(0, strcmp("22", *exception_value1));
Ben Murdoch257744e2011-11-30 15:57:28 +000011413 try_catch.Reset();
11414
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011415 Local<Value> args[] = {v8_num(23)};
11416 CHECK(instance->CallAsConstructor(context.local(), 1, args).IsEmpty());
Ben Murdoch257744e2011-11-30 15:57:28 +000011417 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011418 String::Utf8Value exception_value2(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011419 CHECK_EQ(0, strcmp("23", *exception_value2));
Ben Murdoch257744e2011-11-30 15:57:28 +000011420 try_catch.Reset();
11421 }
11422
11423 // Check whether constructor returns with an object or non-object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011424 {
11425 Local<FunctionTemplate> function_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011426 FunctionTemplate::New(isolate, FakeConstructorCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011427 Local<Function> function =
11428 function_template->GetFunction(context.local()).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011429 Local<Object> instance1 = function;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011430 CHECK(context->Global()
11431 ->Set(context.local(), v8_str("obj4"), instance1)
11432 .FromJust());
11433 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011434 Local<Value> value;
11435 CHECK(!try_catch.HasCaught());
11436
11437 CHECK(instance1->IsObject());
11438 CHECK(instance1->IsFunction());
11439
11440 value = CompileRun("new obj4(28)");
11441 CHECK(!try_catch.HasCaught());
11442 CHECK(value->IsObject());
11443
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011444 Local<Value> args1[] = {v8_num(28)};
11445 value = instance1->CallAsConstructor(context.local(), 1, args1)
11446 .ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011447 CHECK(!try_catch.HasCaught());
11448 CHECK(value->IsObject());
11449
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011450 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011451 instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011452 Local<Object> instance2 =
11453 instance_template->NewInstance(context.local()).ToLocalChecked();
11454 CHECK(context->Global()
11455 ->Set(context.local(), v8_str("obj5"), instance2)
11456 .FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011457 CHECK(!try_catch.HasCaught());
11458
11459 CHECK(instance2->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011460 CHECK(instance2->IsFunction());
Ben Murdoch257744e2011-11-30 15:57:28 +000011461
11462 value = CompileRun("new obj5(28)");
11463 CHECK(!try_catch.HasCaught());
11464 CHECK(!value->IsObject());
11465
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011466 Local<Value> args2[] = {v8_num(28)};
11467 value = instance2->CallAsConstructor(context.local(), 1, args2)
11468 .ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011469 CHECK(!try_catch.HasCaught());
11470 CHECK(!value->IsObject());
11471 }
11472}
11473
11474
Steve Blocka7e24c12009-10-30 11:49:00 +000011475THREADED_TEST(FunctionDescriptorException) {
Steve Blocka7e24c12009-10-30 11:49:00 +000011476 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011477 v8::Isolate* isolate = context->GetIsolate();
11478 v8::HandleScope handle_scope(isolate);
11479 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011480 templ->SetClassName(v8_str("Fun"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011481 Local<Function> cons = templ->GetFunction(context.local()).ToLocalChecked();
11482 CHECK(
11483 context->Global()->Set(context.local(), v8_str("Fun"), cons).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011484 Local<Value> value = CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011485 "function test() {"
11486 " try {"
11487 " (new Fun()).blah()"
11488 " } catch (e) {"
11489 " var str = String(e);"
11490 // " if (str.indexOf('TypeError') == -1) return 1;"
11491 // " if (str.indexOf('[object Fun]') != -1) return 2;"
11492 // " if (str.indexOf('#<Fun>') == -1) return 3;"
11493 " return 0;"
11494 " }"
11495 " return 4;"
11496 "}"
11497 "test();");
11498 CHECK_EQ(0, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011499}
11500
11501
11502THREADED_TEST(EvalAliasedDynamic) {
Steve Blocka7e24c12009-10-30 11:49:00 +000011503 LocalContext current;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011504 v8::HandleScope scope(current->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000011505
11506 // Tests where aliased eval can only be resolved dynamically.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011507 Local<Script> script = v8_compile(
11508 "function f(x) { "
11509 " var foo = 2;"
11510 " with (x) { return eval('foo'); }"
11511 "}"
11512 "foo = 0;"
11513 "result1 = f(new Object());"
11514 "result2 = f(this);"
11515 "var x = new Object();"
11516 "x.eval = function(x) { return 1; };"
11517 "result3 = f(x);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011518 script->Run(current.local()).ToLocalChecked();
11519 CHECK_EQ(2, current->Global()
11520 ->Get(current.local(), v8_str("result1"))
11521 .ToLocalChecked()
11522 ->Int32Value(current.local())
11523 .FromJust());
11524 CHECK_EQ(0, current->Global()
11525 ->Get(current.local(), v8_str("result2"))
11526 .ToLocalChecked()
11527 ->Int32Value(current.local())
11528 .FromJust());
11529 CHECK_EQ(1, current->Global()
11530 ->Get(current.local(), v8_str("result3"))
11531 .ToLocalChecked()
11532 ->Int32Value(current.local())
11533 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011534
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011535 v8::TryCatch try_catch(current->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011536 script = v8_compile(
11537 "function f(x) { "
11538 " var bar = 2;"
11539 " with (x) { return eval('bar'); }"
11540 "}"
11541 "result4 = f(this)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011542 script->Run(current.local()).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011543 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011544 CHECK_EQ(2, current->Global()
11545 ->Get(current.local(), v8_str("result4"))
11546 .ToLocalChecked()
11547 ->Int32Value(current.local())
11548 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011549
Steve Blocka7e24c12009-10-30 11:49:00 +000011550 try_catch.Reset();
11551}
11552
11553
11554THREADED_TEST(CrossEval) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011555 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000011556 LocalContext other;
11557 LocalContext current;
11558
11559 Local<String> token = v8_str("<security token>");
11560 other->SetSecurityToken(token);
11561 current->SetSecurityToken(token);
11562
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011563 // Set up reference from current to other.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011564 CHECK(current->Global()
11565 ->Set(current.local(), v8_str("other"), other->Global())
11566 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011567
11568 // Check that new variables are introduced in other context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011569 Local<Script> script = v8_compile("other.eval('var foo = 1234')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011570 script->Run(current.local()).ToLocalChecked();
11571 Local<Value> foo =
11572 other->Global()->Get(current.local(), v8_str("foo")).ToLocalChecked();
11573 CHECK_EQ(1234, foo->Int32Value(other.local()).FromJust());
11574 CHECK(!current->Global()->Has(current.local(), v8_str("foo")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011575
11576 // Check that writing to non-existing properties introduces them in
11577 // the other context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011578 script = v8_compile("other.eval('na = 1234')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011579 script->Run(current.local()).ToLocalChecked();
11580 CHECK_EQ(1234, other->Global()
11581 ->Get(current.local(), v8_str("na"))
11582 .ToLocalChecked()
11583 ->Int32Value(other.local())
11584 .FromJust());
11585 CHECK(!current->Global()->Has(current.local(), v8_str("na")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011586
11587 // Check that global variables in current context are not visible in other
11588 // context.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011589 v8::TryCatch try_catch(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011590 script = v8_compile("var bar = 42; other.eval('bar');");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011591 CHECK(script->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000011592 CHECK(try_catch.HasCaught());
11593 try_catch.Reset();
11594
11595 // Check that local variables in current context are not visible in other
11596 // context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011597 script = v8_compile(
11598 "(function() { "
11599 " var baz = 87;"
11600 " return other.eval('baz');"
11601 "})();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011602 CHECK(script->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000011603 CHECK(try_catch.HasCaught());
11604 try_catch.Reset();
11605
11606 // Check that global variables in the other environment are visible
11607 // when evaluting code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011608 CHECK(other->Global()
11609 ->Set(other.local(), v8_str("bis"), v8_num(1234))
11610 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011611 script = v8_compile("other.eval('bis')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011612 CHECK_EQ(1234, script->Run(current.local())
11613 .ToLocalChecked()
11614 ->Int32Value(current.local())
11615 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011616 CHECK(!try_catch.HasCaught());
11617
11618 // Check that the 'this' pointer points to the global object evaluating
11619 // code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011620 CHECK(other->Global()
11621 ->Set(current.local(), v8_str("t"), other->Global())
11622 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011623 script = v8_compile("other.eval('this == t')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011624 Local<Value> result = script->Run(current.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000011625 CHECK(result->IsTrue());
11626 CHECK(!try_catch.HasCaught());
11627
11628 // Check that variables introduced in with-statement are not visible in
11629 // other context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011630 script = v8_compile("with({x:2}){other.eval('x')}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011631 CHECK(script->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000011632 CHECK(try_catch.HasCaught());
11633 try_catch.Reset();
11634
11635 // Check that you cannot use 'eval.call' with another object than the
11636 // current global object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011637 script = v8_compile("other.y = 1; eval.call(other, 'y')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011638 CHECK(script->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000011639 CHECK(try_catch.HasCaught());
11640}
11641
11642
11643// Test that calling eval in a context which has been detached from
Emily Bernierd0a1eb72015-03-24 16:35:39 -040011644// its global proxy works.
Steve Blocka7e24c12009-10-30 11:49:00 +000011645THREADED_TEST(EvalInDetachedGlobal) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011646 v8::Isolate* isolate = CcTest::isolate();
11647 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011648
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011649 v8::Local<Context> context0 = Context::New(isolate);
11650 v8::Local<Context> context1 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011651
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011652 // Set up function in context0 that uses eval from context0.
Steve Blocka7e24c12009-10-30 11:49:00 +000011653 context0->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011654 v8::Local<v8::Value> fun = CompileRun(
11655 "var x = 42;"
11656 "(function() {"
11657 " var e = eval;"
11658 " return function(s) { return e(s); }"
11659 "})()");
Steve Blocka7e24c12009-10-30 11:49:00 +000011660 context0->Exit();
11661
11662 // Put the function into context1 and call it before and after
11663 // detaching the global. Before detaching, the call succeeds and
11664 // after detaching and exception is thrown.
11665 context1->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011666 CHECK(context1->Global()->Set(context1, v8_str("fun"), fun).FromJust());
11667 v8::Local<v8::Value> x_value = CompileRun("fun('x')");
11668 CHECK_EQ(42, x_value->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011669 context0->DetachGlobal();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011670 v8::TryCatch catcher(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011671 x_value = CompileRun("fun('x')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011672 CHECK_EQ(42, x_value->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011673 context1->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +000011674}
11675
11676
11677THREADED_TEST(CrossLazyLoad) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011678 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000011679 LocalContext other;
11680 LocalContext current;
11681
11682 Local<String> token = v8_str("<security token>");
11683 other->SetSecurityToken(token);
11684 current->SetSecurityToken(token);
11685
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011686 // Set up reference from current to other.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011687 CHECK(current->Global()
11688 ->Set(current.local(), v8_str("other"), other->Global())
11689 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011690
11691 // Trigger lazy loading in other context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011692 Local<Script> script = v8_compile("other.eval('new Date(42)')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011693 Local<Value> value = script->Run(current.local()).ToLocalChecked();
11694 CHECK_EQ(42.0, value->NumberValue(current.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011695}
11696
11697
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011698static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
Andrei Popescu402d9372010-02-26 13:31:12 +000011699 ApiTestFuzzer::Fuzz();
Steve Blocka7e24c12009-10-30 11:49:00 +000011700 if (args.IsConstructCall()) {
11701 if (args[0]->IsInt32()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011702 args.GetReturnValue().Set(
11703 v8_num(-args[0]
11704 ->Int32Value(args.GetIsolate()->GetCurrentContext())
11705 .FromJust()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011706 return;
Steve Blocka7e24c12009-10-30 11:49:00 +000011707 }
11708 }
11709
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011710 args.GetReturnValue().Set(args[0]);
11711}
11712
11713
11714static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
11715 args.GetReturnValue().Set(args.This());
Steve Blocka7e24c12009-10-30 11:49:00 +000011716}
11717
11718
11719// Test that a call handler can be set for objects which will allow
11720// non-function objects created through the API to be called as
11721// functions.
11722THREADED_TEST(CallAsFunction) {
Steve Blocka7e24c12009-10-30 11:49:00 +000011723 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011724 v8::Isolate* isolate = context->GetIsolate();
11725 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011726
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011727 {
11728 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011729 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
11730 instance_template->SetCallAsFunctionHandler(call_as_function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011731 Local<v8::Object> instance = t->GetFunction(context.local())
11732 .ToLocalChecked()
11733 ->NewInstance(context.local())
11734 .ToLocalChecked();
11735 CHECK(context->Global()
11736 ->Set(context.local(), v8_str("obj"), instance)
11737 .FromJust());
11738 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011739 Local<Value> value;
11740 CHECK(!try_catch.HasCaught());
Steve Blocka7e24c12009-10-30 11:49:00 +000011741
Ben Murdoch257744e2011-11-30 15:57:28 +000011742 value = CompileRun("obj(42)");
11743 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011744 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011745
Ben Murdoch257744e2011-11-30 15:57:28 +000011746 value = CompileRun("(function(o){return o(49)})(obj)");
11747 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011748 CHECK_EQ(49, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011749
Ben Murdoch257744e2011-11-30 15:57:28 +000011750 // test special case of call as function
11751 value = CompileRun("[obj]['0'](45)");
11752 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011753 CHECK_EQ(45, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011754
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011755 value = CompileRun(
11756 "obj.call = Function.prototype.call;"
11757 "obj.call(null, 87)");
Ben Murdoch257744e2011-11-30 15:57:28 +000011758 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011759 CHECK_EQ(87, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011760
Ben Murdoch257744e2011-11-30 15:57:28 +000011761 // Regression tests for bug #1116356: Calling call through call/apply
11762 // must work for non-function receivers.
11763 const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
11764 value = CompileRun(apply_99);
11765 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011766 CHECK_EQ(99, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011767
Ben Murdoch257744e2011-11-30 15:57:28 +000011768 const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
11769 value = CompileRun(call_17);
11770 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011771 CHECK_EQ(17, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011772
Ben Murdoch257744e2011-11-30 15:57:28 +000011773 // Check that the call-as-function handler can be called through
11774 // new.
11775 value = CompileRun("new obj(43)");
11776 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011777 CHECK_EQ(-43, value->Int32Value(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011778
11779 // Check that the call-as-function handler can be called through
11780 // the API.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011781 v8::Local<Value> args[] = {v8_num(28)};
11782 value = instance->CallAsFunction(context.local(), instance, 1, args)
11783 .ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011784 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011785 CHECK_EQ(28, value->Int32Value(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011786 }
11787
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011788 {
11789 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011790 Local<ObjectTemplate> instance_template(t->InstanceTemplate());
11791 USE(instance_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011792 Local<v8::Object> instance = t->GetFunction(context.local())
11793 .ToLocalChecked()
11794 ->NewInstance(context.local())
11795 .ToLocalChecked();
11796 CHECK(context->Global()
11797 ->Set(context.local(), v8_str("obj2"), instance)
11798 .FromJust());
11799 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011800 Local<Value> value;
11801 CHECK(!try_catch.HasCaught());
11802
11803 // Call an object without call-as-function handler through the JS
11804 value = CompileRun("obj2(28)");
11805 CHECK(value.IsEmpty());
11806 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011807 String::Utf8Value exception_value1(try_catch.Exception());
11808 // TODO(verwaest): Better message
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011809 CHECK_EQ(0, strcmp("TypeError: obj2 is not a function", *exception_value1));
Ben Murdoch257744e2011-11-30 15:57:28 +000011810 try_catch.Reset();
11811
11812 // Call an object without call-as-function handler through the API
11813 value = CompileRun("obj2(28)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011814 v8::Local<Value> args[] = {v8_num(28)};
11815 CHECK(
11816 instance->CallAsFunction(context.local(), instance, 1, args).IsEmpty());
Ben Murdoch257744e2011-11-30 15:57:28 +000011817 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011818 String::Utf8Value exception_value2(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011819 CHECK_EQ(0,
11820 strcmp("TypeError: object is not a function", *exception_value2));
Ben Murdoch257744e2011-11-30 15:57:28 +000011821 try_catch.Reset();
11822 }
11823
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011824 {
11825 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011826 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
11827 instance_template->SetCallAsFunctionHandler(ThrowValue);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011828 Local<v8::Object> instance = t->GetFunction(context.local())
11829 .ToLocalChecked()
11830 ->NewInstance(context.local())
11831 .ToLocalChecked();
11832 CHECK(context->Global()
11833 ->Set(context.local(), v8_str("obj3"), instance)
11834 .FromJust());
11835 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011836 Local<Value> value;
11837 CHECK(!try_catch.HasCaught());
11838
11839 // Catch the exception which is thrown by call-as-function handler
11840 value = CompileRun("obj3(22)");
11841 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011842 String::Utf8Value exception_value1(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011843 CHECK_EQ(0, strcmp("22", *exception_value1));
Ben Murdoch257744e2011-11-30 15:57:28 +000011844 try_catch.Reset();
11845
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011846 v8::Local<Value> args[] = {v8_num(23)};
11847 CHECK(
11848 instance->CallAsFunction(context.local(), instance, 1, args).IsEmpty());
Ben Murdoch257744e2011-11-30 15:57:28 +000011849 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011850 String::Utf8Value exception_value2(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011851 CHECK_EQ(0, strcmp("23", *exception_value2));
Ben Murdoch257744e2011-11-30 15:57:28 +000011852 try_catch.Reset();
11853 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011854
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011855 {
11856 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011857 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
11858 instance_template->SetCallAsFunctionHandler(ReturnThis);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011859 Local<v8::Object> instance = t->GetFunction(context.local())
11860 .ToLocalChecked()
11861 ->NewInstance(context.local())
11862 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011863
11864 Local<v8::Value> a1 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011865 instance->CallAsFunction(context.local(), v8::Undefined(isolate), 0,
11866 NULL)
11867 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011868 CHECK(a1->StrictEquals(instance));
11869 Local<v8::Value> a2 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011870 instance->CallAsFunction(context.local(), v8::Null(isolate), 0, NULL)
11871 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011872 CHECK(a2->StrictEquals(instance));
11873 Local<v8::Value> a3 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011874 instance->CallAsFunction(context.local(), v8_num(42), 0, NULL)
11875 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011876 CHECK(a3->StrictEquals(instance));
11877 Local<v8::Value> a4 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011878 instance->CallAsFunction(context.local(), v8_str("hello"), 0, NULL)
11879 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011880 CHECK(a4->StrictEquals(instance));
11881 Local<v8::Value> a5 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011882 instance->CallAsFunction(context.local(), v8::True(isolate), 0, NULL)
11883 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011884 CHECK(a5->StrictEquals(instance));
11885 }
11886
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011887 {
11888 CompileRun(
11889 "function ReturnThisSloppy() {"
11890 " return this;"
11891 "}"
11892 "function ReturnThisStrict() {"
11893 " 'use strict';"
11894 " return this;"
11895 "}");
11896 Local<Function> ReturnThisSloppy = Local<Function>::Cast(
11897 context->Global()
11898 ->Get(context.local(), v8_str("ReturnThisSloppy"))
11899 .ToLocalChecked());
11900 Local<Function> ReturnThisStrict = Local<Function>::Cast(
11901 context->Global()
11902 ->Get(context.local(), v8_str("ReturnThisStrict"))
11903 .ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011904
11905 Local<v8::Value> a1 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011906 ReturnThisSloppy->CallAsFunction(context.local(),
11907 v8::Undefined(isolate), 0, NULL)
11908 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011909 CHECK(a1->StrictEquals(context->Global()));
11910 Local<v8::Value> a2 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011911 ReturnThisSloppy->CallAsFunction(context.local(), v8::Null(isolate), 0,
11912 NULL)
11913 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011914 CHECK(a2->StrictEquals(context->Global()));
11915 Local<v8::Value> a3 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011916 ReturnThisSloppy->CallAsFunction(context.local(), v8_num(42), 0, NULL)
11917 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011918 CHECK(a3->IsNumberObject());
11919 CHECK_EQ(42.0, a3.As<v8::NumberObject>()->ValueOf());
11920 Local<v8::Value> a4 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011921 ReturnThisSloppy->CallAsFunction(context.local(), v8_str("hello"), 0,
11922 NULL)
11923 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011924 CHECK(a4->IsStringObject());
11925 CHECK(a4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
11926 Local<v8::Value> a5 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011927 ReturnThisSloppy->CallAsFunction(context.local(), v8::True(isolate), 0,
11928 NULL)
11929 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011930 CHECK(a5->IsBooleanObject());
11931 CHECK(a5.As<v8::BooleanObject>()->ValueOf());
11932
11933 Local<v8::Value> a6 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011934 ReturnThisStrict->CallAsFunction(context.local(),
11935 v8::Undefined(isolate), 0, NULL)
11936 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011937 CHECK(a6->IsUndefined());
11938 Local<v8::Value> a7 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011939 ReturnThisStrict->CallAsFunction(context.local(), v8::Null(isolate), 0,
11940 NULL)
11941 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011942 CHECK(a7->IsNull());
11943 Local<v8::Value> a8 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011944 ReturnThisStrict->CallAsFunction(context.local(), v8_num(42), 0, NULL)
11945 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011946 CHECK(a8->StrictEquals(v8_num(42)));
11947 Local<v8::Value> a9 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011948 ReturnThisStrict->CallAsFunction(context.local(), v8_str("hello"), 0,
11949 NULL)
11950 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011951 CHECK(a9->StrictEquals(v8_str("hello")));
11952 Local<v8::Value> a10 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011953 ReturnThisStrict->CallAsFunction(context.local(), v8::True(isolate), 0,
11954 NULL)
11955 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011956 CHECK(a10->StrictEquals(v8::True(isolate)));
11957 }
Ben Murdoch257744e2011-11-30 15:57:28 +000011958}
11959
11960
11961// Check whether a non-function object is callable.
11962THREADED_TEST(CallableObject) {
Ben Murdoch257744e2011-11-30 15:57:28 +000011963 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011964 v8::Isolate* isolate = context->GetIsolate();
11965 v8::HandleScope scope(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011966
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011967 {
11968 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011969 instance_template->SetCallAsFunctionHandler(call_as_function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011970 Local<Object> instance =
11971 instance_template->NewInstance(context.local()).ToLocalChecked();
11972 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011973
11974 CHECK(instance->IsCallable());
11975 CHECK(!try_catch.HasCaught());
11976 }
11977
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011978 {
11979 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
11980 Local<Object> instance =
11981 instance_template->NewInstance(context.local()).ToLocalChecked();
11982 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011983
11984 CHECK(!instance->IsCallable());
11985 CHECK(!try_catch.HasCaught());
11986 }
11987
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011988 {
11989 Local<FunctionTemplate> function_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011990 FunctionTemplate::New(isolate, call_as_function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011991 Local<Function> function =
11992 function_template->GetFunction(context.local()).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011993 Local<Object> instance = function;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011994 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011995
11996 CHECK(instance->IsCallable());
11997 CHECK(!try_catch.HasCaught());
11998 }
11999
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012000 {
12001 Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate);
12002 Local<Function> function =
12003 function_template->GetFunction(context.local()).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000012004 Local<Object> instance = function;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012005 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000012006
12007 CHECK(instance->IsCallable());
12008 CHECK(!try_catch.HasCaught());
12009 }
Steve Blocka7e24c12009-10-30 11:49:00 +000012010}
12011
12012
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012013THREADED_TEST(Regress567998) {
12014 LocalContext env;
12015 v8::HandleScope scope(env->GetIsolate());
12016
12017 Local<v8::FunctionTemplate> desc =
12018 v8::FunctionTemplate::New(env->GetIsolate());
12019 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
12020 desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis); // callable
12021
12022 Local<v8::Object> obj = desc->GetFunction(env.local())
12023 .ToLocalChecked()
12024 ->NewInstance(env.local())
12025 .ToLocalChecked();
12026 CHECK(
12027 env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
12028
12029 ExpectString("undetectable.toString()", "[object Object]");
12030 ExpectString("typeof undetectable", "undefined");
12031 ExpectString("typeof(undetectable)", "undefined");
12032 ExpectBoolean("typeof undetectable == 'undefined'", true);
12033 ExpectBoolean("typeof undetectable == 'object'", false);
12034 ExpectBoolean("if (undetectable) { true; } else { false; }", false);
12035 ExpectBoolean("!undetectable", true);
12036
12037 ExpectObject("true&&undetectable", obj);
12038 ExpectBoolean("false&&undetectable", false);
12039 ExpectBoolean("true||undetectable", true);
12040 ExpectObject("false||undetectable", obj);
12041
12042 ExpectObject("undetectable&&true", obj);
12043 ExpectObject("undetectable&&false", obj);
12044 ExpectBoolean("undetectable||true", true);
12045 ExpectBoolean("undetectable||false", false);
12046
12047 ExpectBoolean("undetectable==null", true);
12048 ExpectBoolean("null==undetectable", true);
12049 ExpectBoolean("undetectable==undefined", true);
12050 ExpectBoolean("undefined==undetectable", true);
12051 ExpectBoolean("undetectable==undetectable", true);
12052
12053 ExpectBoolean("undetectable===null", false);
12054 ExpectBoolean("null===undetectable", false);
12055 ExpectBoolean("undetectable===undefined", false);
12056 ExpectBoolean("undefined===undetectable", false);
12057 ExpectBoolean("undetectable===undetectable", true);
12058}
12059
12060
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012061static int Recurse(v8::Isolate* isolate, int depth, int iterations) {
12062 v8::HandleScope scope(isolate);
12063 if (depth == 0) return v8::HandleScope::NumberOfHandles(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000012064 for (int i = 0; i < iterations; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012065 Local<v8::Number> n(v8::Integer::New(isolate, 42));
Steve Blocka7e24c12009-10-30 11:49:00 +000012066 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012067 return Recurse(isolate, depth - 1, iterations);
Steve Blocka7e24c12009-10-30 11:49:00 +000012068}
12069
12070
12071THREADED_TEST(HandleIteration) {
12072 static const int kIterations = 500;
12073 static const int kNesting = 200;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012074 LocalContext context;
12075 v8::Isolate* isolate = context->GetIsolate();
12076 v8::HandleScope scope0(isolate);
12077 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000012078 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012079 v8::HandleScope scope1(isolate);
12080 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000012081 for (int i = 0; i < kIterations; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012082 Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
12083 CHECK_EQ(i + 1, v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000012084 }
12085
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012086 CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000012087 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012088 v8::HandleScope scope2(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000012089 for (int j = 0; j < kIterations; j++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012090 Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
12091 CHECK_EQ(j + 1 + kIterations,
12092 v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000012093 }
12094 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012095 CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000012096 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012097 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
12098 CHECK_EQ(kNesting * kIterations, Recurse(isolate, kNesting, kIterations));
Steve Blocka7e24c12009-10-30 11:49:00 +000012099}
12100
12101
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012102static void InterceptorCallICFastApi(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012103 Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012104 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012105 CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
12106 int* call_count =
12107 reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
Andrei Popescu402d9372010-02-26 13:31:12 +000012108 ++(*call_count);
12109 if ((*call_count) % 20 == 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012110 CcTest::heap()->CollectAllGarbage();
Andrei Popescu402d9372010-02-26 13:31:12 +000012111 }
Andrei Popescu402d9372010-02-26 13:31:12 +000012112}
12113
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012114static void FastApiCallback_TrivialSignature(
12115 const v8::FunctionCallbackInfo<v8::Value>& args) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012116 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012117 CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
12118 v8::Isolate* isolate = CcTest::isolate();
12119 CHECK_EQ(isolate, args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012120 CHECK(args.This()
12121 ->Equals(isolate->GetCurrentContext(), args.Holder())
12122 .FromJust());
12123 CHECK(args.Data()
12124 ->Equals(isolate->GetCurrentContext(), v8_str("method_data"))
12125 .FromJust());
12126 args.GetReturnValue().Set(
12127 args[0]->Int32Value(isolate->GetCurrentContext()).FromJust() + 1);
Andrei Popescu402d9372010-02-26 13:31:12 +000012128}
12129
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012130static void FastApiCallback_SimpleSignature(
12131 const v8::FunctionCallbackInfo<v8::Value>& args) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012132 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012133 CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
12134 v8::Isolate* isolate = CcTest::isolate();
12135 CHECK_EQ(isolate, args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012136 CHECK(args.This()
12137 ->GetPrototype()
12138 ->Equals(isolate->GetCurrentContext(), args.Holder())
12139 .FromJust());
12140 CHECK(args.Data()
12141 ->Equals(isolate->GetCurrentContext(), v8_str("method_data"))
12142 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012143 // Note, we're using HasRealNamedProperty instead of Has to avoid
12144 // invoking the interceptor again.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012145 CHECK(args.Holder()
12146 ->HasRealNamedProperty(isolate->GetCurrentContext(), v8_str("foo"))
12147 .FromJust());
12148 args.GetReturnValue().Set(
12149 args[0]->Int32Value(isolate->GetCurrentContext()).FromJust() + 1);
Andrei Popescu402d9372010-02-26 13:31:12 +000012150}
12151
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012152
Andrei Popescu402d9372010-02-26 13:31:12 +000012153// Helper to maximize the odds of object moving.
12154static void GenerateSomeGarbage() {
12155 CompileRun(
12156 "var garbage;"
12157 "for (var i = 0; i < 1000; i++) {"
12158 " garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
12159 "}"
12160 "garbage = undefined;");
12161}
12162
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012163
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012164void DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Block1e0659c2011-05-24 12:43:12 +010012165 static int count = 0;
12166 if (count++ % 3 == 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012167 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012168 // This should move the stub
Steve Block1e0659c2011-05-24 12:43:12 +010012169 GenerateSomeGarbage(); // This should ensure the old stub memory is flushed
12170 }
Steve Block1e0659c2011-05-24 12:43:12 +010012171}
12172
12173
12174THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
Steve Block1e0659c2011-05-24 12:43:12 +010012175 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012176 v8::Isolate* isolate = context->GetIsolate();
12177 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012178 v8::Local<v8::ObjectTemplate> nativeobject_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012179 v8::ObjectTemplate::New(isolate);
12180 nativeobject_templ->Set(isolate, "callback",
12181 v8::FunctionTemplate::New(isolate,
12182 DirectApiCallback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012183 v8::Local<v8::Object> nativeobject_obj =
12184 nativeobject_templ->NewInstance(context.local()).ToLocalChecked();
12185 CHECK(context->Global()
12186 ->Set(context.local(), v8_str("nativeobject"), nativeobject_obj)
12187 .FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +010012188 // call the api function multiple times to ensure direct call stub creation.
12189 CompileRun(
12190 "function f() {"
12191 " for (var i = 1; i <= 30; i++) {"
12192 " nativeobject.callback();"
12193 " }"
12194 "}"
12195 "f();");
12196}
12197
12198
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012199void ThrowingDirectApiCallback(
12200 const v8::FunctionCallbackInfo<v8::Value>& args) {
12201 args.GetIsolate()->ThrowException(v8_str("g"));
Steve Block1e0659c2011-05-24 12:43:12 +010012202}
12203
12204
12205THREADED_TEST(CallICFastApi_DirectCall_Throw) {
Steve Block1e0659c2011-05-24 12:43:12 +010012206 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012207 v8::Isolate* isolate = context->GetIsolate();
12208 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012209 v8::Local<v8::ObjectTemplate> nativeobject_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012210 v8::ObjectTemplate::New(isolate);
12211 nativeobject_templ->Set(isolate, "callback",
12212 v8::FunctionTemplate::New(isolate,
12213 ThrowingDirectApiCallback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012214 v8::Local<v8::Object> nativeobject_obj =
12215 nativeobject_templ->NewInstance(context.local()).ToLocalChecked();
12216 CHECK(context->Global()
12217 ->Set(context.local(), v8_str("nativeobject"), nativeobject_obj)
12218 .FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +010012219 // call the api function multiple times to ensure direct call stub creation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012220 v8::Local<Value> result = CompileRun(
Steve Block1e0659c2011-05-24 12:43:12 +010012221 "var result = '';"
12222 "function f() {"
12223 " for (var i = 1; i <= 5; i++) {"
12224 " try { nativeobject.callback(); } catch (e) { result += e; }"
12225 " }"
12226 "}"
12227 "f(); result;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012228 CHECK(v8_str("ggggg")->Equals(context.local(), result).FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +010012229}
12230
12231
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012232static int p_getter_count_3;
12233
12234
12235static Local<Value> DoDirectGetter() {
12236 if (++p_getter_count_3 % 3 == 0) {
12237 CcTest::heap()->CollectAllGarbage();
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012238 GenerateSomeGarbage();
12239 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012240 return v8_str("Direct Getter Result");
12241}
12242
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012243
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012244static void DirectGetterCallback(
12245 Local<String> name,
12246 const v8::PropertyCallbackInfo<v8::Value>& info) {
12247 CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
12248 info.GetReturnValue().Set(DoDirectGetter());
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012249}
12250
12251
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012252template<typename Accessor>
12253static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012254 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012255 v8::Isolate* isolate = context->GetIsolate();
12256 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012257 v8::Local<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012258 obj->SetAccessor(v8_str("p1"), accessor);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012259 CHECK(context->Global()
12260 ->Set(context.local(), v8_str("o1"),
12261 obj->NewInstance(context.local()).ToLocalChecked())
12262 .FromJust());
12263 p_getter_count_3 = 0;
12264 v8::Local<v8::Value> result = CompileRun(
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012265 "function f() {"
12266 " for (var i = 0; i < 30; i++) o1.p1;"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012267 " return o1.p1"
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012268 "}"
12269 "f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012270 CHECK(v8_str("Direct Getter Result")
12271 ->Equals(context.local(), result)
12272 .FromJust());
12273 CHECK_EQ(31, p_getter_count_3);
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012274}
12275
12276
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012277THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
12278 LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
12279}
12280
12281
12282void ThrowingDirectGetterCallback(
12283 Local<String> name,
12284 const v8::PropertyCallbackInfo<v8::Value>& info) {
12285 info.GetIsolate()->ThrowException(v8_str("g"));
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012286}
12287
12288
12289THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012290 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012291 v8::Isolate* isolate = context->GetIsolate();
12292 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012293 v8::Local<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012294 obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012295 CHECK(context->Global()
12296 ->Set(context.local(), v8_str("o1"),
12297 obj->NewInstance(context.local()).ToLocalChecked())
12298 .FromJust());
12299 v8::Local<Value> result = CompileRun(
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012300 "var result = '';"
12301 "for (var i = 0; i < 5; i++) {"
12302 " try { o1.p1; } catch (e) { result += e; }"
12303 "}"
12304 "result;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012305 CHECK(v8_str("ggggg")->Equals(context.local(), result).FromJust());
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012306}
12307
12308
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012309THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012310 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012311 v8::Isolate* isolate = CcTest::isolate();
12312 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012313 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012314 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012315 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
12316 isolate, FastApiCallback_TrivialSignature, v8_str("method_data"),
12317 v8::Local<v8::Signature>());
12318 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012319 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012320 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012321 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012322 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012323 v8::External::New(isolate, &interceptor_call_count)));
Andrei Popescu402d9372010-02-26 13:31:12 +000012324 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012325 v8::Local<v8::Function> fun =
12326 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012327 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012328 CHECK(context->Global()
12329 ->Set(context.local(), v8_str("o"),
12330 fun->NewInstance(context.local()).ToLocalChecked())
12331 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012332 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012333 "var result = 0;"
12334 "for (var i = 0; i < 100; i++) {"
12335 " result = o.method(41);"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012336 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012337 CHECK_EQ(42, context->Global()
12338 ->Get(context.local(), v8_str("result"))
12339 .ToLocalChecked()
12340 ->Int32Value(context.local())
12341 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012342 CHECK_EQ(100, interceptor_call_count);
12343}
12344
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012345
12346THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012347 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012348 v8::Isolate* isolate = CcTest::isolate();
12349 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012350 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012351 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012352 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012353 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12354 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012355 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012356 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012357 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012358 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012359 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012360 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012361 v8::External::New(isolate, &interceptor_call_count)));
Andrei Popescu402d9372010-02-26 13:31:12 +000012362 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012363 v8::Local<v8::Function> fun =
12364 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012365 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012366 CHECK(context->Global()
12367 ->Set(context.local(), v8_str("o"),
12368 fun->NewInstance(context.local()).ToLocalChecked())
12369 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012370 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012371 "o.foo = 17;"
12372 "var receiver = {};"
12373 "receiver.__proto__ = o;"
12374 "var result = 0;"
12375 "for (var i = 0; i < 100; i++) {"
12376 " result = receiver.method(41);"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012377 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012378 CHECK_EQ(42, context->Global()
12379 ->Get(context.local(), v8_str("result"))
12380 .ToLocalChecked()
12381 ->Int32Value(context.local())
12382 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012383 CHECK_EQ(100, interceptor_call_count);
12384}
12385
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012386
12387THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012388 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012389 v8::Isolate* isolate = CcTest::isolate();
12390 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012391 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012392 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012393 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012394 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12395 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012396 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012397 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012398 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012399 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012400 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012401 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012402 v8::External::New(isolate, &interceptor_call_count)));
Andrei Popescu402d9372010-02-26 13:31:12 +000012403 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012404 v8::Local<v8::Function> fun =
12405 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012406 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012407 CHECK(context->Global()
12408 ->Set(context.local(), v8_str("o"),
12409 fun->NewInstance(context.local()).ToLocalChecked())
12410 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012411 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012412 "o.foo = 17;"
12413 "var receiver = {};"
12414 "receiver.__proto__ = o;"
12415 "var result = 0;"
12416 "var saved_result = 0;"
12417 "for (var i = 0; i < 100; i++) {"
12418 " result = receiver.method(41);"
12419 " if (i == 50) {"
12420 " saved_result = result;"
12421 " receiver = {method: function(x) { return x - 1 }};"
12422 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012423 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012424 CHECK_EQ(40, context->Global()
12425 ->Get(context.local(), v8_str("result"))
12426 .ToLocalChecked()
12427 ->Int32Value(context.local())
12428 .FromJust());
12429 CHECK_EQ(42, context->Global()
12430 ->Get(context.local(), v8_str("saved_result"))
12431 .ToLocalChecked()
12432 ->Int32Value(context.local())
12433 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012434 CHECK_GE(interceptor_call_count, 50);
12435}
12436
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012437
12438THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012439 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012440 v8::Isolate* isolate = CcTest::isolate();
12441 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012442 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012443 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012444 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012445 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12446 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012447 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012448 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012449 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012450 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012451 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012452 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012453 v8::External::New(isolate, &interceptor_call_count)));
Andrei Popescu402d9372010-02-26 13:31:12 +000012454 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012455 v8::Local<v8::Function> fun =
12456 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012457 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012458 CHECK(context->Global()
12459 ->Set(context.local(), v8_str("o"),
12460 fun->NewInstance(context.local()).ToLocalChecked())
12461 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012462 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012463 "o.foo = 17;"
12464 "var receiver = {};"
12465 "receiver.__proto__ = o;"
12466 "var result = 0;"
12467 "var saved_result = 0;"
12468 "for (var i = 0; i < 100; i++) {"
12469 " result = receiver.method(41);"
12470 " if (i == 50) {"
12471 " saved_result = result;"
12472 " o.method = function(x) { return x - 1 };"
12473 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012474 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012475 CHECK_EQ(40, context->Global()
12476 ->Get(context.local(), v8_str("result"))
12477 .ToLocalChecked()
12478 ->Int32Value(context.local())
12479 .FromJust());
12480 CHECK_EQ(42, context->Global()
12481 ->Get(context.local(), v8_str("saved_result"))
12482 .ToLocalChecked()
12483 ->Int32Value(context.local())
12484 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012485 CHECK_GE(interceptor_call_count, 50);
12486}
12487
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012488
12489THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
Steve Block6ded16b2010-05-10 14:33:55 +010012490 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012491 v8::Isolate* isolate = CcTest::isolate();
12492 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012493 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012494 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012495 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012496 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12497 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012498 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Steve Block6ded16b2010-05-10 14:33:55 +010012499 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012500 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012501 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012502 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012503 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012504 v8::External::New(isolate, &interceptor_call_count)));
Steve Block6ded16b2010-05-10 14:33:55 +010012505 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012506 v8::Local<v8::Function> fun =
12507 fun_templ->GetFunction(context.local()).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +010012508 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012509 CHECK(context->Global()
12510 ->Set(context.local(), v8_str("o"),
12511 fun->NewInstance(context.local()).ToLocalChecked())
12512 .FromJust());
12513 v8::TryCatch try_catch(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012514 CompileRun(
Steve Block6ded16b2010-05-10 14:33:55 +010012515 "o.foo = 17;"
12516 "var receiver = {};"
12517 "receiver.__proto__ = o;"
12518 "var result = 0;"
12519 "var saved_result = 0;"
12520 "for (var i = 0; i < 100; i++) {"
12521 " result = receiver.method(41);"
12522 " if (i == 50) {"
12523 " saved_result = result;"
12524 " receiver = 333;"
12525 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012526 "}");
Steve Block6ded16b2010-05-10 14:33:55 +010012527 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012528 // TODO(verwaest): Adjust message.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012529 CHECK(
12530 v8_str("TypeError: receiver.method is not a function")
12531 ->Equals(
12532 context.local(),
12533 try_catch.Exception()->ToString(context.local()).ToLocalChecked())
12534 .FromJust());
12535 CHECK_EQ(42, context->Global()
12536 ->Get(context.local(), v8_str("saved_result"))
12537 .ToLocalChecked()
12538 ->Int32Value(context.local())
12539 .FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +010012540 CHECK_GE(interceptor_call_count, 50);
12541}
12542
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012543
12544THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012545 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012546 v8::Isolate* isolate = CcTest::isolate();
12547 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012548 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012549 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012550 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012551 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12552 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012553 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012554 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012555 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012556 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012557 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012558 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012559 v8::External::New(isolate, &interceptor_call_count)));
Andrei Popescu402d9372010-02-26 13:31:12 +000012560 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012561 v8::Local<v8::Function> fun =
12562 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012563 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012564 CHECK(context->Global()
12565 ->Set(context.local(), v8_str("o"),
12566 fun->NewInstance(context.local()).ToLocalChecked())
12567 .FromJust());
12568 v8::TryCatch try_catch(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012569 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012570 "o.foo = 17;"
12571 "var receiver = {};"
12572 "receiver.__proto__ = o;"
12573 "var result = 0;"
12574 "var saved_result = 0;"
12575 "for (var i = 0; i < 100; i++) {"
12576 " result = receiver.method(41);"
12577 " if (i == 50) {"
12578 " saved_result = result;"
12579 " receiver = {method: receiver.method};"
12580 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012581 "}");
Andrei Popescu402d9372010-02-26 13:31:12 +000012582 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012583 CHECK(
12584 v8_str("TypeError: Illegal invocation")
12585 ->Equals(
12586 context.local(),
12587 try_catch.Exception()->ToString(context.local()).ToLocalChecked())
12588 .FromJust());
12589 CHECK_EQ(42, context->Global()
12590 ->Get(context.local(), v8_str("saved_result"))
12591 .ToLocalChecked()
12592 ->Int32Value(context.local())
12593 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012594 CHECK_GE(interceptor_call_count, 50);
12595}
12596
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012597
12598THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
12599 v8::Isolate* isolate = CcTest::isolate();
12600 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012601 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012602 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012603 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
12604 isolate, FastApiCallback_TrivialSignature, v8_str("method_data"),
12605 v8::Local<v8::Signature>());
12606 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012607 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012608 v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012609 USE(templ);
Andrei Popescu402d9372010-02-26 13:31:12 +000012610 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012611 v8::Local<v8::Function> fun =
12612 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012613 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012614 CHECK(context->Global()
12615 ->Set(context.local(), v8_str("o"),
12616 fun->NewInstance(context.local()).ToLocalChecked())
12617 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012618 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012619 "var result = 0;"
12620 "for (var i = 0; i < 100; i++) {"
12621 " result = o.method(41);"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012622 "}");
Andrei Popescu402d9372010-02-26 13:31:12 +000012623
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012624 CHECK_EQ(42, context->Global()
12625 ->Get(context.local(), v8_str("result"))
12626 .ToLocalChecked()
12627 ->Int32Value(context.local())
12628 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012629}
12630
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012631
12632THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
12633 v8::Isolate* isolate = CcTest::isolate();
12634 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012635 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012636 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012637 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012638 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12639 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012640 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012641 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012642 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012643 v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012644 CHECK(!templ.IsEmpty());
Andrei Popescu402d9372010-02-26 13:31:12 +000012645 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012646 v8::Local<v8::Function> fun =
12647 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012648 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012649 CHECK(context->Global()
12650 ->Set(context.local(), v8_str("o"),
12651 fun->NewInstance(context.local()).ToLocalChecked())
12652 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012653 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012654 "o.foo = 17;"
12655 "var receiver = {};"
12656 "receiver.__proto__ = o;"
12657 "var result = 0;"
12658 "for (var i = 0; i < 100; i++) {"
12659 " result = receiver.method(41);"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012660 "}");
Andrei Popescu402d9372010-02-26 13:31:12 +000012661
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012662 CHECK_EQ(42, context->Global()
12663 ->Get(context.local(), v8_str("result"))
12664 .ToLocalChecked()
12665 ->Int32Value(context.local())
12666 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012667}
12668
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012669
12670THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
12671 v8::Isolate* isolate = CcTest::isolate();
12672 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012673 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012674 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012675 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012676 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12677 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012678 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012679 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012680 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012681 v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012682 CHECK(!templ.IsEmpty());
Andrei Popescu402d9372010-02-26 13:31:12 +000012683 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012684 v8::Local<v8::Function> fun =
12685 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012686 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012687 CHECK(context->Global()
12688 ->Set(context.local(), v8_str("o"),
12689 fun->NewInstance(context.local()).ToLocalChecked())
12690 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012691 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012692 "o.foo = 17;"
12693 "var receiver = {};"
12694 "receiver.__proto__ = o;"
12695 "var result = 0;"
12696 "var saved_result = 0;"
12697 "for (var i = 0; i < 100; i++) {"
12698 " result = receiver.method(41);"
12699 " if (i == 50) {"
12700 " saved_result = result;"
12701 " receiver = {method: function(x) { return x - 1 }};"
12702 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012703 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012704 CHECK_EQ(40, context->Global()
12705 ->Get(context.local(), v8_str("result"))
12706 .ToLocalChecked()
12707 ->Int32Value(context.local())
12708 .FromJust());
12709 CHECK_EQ(42, context->Global()
12710 ->Get(context.local(), v8_str("saved_result"))
12711 .ToLocalChecked()
12712 ->Int32Value(context.local())
12713 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012714}
12715
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012716
12717THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
12718 v8::Isolate* isolate = CcTest::isolate();
12719 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012720 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012721 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012722 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012723 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12724 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012725 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Steve Block6ded16b2010-05-10 14:33:55 +010012726 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012727 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012728 v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012729 CHECK(!templ.IsEmpty());
Steve Block6ded16b2010-05-10 14:33:55 +010012730 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012731 v8::Local<v8::Function> fun =
12732 fun_templ->GetFunction(context.local()).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +010012733 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012734 CHECK(context->Global()
12735 ->Set(context.local(), v8_str("o"),
12736 fun->NewInstance(context.local()).ToLocalChecked())
12737 .FromJust());
12738 v8::TryCatch try_catch(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012739 CompileRun(
Steve Block6ded16b2010-05-10 14:33:55 +010012740 "o.foo = 17;"
12741 "var receiver = {};"
12742 "receiver.__proto__ = o;"
12743 "var result = 0;"
12744 "var saved_result = 0;"
12745 "for (var i = 0; i < 100; i++) {"
12746 " result = receiver.method(41);"
12747 " if (i == 50) {"
12748 " saved_result = result;"
12749 " receiver = 333;"
12750 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012751 "}");
Steve Block6ded16b2010-05-10 14:33:55 +010012752 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012753 // TODO(verwaest): Adjust message.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012754 CHECK(
12755 v8_str("TypeError: receiver.method is not a function")
12756 ->Equals(
12757 context.local(),
12758 try_catch.Exception()->ToString(context.local()).ToLocalChecked())
12759 .FromJust());
12760 CHECK_EQ(42, context->Global()
12761 ->Get(context.local(), v8_str("saved_result"))
12762 .ToLocalChecked()
12763 ->Int32Value(context.local())
12764 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012765}
12766
12767
12768THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) {
12769 v8::Isolate* isolate = CcTest::isolate();
12770 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012771 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012772 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012773 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012774 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12775 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012776 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012777 proto_templ->Set(v8_str("method"), method_templ);
12778 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012779 v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012780 CHECK(!templ.IsEmpty());
12781 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012782 v8::Local<v8::Function> fun =
12783 fun_templ->GetFunction(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012784 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012785 CHECK(context->Global()
12786 ->Set(context.local(), v8_str("o"),
12787 fun->NewInstance(context.local()).ToLocalChecked())
12788 .FromJust());
12789 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012790 CompileRun(
12791 "o.foo = 17;"
12792 "var receiver = {};"
12793 "receiver.__proto__ = o;"
12794 "var result = 0;"
12795 "var saved_result = 0;"
12796 "for (var i = 0; i < 100; i++) {"
12797 " result = receiver.method(41);"
12798 " if (i == 50) {"
12799 " saved_result = result;"
12800 " receiver = Object.create(receiver);"
12801 " }"
12802 "}");
12803 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012804 CHECK(
12805 v8_str("TypeError: Illegal invocation")
12806 ->Equals(
12807 context.local(),
12808 try_catch.Exception()->ToString(context.local()).ToLocalChecked())
12809 .FromJust());
12810 CHECK_EQ(42, context->Global()
12811 ->Get(context.local(), v8_str("saved_result"))
12812 .ToLocalChecked()
12813 ->Int32Value(context.local())
12814 .FromJust());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010012815}
12816
12817
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012818static void ThrowingGetter(Local<String> name,
12819 const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010012820 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012821 info.GetIsolate()->ThrowException(Local<Value>());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012822 info.GetReturnValue().SetUndefined();
Ben Murdoch8b112d22011-06-08 16:22:53 +010012823}
12824
12825
12826THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010012827 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012828 HandleScope scope(context->GetIsolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012829
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012830 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012831 Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
12832 instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
12833
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012834 Local<Object> instance = templ->GetFunction(context.local())
12835 .ToLocalChecked()
12836 ->NewInstance(context.local())
12837 .ToLocalChecked();
Ben Murdoch8b112d22011-06-08 16:22:53 +010012838
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012839 Local<Object> another = Object::New(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012840 CHECK(another->SetPrototype(context.local(), instance).FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012841
12842 Local<Object> with_js_getter = CompileRun(
12843 "o = {};\n"
12844 "o.__defineGetter__('f', function() { throw undefined; });\n"
12845 "o\n").As<Object>();
12846 CHECK(!with_js_getter.IsEmpty());
12847
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012848 TryCatch try_catch(context->GetIsolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012849
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012850 v8::MaybeLocal<Value> result =
12851 instance->GetRealNamedProperty(context.local(), v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012852 CHECK(try_catch.HasCaught());
12853 try_catch.Reset();
12854 CHECK(result.IsEmpty());
12855
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012856 Maybe<PropertyAttribute> attr =
12857 instance->GetRealNamedPropertyAttributes(context.local(), v8_str("f"));
12858 CHECK(!try_catch.HasCaught());
12859 CHECK(Just(None) == attr);
12860
12861 result = another->GetRealNamedProperty(context.local(), v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012862 CHECK(try_catch.HasCaught());
12863 try_catch.Reset();
12864 CHECK(result.IsEmpty());
12865
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012866 attr = another->GetRealNamedPropertyAttributes(context.local(), v8_str("f"));
12867 CHECK(!try_catch.HasCaught());
12868 CHECK(Just(None) == attr);
12869
12870 result = another->GetRealNamedPropertyInPrototypeChain(context.local(),
12871 v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012872 CHECK(try_catch.HasCaught());
12873 try_catch.Reset();
12874 CHECK(result.IsEmpty());
12875
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012876 attr = another->GetRealNamedPropertyAttributesInPrototypeChain(
12877 context.local(), v8_str("f"));
12878 CHECK(!try_catch.HasCaught());
12879 CHECK(Just(None) == attr);
12880
12881 result = another->Get(context.local(), v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012882 CHECK(try_catch.HasCaught());
12883 try_catch.Reset();
12884 CHECK(result.IsEmpty());
12885
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012886 result = with_js_getter->GetRealNamedProperty(context.local(), v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012887 CHECK(try_catch.HasCaught());
12888 try_catch.Reset();
12889 CHECK(result.IsEmpty());
12890
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012891 attr = with_js_getter->GetRealNamedPropertyAttributes(context.local(),
12892 v8_str("f"));
12893 CHECK(!try_catch.HasCaught());
12894 CHECK(Just(None) == attr);
12895
12896 result = with_js_getter->Get(context.local(), v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012897 CHECK(try_catch.HasCaught());
12898 try_catch.Reset();
12899 CHECK(result.IsEmpty());
Ben Murdochda12d292016-06-02 14:46:10 +010012900
12901 Local<Object> target = CompileRun("({})").As<Object>();
12902 Local<Object> handler = CompileRun("({})").As<Object>();
12903 Local<v8::Proxy> proxy =
12904 v8::Proxy::New(context.local(), target, handler).ToLocalChecked();
12905
12906 result = target->GetRealNamedProperty(context.local(), v8_str("f"));
12907 CHECK(!try_catch.HasCaught());
12908 CHECK(result.IsEmpty());
12909
12910 result = proxy->GetRealNamedProperty(context.local(), v8_str("f"));
12911 CHECK(!try_catch.HasCaught());
12912 CHECK(result.IsEmpty());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012913}
12914
12915
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012916static void ThrowingCallbackWithTryCatch(
12917 const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012918 TryCatch try_catch(args.GetIsolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012919 // Verboseness is important: it triggers message delivery which can call into
12920 // external code.
12921 try_catch.SetVerbose(true);
12922 CompileRun("throw 'from JS';");
12923 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012924 CHECK(!CcTest::i_isolate()->has_pending_exception());
12925 CHECK(!CcTest::i_isolate()->has_scheduled_exception());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012926}
12927
12928
12929static int call_depth;
12930
12931
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012932static void WithTryCatch(Local<Message> message, Local<Value> data) {
12933 TryCatch try_catch(CcTest::isolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012934}
12935
12936
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012937static void ThrowFromJS(Local<Message> message, Local<Value> data) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010012938 if (--call_depth) CompileRun("throw 'ThrowInJS';");
12939}
12940
12941
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012942static void ThrowViaApi(Local<Message> message, Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012943 if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012944}
12945
12946
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012947static void WebKitLike(Local<Message> message, Local<Value> data) {
12948 Local<String> errorMessageString = message->Get();
Ben Murdoch8b112d22011-06-08 16:22:53 +010012949 CHECK(!errorMessageString.IsEmpty());
12950 message->GetStackTrace();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012951 message->GetScriptOrigin().ResourceName();
Ben Murdoch8b112d22011-06-08 16:22:53 +010012952}
12953
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012954
Ben Murdoch8b112d22011-06-08 16:22:53 +010012955THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010012956 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012957 v8::Isolate* isolate = context->GetIsolate();
12958 HandleScope scope(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +010012959
12960 Local<Function> func =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012961 FunctionTemplate::New(isolate, ThrowingCallbackWithTryCatch)
12962 ->GetFunction(context.local())
12963 .ToLocalChecked();
12964 CHECK(
12965 context->Global()->Set(context.local(), v8_str("func"), func).FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012966
12967 MessageCallback callbacks[] =
12968 { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
12969 for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
12970 MessageCallback callback = callbacks[i];
12971 if (callback != NULL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012972 isolate->AddMessageListener(callback);
Ben Murdoch8b112d22011-06-08 16:22:53 +010012973 }
Ben Murdoch257744e2011-11-30 15:57:28 +000012974 // Some small number to control number of times message handler should
12975 // throw an exception.
Ben Murdoch8b112d22011-06-08 16:22:53 +010012976 call_depth = 5;
12977 ExpectFalse(
12978 "var thrown = false;\n"
12979 "try { func(); } catch(e) { thrown = true; }\n"
12980 "thrown\n");
12981 if (callback != NULL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012982 isolate->RemoveMessageListeners(callback);
Ben Murdoch8b112d22011-06-08 16:22:53 +010012983 }
12984 }
12985}
12986
12987
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012988static void ParentGetter(Local<String> name,
12989 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +000012990 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012991 info.GetReturnValue().Set(v8_num(1));
Steve Blocka7e24c12009-10-30 11:49:00 +000012992}
12993
12994
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012995static void ChildGetter(Local<String> name,
12996 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +000012997 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012998 info.GetReturnValue().Set(v8_num(42));
Steve Blocka7e24c12009-10-30 11:49:00 +000012999}
13000
13001
13002THREADED_TEST(Overriding) {
Steve Blocka7e24c12009-10-30 11:49:00 +000013003 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013004 v8::Isolate* isolate = context->GetIsolate();
13005 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000013006
13007 // Parent template.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013008 Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000013009 Local<ObjectTemplate> parent_instance_templ =
13010 parent_templ->InstanceTemplate();
13011 parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
13012
13013 // Template that inherits from the parent template.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013014 Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000013015 Local<ObjectTemplate> child_instance_templ =
13016 child_templ->InstanceTemplate();
13017 child_templ->Inherit(parent_templ);
13018 // Override 'f'. The child version of 'f' should get called for child
13019 // instances.
13020 child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
13021 // Add 'g' twice. The 'g' added last should get called for instances.
13022 child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
13023 child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
13024
13025 // Add 'h' as an accessor to the proto template with ReadOnly attributes
13026 // so 'h' can be shadowed on the instance object.
13027 Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
13028 child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013029 v8::Local<Value>(), v8::DEFAULT, v8::ReadOnly);
Steve Blocka7e24c12009-10-30 11:49:00 +000013030
13031 // Add 'i' as an accessor to the instance template with ReadOnly attributes
13032 // but the attribute does not have effect because it is duplicated with
13033 // NULL setter.
13034 child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013035 v8::Local<Value>(), v8::DEFAULT,
13036 v8::ReadOnly);
Steve Blocka7e24c12009-10-30 11:49:00 +000013037
13038
13039 // Instantiate the child template.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013040 Local<v8::Object> instance = child_templ->GetFunction(context.local())
13041 .ToLocalChecked()
13042 ->NewInstance(context.local())
13043 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000013044
13045 // Check that the child function overrides the parent one.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013046 CHECK(context->Global()
13047 ->Set(context.local(), v8_str("o"), instance)
13048 .FromJust());
13049 Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000013050 // Check that the 'g' that was added last is hit.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013051 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
13052 value = v8_compile("o.g")->Run(context.local()).ToLocalChecked();
13053 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013054
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013055 // Check that 'h' cannot be shadowed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013056 value = v8_compile("o.h = 3; o.h")->Run(context.local()).ToLocalChecked();
13057 CHECK_EQ(1, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013058
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013059 // Check that 'i' cannot be shadowed or changed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013060 value = v8_compile("o.i = 3; o.i")->Run(context.local()).ToLocalChecked();
13061 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013062}
13063
13064
Ben Murdoch097c5b22016-05-18 11:27:45 +010013065static void ShouldThrowOnErrorGetter(
13066 Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
13067 ApiTestFuzzer::Fuzz();
13068 v8::Isolate* isolate = info.GetIsolate();
13069 Local<Boolean> should_throw_on_error =
13070 Boolean::New(isolate, info.ShouldThrowOnError());
13071 info.GetReturnValue().Set(should_throw_on_error);
13072}
13073
13074
13075template <typename T>
13076static void ShouldThrowOnErrorSetter(Local<Name> name, Local<v8::Value> value,
13077 const v8::PropertyCallbackInfo<T>& info) {
13078 ApiTestFuzzer::Fuzz();
13079 v8::Isolate* isolate = info.GetIsolate();
13080 auto context = isolate->GetCurrentContext();
13081 Local<Boolean> should_throw_on_error_value =
13082 Boolean::New(isolate, info.ShouldThrowOnError());
13083 CHECK(context->Global()
13084 ->Set(isolate->GetCurrentContext(), v8_str("should_throw_setter"),
13085 should_throw_on_error_value)
13086 .FromJust());
13087}
13088
13089
13090THREADED_TEST(AccessorShouldThrowOnError) {
Ben Murdoch097c5b22016-05-18 11:27:45 +010013091 LocalContext context;
13092 v8::Isolate* isolate = context->GetIsolate();
13093 v8::HandleScope scope(isolate);
13094 Local<Object> global = context->Global();
13095
13096 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
13097 Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
13098 instance_templ->SetAccessor(v8_str("f"), ShouldThrowOnErrorGetter,
13099 ShouldThrowOnErrorSetter<void>);
13100
13101 Local<v8::Object> instance = templ->GetFunction(context.local())
13102 .ToLocalChecked()
13103 ->NewInstance(context.local())
13104 .ToLocalChecked();
13105
13106 CHECK(global->Set(context.local(), v8_str("o"), instance).FromJust());
13107
13108 // SLOPPY mode
13109 Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
13110 CHECK(value->IsFalse());
13111 v8_compile("o.f = 153")->Run(context.local()).ToLocalChecked();
13112 value = global->Get(context.local(), v8_str("should_throw_setter"))
13113 .ToLocalChecked();
13114 CHECK(value->IsFalse());
13115
13116 // STRICT mode
13117 value = v8_compile("'use strict';o.f")->Run(context.local()).ToLocalChecked();
13118 CHECK(value->IsFalse());
13119 v8_compile("'use strict'; o.f = 153")->Run(context.local()).ToLocalChecked();
13120 value = global->Get(context.local(), v8_str("should_throw_setter"))
13121 .ToLocalChecked();
13122 CHECK(value->IsTrue());
Ben Murdoch097c5b22016-05-18 11:27:45 +010013123}
13124
13125
13126static void ShouldThrowOnErrorQuery(
13127 Local<Name> name, const v8::PropertyCallbackInfo<v8::Integer>& info) {
13128 ApiTestFuzzer::Fuzz();
13129 v8::Isolate* isolate = info.GetIsolate();
13130 info.GetReturnValue().Set(v8::None);
13131
13132 auto context = isolate->GetCurrentContext();
13133 Local<Boolean> should_throw_on_error_value =
13134 Boolean::New(isolate, info.ShouldThrowOnError());
13135 CHECK(context->Global()
13136 ->Set(isolate->GetCurrentContext(), v8_str("should_throw_query"),
13137 should_throw_on_error_value)
13138 .FromJust());
13139}
13140
13141
13142static void ShouldThrowOnErrorDeleter(
13143 Local<Name> name, const v8::PropertyCallbackInfo<v8::Boolean>& info) {
13144 ApiTestFuzzer::Fuzz();
13145 v8::Isolate* isolate = info.GetIsolate();
13146 info.GetReturnValue().Set(v8::True(isolate));
13147
13148 auto context = isolate->GetCurrentContext();
13149 Local<Boolean> should_throw_on_error_value =
13150 Boolean::New(isolate, info.ShouldThrowOnError());
13151 CHECK(context->Global()
13152 ->Set(isolate->GetCurrentContext(), v8_str("should_throw_deleter"),
13153 should_throw_on_error_value)
13154 .FromJust());
13155}
13156
13157
13158static void ShouldThrowOnErrorPropertyEnumerator(
13159 const v8::PropertyCallbackInfo<v8::Array>& info) {
13160 ApiTestFuzzer::Fuzz();
13161 v8::Isolate* isolate = info.GetIsolate();
13162 Local<v8::Array> names = v8::Array::New(isolate, 1);
13163 CHECK(names->Set(isolate->GetCurrentContext(), names, v8_num(1)).FromJust());
13164 info.GetReturnValue().Set(names);
13165
13166 auto context = isolate->GetCurrentContext();
13167 Local<Boolean> should_throw_on_error_value =
13168 Boolean::New(isolate, info.ShouldThrowOnError());
13169 CHECK(context->Global()
13170 ->Set(isolate->GetCurrentContext(),
13171 v8_str("should_throw_enumerator"),
13172 should_throw_on_error_value)
13173 .FromJust());
13174}
13175
13176
13177THREADED_TEST(InterceptorShouldThrowOnError) {
Ben Murdoch097c5b22016-05-18 11:27:45 +010013178 LocalContext context;
13179 v8::Isolate* isolate = context->GetIsolate();
13180 v8::HandleScope scope(isolate);
13181 Local<Object> global = context->Global();
13182
13183 auto interceptor_templ = v8::ObjectTemplate::New(isolate);
13184 v8::NamedPropertyHandlerConfiguration handler(
13185 ShouldThrowOnErrorGetter, ShouldThrowOnErrorSetter<Value>,
13186 ShouldThrowOnErrorQuery, ShouldThrowOnErrorDeleter,
13187 ShouldThrowOnErrorPropertyEnumerator);
13188 interceptor_templ->SetHandler(handler);
13189
13190 Local<v8::Object> instance =
13191 interceptor_templ->NewInstance(context.local()).ToLocalChecked();
13192
13193 CHECK(global->Set(context.local(), v8_str("o"), instance).FromJust());
13194
13195 // SLOPPY mode
13196 Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
13197 CHECK(value->IsFalse());
13198 v8_compile("o.f = 153")->Run(context.local()).ToLocalChecked();
13199 value = global->Get(context.local(), v8_str("should_throw_setter"))
13200 .ToLocalChecked();
13201 CHECK(value->IsFalse());
13202
13203 v8_compile("delete o.f")->Run(context.local()).ToLocalChecked();
13204 value = global->Get(context.local(), v8_str("should_throw_deleter"))
13205 .ToLocalChecked();
13206 CHECK(value->IsFalse());
13207
13208 v8_compile("Object.getOwnPropertyNames(o)")
13209 ->Run(context.local())
13210 .ToLocalChecked();
13211 value = global->Get(context.local(), v8_str("should_throw_enumerator"))
13212 .ToLocalChecked();
13213 CHECK(value->IsFalse());
13214
13215 // STRICT mode
13216 value = v8_compile("'use strict';o.f")->Run(context.local()).ToLocalChecked();
13217 CHECK(value->IsFalse());
13218 v8_compile("'use strict'; o.f = 153")->Run(context.local()).ToLocalChecked();
13219 value = global->Get(context.local(), v8_str("should_throw_setter"))
13220 .ToLocalChecked();
13221 CHECK(value->IsTrue());
13222
13223 v8_compile("'use strict'; delete o.f")->Run(context.local()).ToLocalChecked();
13224 value = global->Get(context.local(), v8_str("should_throw_deleter"))
13225 .ToLocalChecked();
13226 CHECK(value->IsTrue());
13227
13228 v8_compile("'use strict'; Object.getOwnPropertyNames(o)")
13229 ->Run(context.local())
13230 .ToLocalChecked();
13231 value = global->Get(context.local(), v8_str("should_throw_enumerator"))
13232 .ToLocalChecked();
13233 CHECK(value->IsFalse());
Ben Murdoch097c5b22016-05-18 11:27:45 +010013234}
13235
13236
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013237static void IsConstructHandler(
13238 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +000013239 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013240 args.GetReturnValue().Set(args.IsConstructCall());
Steve Blocka7e24c12009-10-30 11:49:00 +000013241}
13242
13243
13244THREADED_TEST(IsConstructCall) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013245 v8::Isolate* isolate = CcTest::isolate();
13246 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000013247
13248 // Function template with call handler.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013249 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000013250 templ->SetCallHandler(IsConstructHandler);
13251
13252 LocalContext context;
13253
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013254 CHECK(context->Global()
13255 ->Set(context.local(), v8_str("f"),
13256 templ->GetFunction(context.local()).ToLocalChecked())
13257 .FromJust());
13258 Local<Value> value = v8_compile("f()")->Run(context.local()).ToLocalChecked();
13259 CHECK(!value->BooleanValue(context.local()).FromJust());
13260 value = v8_compile("new f()")->Run(context.local()).ToLocalChecked();
13261 CHECK(value->BooleanValue(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013262}
13263
13264
13265THREADED_TEST(ObjectProtoToString) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013266 v8::Isolate* isolate = CcTest::isolate();
13267 v8::HandleScope scope(isolate);
13268 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000013269 templ->SetClassName(v8_str("MyClass"));
13270
13271 LocalContext context;
13272
13273 Local<String> customized_tostring = v8_str("customized toString");
13274
13275 // Replace Object.prototype.toString
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013276 v8_compile(
13277 "Object.prototype.toString = function() {"
13278 " return 'customized toString';"
13279 "}")
13280 ->Run(context.local())
13281 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000013282
13283 // Normal ToString call should call replaced Object.prototype.toString
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013284 Local<v8::Object> instance = templ->GetFunction(context.local())
13285 .ToLocalChecked()
13286 ->NewInstance(context.local())
13287 .ToLocalChecked();
13288 Local<String> value = instance->ToString(context.local()).ToLocalChecked();
13289 CHECK(value->IsString() &&
13290 value->Equals(context.local(), customized_tostring).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013291
13292 // ObjectProtoToString should not call replace toString function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013293 value = instance->ObjectProtoToString(context.local()).ToLocalChecked();
13294 CHECK(value->IsString() &&
13295 value->Equals(context.local(), v8_str("[object MyClass]")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013296
13297 // Check global
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013298 value =
13299 context->Global()->ObjectProtoToString(context.local()).ToLocalChecked();
13300 CHECK(value->IsString() &&
13301 value->Equals(context.local(), v8_str("[object global]")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013302
13303 // Check ordinary object
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013304 Local<Value> object =
13305 v8_compile("new Object()")->Run(context.local()).ToLocalChecked();
13306 value = object.As<v8::Object>()
13307 ->ObjectProtoToString(context.local())
13308 .ToLocalChecked();
13309 CHECK(value->IsString() &&
13310 value->Equals(context.local(), v8_str("[object Object]")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013311}
13312
13313
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013314TEST(ObjectProtoToStringES6) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080013315 LocalContext context;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013316 v8::Isolate* isolate = CcTest::isolate();
13317 v8::HandleScope scope(isolate);
13318 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
13319 templ->SetClassName(v8_str("MyClass"));
13320
13321 Local<String> customized_tostring = v8_str("customized toString");
13322
13323 // Replace Object.prototype.toString
13324 CompileRun(
13325 "Object.prototype.toString = function() {"
13326 " return 'customized toString';"
13327 "}");
13328
13329 // Normal ToString call should call replaced Object.prototype.toString
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013330 Local<v8::Object> instance = templ->GetFunction(context.local())
13331 .ToLocalChecked()
13332 ->NewInstance(context.local())
13333 .ToLocalChecked();
13334 Local<String> value = instance->ToString(context.local()).ToLocalChecked();
13335 CHECK(value->IsString() &&
13336 value->Equals(context.local(), customized_tostring).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013337
13338 // ObjectProtoToString should not call replace toString function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013339 value = instance->ObjectProtoToString(context.local()).ToLocalChecked();
13340 CHECK(value->IsString() &&
13341 value->Equals(context.local(), v8_str("[object MyClass]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013342
13343 // Check global
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013344 value =
13345 context->Global()->ObjectProtoToString(context.local()).ToLocalChecked();
13346 CHECK(value->IsString() &&
13347 value->Equals(context.local(), v8_str("[object global]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013348
13349 // Check ordinary object
13350 Local<Value> object = CompileRun("new Object()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013351 value = object.As<v8::Object>()
13352 ->ObjectProtoToString(context.local())
13353 .ToLocalChecked();
13354 CHECK(value->IsString() &&
13355 value->Equals(context.local(), v8_str("[object Object]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013356
13357 // Check that ES6 semantics using @@toStringTag work
13358 Local<v8::Symbol> toStringTag = v8::Symbol::GetToStringTag(isolate);
13359
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013360#define TEST_TOSTRINGTAG(type, tag, expected) \
13361 do { \
13362 object = CompileRun("new " #type "()"); \
13363 CHECK(object.As<v8::Object>() \
13364 ->Set(context.local(), toStringTag, v8_str(#tag)) \
13365 .FromJust()); \
13366 value = object.As<v8::Object>() \
13367 ->ObjectProtoToString(context.local()) \
13368 .ToLocalChecked(); \
13369 CHECK(value->IsString() && \
13370 value->Equals(context.local(), v8_str("[object " #expected "]")) \
13371 .FromJust()); \
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013372 } while (0)
13373
13374 TEST_TOSTRINGTAG(Array, Object, Object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013375 TEST_TOSTRINGTAG(Object, Arguments, Arguments);
13376 TEST_TOSTRINGTAG(Object, Array, Array);
13377 TEST_TOSTRINGTAG(Object, Boolean, Boolean);
13378 TEST_TOSTRINGTAG(Object, Date, Date);
13379 TEST_TOSTRINGTAG(Object, Error, Error);
13380 TEST_TOSTRINGTAG(Object, Function, Function);
13381 TEST_TOSTRINGTAG(Object, Number, Number);
13382 TEST_TOSTRINGTAG(Object, RegExp, RegExp);
13383 TEST_TOSTRINGTAG(Object, String, String);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013384 TEST_TOSTRINGTAG(Object, Foo, Foo);
13385
13386#undef TEST_TOSTRINGTAG
13387
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013388 Local<v8::RegExp> valueRegExp =
13389 v8::RegExp::New(context.local(), v8_str("^$"), v8::RegExp::kNone)
13390 .ToLocalChecked();
13391 Local<Value> valueNumber = v8_num(123);
13392 Local<v8::Symbol> valueSymbol = v8_symbol("TestSymbol");
13393 Local<v8::Function> valueFunction =
13394 CompileRun("(function fn() {})").As<v8::Function>();
13395 Local<v8::Object> valueObject = v8::Object::New(v8::Isolate::GetCurrent());
13396 Local<v8::Primitive> valueNull = v8::Null(v8::Isolate::GetCurrent());
13397 Local<v8::Primitive> valueUndef = v8::Undefined(v8::Isolate::GetCurrent());
13398
13399#define TEST_TOSTRINGTAG(type, tagValue, expected) \
13400 do { \
13401 object = CompileRun("new " #type "()"); \
13402 CHECK(object.As<v8::Object>() \
13403 ->Set(context.local(), toStringTag, tagValue) \
13404 .FromJust()); \
13405 value = object.As<v8::Object>() \
13406 ->ObjectProtoToString(context.local()) \
13407 .ToLocalChecked(); \
13408 CHECK(value->IsString() && \
13409 value->Equals(context.local(), v8_str("[object " #expected "]")) \
13410 .FromJust()); \
13411 } while (0)
13412
13413#define TEST_TOSTRINGTAG_TYPES(tagValue) \
13414 TEST_TOSTRINGTAG(Array, tagValue, Array); \
13415 TEST_TOSTRINGTAG(Object, tagValue, Object); \
13416 TEST_TOSTRINGTAG(Function, tagValue, Function); \
13417 TEST_TOSTRINGTAG(Date, tagValue, Date); \
13418 TEST_TOSTRINGTAG(RegExp, tagValue, RegExp); \
13419 TEST_TOSTRINGTAG(Error, tagValue, Error); \
13420
13421 // Test non-String-valued @@toStringTag
13422 TEST_TOSTRINGTAG_TYPES(valueRegExp);
13423 TEST_TOSTRINGTAG_TYPES(valueNumber);
13424 TEST_TOSTRINGTAG_TYPES(valueSymbol);
13425 TEST_TOSTRINGTAG_TYPES(valueFunction);
13426 TEST_TOSTRINGTAG_TYPES(valueObject);
13427 TEST_TOSTRINGTAG_TYPES(valueNull);
13428 TEST_TOSTRINGTAG_TYPES(valueUndef);
13429
13430#undef TEST_TOSTRINGTAG
13431#undef TEST_TOSTRINGTAG_TYPES
13432
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013433 // @@toStringTag getter throws
13434 Local<Value> obj = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013435 obj.As<v8::Object>()
13436 ->SetAccessor(context.local(), toStringTag, ThrowingSymbolAccessorGetter)
13437 .FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013438 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013439 TryCatch try_catch(isolate);
13440 CHECK(obj.As<v8::Object>()->ObjectProtoToString(context.local()).IsEmpty());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013441 CHECK(try_catch.HasCaught());
13442 }
13443
13444 // @@toStringTag getter does not throw
13445 obj = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013446 obj.As<v8::Object>()
13447 ->SetAccessor(context.local(), toStringTag,
13448 SymbolAccessorGetterReturnsDefault, 0, v8_str("Test"))
13449 .FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013450 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013451 TryCatch try_catch(isolate);
13452 value = obj.As<v8::Object>()
13453 ->ObjectProtoToString(context.local())
13454 .ToLocalChecked();
13455 CHECK(value->IsString() &&
13456 value->Equals(context.local(), v8_str("[object Test]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013457 CHECK(!try_catch.HasCaught());
13458 }
13459
13460 // JS @@toStringTag value
13461 obj = CompileRun("obj = {}; obj[Symbol.toStringTag] = 'Test'; obj");
13462 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013463 TryCatch try_catch(isolate);
13464 value = obj.As<v8::Object>()
13465 ->ObjectProtoToString(context.local())
13466 .ToLocalChecked();
13467 CHECK(value->IsString() &&
13468 value->Equals(context.local(), v8_str("[object Test]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013469 CHECK(!try_catch.HasCaught());
13470 }
13471
13472 // JS @@toStringTag getter throws
13473 obj = CompileRun(
13474 "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
13475 " get: function() { throw 'Test'; }"
13476 "}); obj");
13477 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013478 TryCatch try_catch(isolate);
13479 CHECK(obj.As<v8::Object>()->ObjectProtoToString(context.local()).IsEmpty());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013480 CHECK(try_catch.HasCaught());
13481 }
13482
13483 // JS @@toStringTag getter does not throw
13484 obj = CompileRun(
13485 "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
13486 " get: function() { return 'Test'; }"
13487 "}); obj");
13488 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013489 TryCatch try_catch(isolate);
13490 value = obj.As<v8::Object>()
13491 ->ObjectProtoToString(context.local())
13492 .ToLocalChecked();
13493 CHECK(value->IsString() &&
13494 value->Equals(context.local(), v8_str("[object Test]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013495 CHECK(!try_catch.HasCaught());
13496 }
13497}
13498
13499
13500THREADED_TEST(ObjectGetConstructorName) {
13501 v8::Isolate* isolate = CcTest::isolate();
13502 LocalContext context;
13503 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013504 v8_compile(
13505 "function Parent() {};"
13506 "function Child() {};"
13507 "Child.prototype = new Parent();"
13508 "Child.prototype.constructor = Child;"
Ben Murdochda12d292016-06-02 14:46:10 +010013509 "var outer = { inner: (0, function() { }) };"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013510 "var p = new Parent();"
13511 "var c = new Child();"
13512 "var x = new outer.inner();"
13513 "var proto = Child.prototype;")
13514 ->Run(context.local())
13515 .ToLocalChecked();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080013516
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013517 Local<v8::Value> p =
13518 context->Global()->Get(context.local(), v8_str("p")).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013519 CHECK(p->IsObject() &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013520 p->ToObject(context.local())
13521 .ToLocalChecked()
13522 ->GetConstructorName()
13523 ->Equals(context.local(), v8_str("Parent"))
13524 .FromJust());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080013525
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013526 Local<v8::Value> c =
13527 context->Global()->Get(context.local(), v8_str("c")).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013528 CHECK(c->IsObject() &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013529 c->ToObject(context.local())
13530 .ToLocalChecked()
13531 ->GetConstructorName()
13532 ->Equals(context.local(), v8_str("Child"))
13533 .FromJust());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080013534
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013535 Local<v8::Value> x =
13536 context->Global()->Get(context.local(), v8_str("x")).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013537 CHECK(x->IsObject() &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013538 x->ToObject(context.local())
13539 .ToLocalChecked()
13540 ->GetConstructorName()
13541 ->Equals(context.local(), v8_str("outer.inner"))
13542 .FromJust());
13543
13544 Local<v8::Value> child_prototype =
13545 context->Global()->Get(context.local(), v8_str("proto")).ToLocalChecked();
13546 CHECK(child_prototype->IsObject() &&
13547 child_prototype->ToObject(context.local())
13548 .ToLocalChecked()
13549 ->GetConstructorName()
13550 ->Equals(context.local(), v8_str("Parent"))
13551 .FromJust());
13552}
13553
13554
13555THREADED_TEST(SubclassGetConstructorName) {
13556 v8::Isolate* isolate = CcTest::isolate();
13557 LocalContext context;
13558 v8::HandleScope scope(isolate);
13559 v8_compile(
13560 "\"use strict\";"
13561 "class Parent {}"
13562 "class Child extends Parent {}"
13563 "var p = new Parent();"
13564 "var c = new Child();")
13565 ->Run(context.local())
13566 .ToLocalChecked();
13567
13568 Local<v8::Value> p =
13569 context->Global()->Get(context.local(), v8_str("p")).ToLocalChecked();
13570 CHECK(p->IsObject() &&
13571 p->ToObject(context.local())
13572 .ToLocalChecked()
13573 ->GetConstructorName()
13574 ->Equals(context.local(), v8_str("Parent"))
13575 .FromJust());
13576
13577 Local<v8::Value> c =
13578 context->Global()->Get(context.local(), v8_str("c")).ToLocalChecked();
13579 CHECK(c->IsObject() &&
13580 c->ToObject(context.local())
13581 .ToLocalChecked()
13582 ->GetConstructorName()
13583 ->Equals(context.local(), v8_str("Child"))
13584 .FromJust());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080013585}
13586
13587
Steve Blocka7e24c12009-10-30 11:49:00 +000013588bool ApiTestFuzzer::fuzzing_ = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013589v8::base::Semaphore ApiTestFuzzer::all_tests_done_(0);
Steve Blocka7e24c12009-10-30 11:49:00 +000013590int ApiTestFuzzer::active_tests_;
13591int ApiTestFuzzer::tests_being_run_;
13592int ApiTestFuzzer::current_;
13593
13594
13595// We are in a callback and want to switch to another thread (if we
13596// are currently running the thread fuzzing test).
13597void ApiTestFuzzer::Fuzz() {
13598 if (!fuzzing_) return;
13599 ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
13600 test->ContextSwitch();
13601}
13602
13603
13604// Let the next thread go. Since it is also waiting on the V8 lock it may
13605// not start immediately.
13606bool ApiTestFuzzer::NextThread() {
13607 int test_position = GetNextTestNumber();
Steve Blockd0582a62009-12-15 09:54:21 +000013608 const char* test_name = RegisterThreadedTest::nth(current_)->name();
Steve Blocka7e24c12009-10-30 11:49:00 +000013609 if (test_position == current_) {
Steve Blockd0582a62009-12-15 09:54:21 +000013610 if (kLogThreading)
13611 printf("Stay with %s\n", test_name);
Steve Blocka7e24c12009-10-30 11:49:00 +000013612 return false;
13613 }
Steve Blockd0582a62009-12-15 09:54:21 +000013614 if (kLogThreading) {
13615 printf("Switch from %s to %s\n",
13616 test_name,
13617 RegisterThreadedTest::nth(test_position)->name());
13618 }
Steve Blocka7e24c12009-10-30 11:49:00 +000013619 current_ = test_position;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013620 RegisterThreadedTest::nth(current_)->fuzzer_->gate_.Signal();
Steve Blocka7e24c12009-10-30 11:49:00 +000013621 return true;
13622}
13623
13624
13625void ApiTestFuzzer::Run() {
13626 // When it is our turn...
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013627 gate_.Wait();
Steve Blocka7e24c12009-10-30 11:49:00 +000013628 {
13629 // ... get the V8 lock and start running the test.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013630 v8::Locker locker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013631 CallTest();
13632 }
13633 // This test finished.
13634 active_ = false;
13635 active_tests_--;
13636 // If it was the last then signal that fact.
13637 if (active_tests_ == 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013638 all_tests_done_.Signal();
Steve Blocka7e24c12009-10-30 11:49:00 +000013639 } else {
13640 // Otherwise select a new test and start that.
13641 NextThread();
13642 }
13643}
13644
13645
13646static unsigned linear_congruential_generator;
13647
13648
Ben Murdoch3ef787d2012-04-12 10:51:47 +010013649void ApiTestFuzzer::SetUp(PartOfTest part) {
Steve Blocka7e24c12009-10-30 11:49:00 +000013650 linear_congruential_generator = i::FLAG_testing_prng_seed;
13651 fuzzing_ = true;
Ben Murdoch257744e2011-11-30 15:57:28 +000013652 int count = RegisterThreadedTest::count();
13653 int start = count * part / (LAST_PART + 1);
13654 int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
13655 active_tests_ = tests_being_run_ = end - start + 1;
Steve Blocka7e24c12009-10-30 11:49:00 +000013656 for (int i = 0; i < tests_being_run_; i++) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000013657 RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
Steve Blocka7e24c12009-10-30 11:49:00 +000013658 }
13659 for (int i = 0; i < active_tests_; i++) {
13660 RegisterThreadedTest::nth(i)->fuzzer_->Start();
13661 }
13662}
13663
13664
13665static void CallTestNumber(int test_number) {
13666 (RegisterThreadedTest::nth(test_number)->callback())();
13667}
13668
13669
13670void ApiTestFuzzer::RunAllTests() {
13671 // Set off the first test.
13672 current_ = -1;
13673 NextThread();
13674 // Wait till they are all done.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013675 all_tests_done_.Wait();
Steve Blocka7e24c12009-10-30 11:49:00 +000013676}
13677
13678
13679int ApiTestFuzzer::GetNextTestNumber() {
13680 int next_test;
13681 do {
13682 next_test = (linear_congruential_generator >> 16) % tests_being_run_;
13683 linear_congruential_generator *= 1664525u;
13684 linear_congruential_generator += 1013904223u;
13685 } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
13686 return next_test;
13687}
13688
13689
13690void ApiTestFuzzer::ContextSwitch() {
13691 // If the new thread is the same as the current thread there is nothing to do.
13692 if (NextThread()) {
13693 // Now it can start.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013694 v8::Unlocker unlocker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013695 // Wait till someone starts us again.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013696 gate_.Wait();
Steve Blocka7e24c12009-10-30 11:49:00 +000013697 // And we're off.
13698 }
13699}
13700
13701
13702void ApiTestFuzzer::TearDown() {
13703 fuzzing_ = false;
13704 for (int i = 0; i < RegisterThreadedTest::count(); i++) {
13705 ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
13706 if (fuzzer != NULL) fuzzer->Join();
13707 }
13708}
13709
13710
13711// Lets not be needlessly self-referential.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013712TEST(Threading1) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010013713 ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART);
Steve Blocka7e24c12009-10-30 11:49:00 +000013714 ApiTestFuzzer::RunAllTests();
13715 ApiTestFuzzer::TearDown();
13716}
13717
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013718
Steve Blocka7e24c12009-10-30 11:49:00 +000013719TEST(Threading2) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010013720 ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
Steve Blocka7e24c12009-10-30 11:49:00 +000013721 ApiTestFuzzer::RunAllTests();
13722 ApiTestFuzzer::TearDown();
13723}
13724
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013725
Ben Murdoch257744e2011-11-30 15:57:28 +000013726TEST(Threading3) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010013727 ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
Ben Murdoch257744e2011-11-30 15:57:28 +000013728 ApiTestFuzzer::RunAllTests();
13729 ApiTestFuzzer::TearDown();
13730}
13731
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013732
Ben Murdoch257744e2011-11-30 15:57:28 +000013733TEST(Threading4) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010013734 ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
Ben Murdoch257744e2011-11-30 15:57:28 +000013735 ApiTestFuzzer::RunAllTests();
13736 ApiTestFuzzer::TearDown();
13737}
Steve Blocka7e24c12009-10-30 11:49:00 +000013738
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013739
Steve Blocka7e24c12009-10-30 11:49:00 +000013740void ApiTestFuzzer::CallTest() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013741 v8::Isolate::Scope scope(CcTest::isolate());
Steve Blockd0582a62009-12-15 09:54:21 +000013742 if (kLogThreading)
13743 printf("Start test %d\n", test_number_);
Steve Blocka7e24c12009-10-30 11:49:00 +000013744 CallTestNumber(test_number_);
Steve Blockd0582a62009-12-15 09:54:21 +000013745 if (kLogThreading)
13746 printf("End test %d\n", test_number_);
Steve Blocka7e24c12009-10-30 11:49:00 +000013747}
13748
13749
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013750static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
13751 v8::Isolate* isolate = args.GetIsolate();
13752 CHECK(v8::Locker::IsLocked(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000013753 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013754 v8::Unlocker unlocker(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000013755 const char* code = "throw 7;";
13756 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013757 v8::Locker nested_locker(isolate);
13758 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013759 v8::Local<Value> exception;
13760 {
13761 v8::TryCatch try_catch(isolate);
13762 v8::Local<Value> value = CompileRun(code);
Steve Blocka7e24c12009-10-30 11:49:00 +000013763 CHECK(value.IsEmpty());
13764 CHECK(try_catch.HasCaught());
13765 // Make sure to wrap the exception in a new handle because
13766 // the handle returned from the TryCatch is destroyed
13767 // when the TryCatch is destroyed.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013768 exception = Local<Value>::New(isolate, try_catch.Exception());
Steve Blocka7e24c12009-10-30 11:49:00 +000013769 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013770 args.GetIsolate()->ThrowException(exception);
Steve Blocka7e24c12009-10-30 11:49:00 +000013771 }
13772}
13773
13774
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013775static void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
13776 CHECK(v8::Locker::IsLocked(CcTest::isolate()));
Steve Blocka7e24c12009-10-30 11:49:00 +000013777 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013778 v8::Unlocker unlocker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013779 const char* code = "throw 7;";
13780 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013781 v8::Locker nested_locker(CcTest::isolate());
13782 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013783 v8::Local<Value> value = CompileRun(code);
Steve Blocka7e24c12009-10-30 11:49:00 +000013784 CHECK(value.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013785 args.GetReturnValue().Set(v8_str("foo"));
Steve Blocka7e24c12009-10-30 11:49:00 +000013786 }
13787}
13788
13789
13790// These are locking tests that don't need to be run again
13791// as part of the locking aggregation tests.
13792TEST(NestedLockers) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013793 v8::Isolate* isolate = CcTest::isolate();
13794 v8::Locker locker(isolate);
13795 CHECK(v8::Locker::IsLocked(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000013796 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013797 v8::HandleScope scope(env->GetIsolate());
13798 Local<v8::FunctionTemplate> fun_templ =
13799 v8::FunctionTemplate::New(isolate, ThrowInJS);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013800 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
13801 CHECK(env->Global()->Set(env.local(), v8_str("throw_in_js"), fun).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013802 Local<Script> script = v8_compile("(function () {"
13803 " try {"
13804 " throw_in_js();"
13805 " return 42;"
13806 " } catch (e) {"
13807 " return e * 13;"
13808 " }"
13809 "})();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013810 CHECK_EQ(91, script->Run(env.local())
13811 .ToLocalChecked()
13812 ->Int32Value(env.local())
13813 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013814}
13815
13816
13817// These are locking tests that don't need to be run again
13818// as part of the locking aggregation tests.
13819TEST(NestedLockersNoTryCatch) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013820 v8::Locker locker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013821 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013822 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013823 Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013824 v8::FunctionTemplate::New(env->GetIsolate(), ThrowInJSNoCatch);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013825 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
13826 CHECK(env->Global()->Set(env.local(), v8_str("throw_in_js"), fun).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013827 Local<Script> script = v8_compile("(function () {"
13828 " try {"
13829 " throw_in_js();"
13830 " return 42;"
13831 " } catch (e) {"
13832 " return e * 13;"
13833 " }"
13834 "})();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013835 CHECK_EQ(91, script->Run(env.local())
13836 .ToLocalChecked()
13837 ->Int32Value(env.local())
13838 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013839}
13840
13841
13842THREADED_TEST(RecursiveLocking) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013843 v8::Locker locker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013844 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013845 v8::Locker locker2(CcTest::isolate());
13846 CHECK(v8::Locker::IsLocked(CcTest::isolate()));
Steve Blocka7e24c12009-10-30 11:49:00 +000013847 }
13848}
13849
13850
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013851static void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +000013852 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013853 v8::Unlocker unlocker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013854}
13855
13856
13857THREADED_TEST(LockUnlockLock) {
13858 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013859 v8::Locker locker(CcTest::isolate());
13860 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013861 LocalContext env;
13862 Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013863 v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013864 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
13865 CHECK(env->Global()
13866 ->Set(env.local(), v8_str("unlock_for_a_moment"), fun)
13867 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013868 Local<Script> script = v8_compile("(function () {"
13869 " unlock_for_a_moment();"
13870 " return 42;"
13871 "})();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013872 CHECK_EQ(42, script->Run(env.local())
13873 .ToLocalChecked()
13874 ->Int32Value(env.local())
13875 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013876 }
13877 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013878 v8::Locker locker(CcTest::isolate());
13879 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013880 LocalContext env;
13881 Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013882 v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013883 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
13884 CHECK(env->Global()
13885 ->Set(env.local(), v8_str("unlock_for_a_moment"), fun)
13886 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013887 Local<Script> script = v8_compile("(function () {"
13888 " unlock_for_a_moment();"
13889 " return 42;"
13890 "})();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013891 CHECK_EQ(42, script->Run(env.local())
13892 .ToLocalChecked()
13893 ->Int32Value(env.local())
13894 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013895 }
13896}
13897
13898
Leon Clarked91b9f72010-01-27 17:25:45 +000013899static int GetGlobalObjectsCount() {
Leon Clarkeeab96aa2010-01-27 16:31:12 +000013900 int count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013901 i::HeapIterator it(CcTest::heap());
Leon Clarked91b9f72010-01-27 17:25:45 +000013902 for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013903 if (object->IsJSGlobalObject()) {
13904 i::JSGlobalObject* g = i::JSGlobalObject::cast(object);
13905 // Skip dummy global object.
13906 if (i::GlobalDictionary::cast(g->properties())->NumberOfElements() != 0) {
13907 count++;
13908 }
13909 }
Leon Clarked91b9f72010-01-27 17:25:45 +000013910 return count;
13911}
13912
13913
Ben Murdochf87a2032010-10-22 12:50:53 +010013914static void CheckSurvivingGlobalObjectsCount(int expected) {
Steve Blocka7e24c12009-10-30 11:49:00 +000013915 // We need to collect all garbage twice to be sure that everything
13916 // has been collected. This is because inline caches are cleared in
13917 // the first garbage collection but some of the maps have already
13918 // been marked at that point. Therefore some of the maps are not
13919 // collected until the second garbage collection.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013920 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013921 CcTest::heap()->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
Leon Clarked91b9f72010-01-27 17:25:45 +000013922 int count = GetGlobalObjectsCount();
Steve Blocka7e24c12009-10-30 11:49:00 +000013923#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013924 if (count != expected) CcTest::heap()->TracePathToGlobal();
Steve Blocka7e24c12009-10-30 11:49:00 +000013925#endif
Ben Murdochf87a2032010-10-22 12:50:53 +010013926 CHECK_EQ(expected, count);
Steve Blocka7e24c12009-10-30 11:49:00 +000013927}
13928
13929
13930TEST(DontLeakGlobalObjects) {
13931 // Regression test for issues 1139850 and 1174891.
13932
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013933 i::FLAG_expose_gc = true;
Steve Blocka7e24c12009-10-30 11:49:00 +000013934 v8::V8::Initialize();
13935
Steve Blocka7e24c12009-10-30 11:49:00 +000013936 for (int i = 0; i < 5; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013937 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013938 LocalContext context;
13939 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013940 CcTest::isolate()->ContextDisposedNotification();
Ben Murdochf87a2032010-10-22 12:50:53 +010013941 CheckSurvivingGlobalObjectsCount(0);
Steve Blocka7e24c12009-10-30 11:49:00 +000013942
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013943 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013944 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013945 v8_compile("Date")->Run(context.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000013946 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013947 CcTest::isolate()->ContextDisposedNotification();
Ben Murdochf87a2032010-10-22 12:50:53 +010013948 CheckSurvivingGlobalObjectsCount(0);
Steve Blocka7e24c12009-10-30 11:49:00 +000013949
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013950 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013951 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013952 v8_compile("/aaa/")->Run(context.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000013953 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013954 CcTest::isolate()->ContextDisposedNotification();
Ben Murdochf87a2032010-10-22 12:50:53 +010013955 CheckSurvivingGlobalObjectsCount(0);
Steve Blocka7e24c12009-10-30 11:49:00 +000013956
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013957 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013958 const char* extension_list[] = { "v8/gc" };
13959 v8::ExtensionConfiguration extensions(1, extension_list);
13960 LocalContext context(&extensions);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013961 v8_compile("gc();")->Run(context.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000013962 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013963 CcTest::isolate()->ContextDisposedNotification();
Ben Murdochf87a2032010-10-22 12:50:53 +010013964 CheckSurvivingGlobalObjectsCount(0);
Steve Blocka7e24c12009-10-30 11:49:00 +000013965 }
13966}
13967
13968
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013969TEST(CopyablePersistent) {
13970 LocalContext context;
13971 v8::Isolate* isolate = context->GetIsolate();
13972 i::GlobalHandles* globals =
13973 reinterpret_cast<i::Isolate*>(isolate)->global_handles();
13974 int initial_handles = globals->global_handles_count();
13975 typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> >
13976 CopyableObject;
13977 {
13978 CopyableObject handle1;
13979 {
13980 v8::HandleScope scope(isolate);
13981 handle1.Reset(isolate, v8::Object::New(isolate));
13982 }
13983 CHECK_EQ(initial_handles + 1, globals->global_handles_count());
13984 CopyableObject handle2;
13985 handle2 = handle1;
13986 CHECK(handle1 == handle2);
13987 CHECK_EQ(initial_handles + 2, globals->global_handles_count());
13988 CopyableObject handle3(handle2);
13989 CHECK(handle1 == handle3);
13990 CHECK_EQ(initial_handles + 3, globals->global_handles_count());
13991 }
13992 // Verify autodispose
13993 CHECK_EQ(initial_handles, globals->global_handles_count());
13994}
13995
13996
13997static void WeakApiCallback(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013998 const v8::WeakCallbackInfo<Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013999 data.GetParameter()->Reset();
14000 delete data.GetParameter();
14001}
14002
14003
14004TEST(WeakCallbackApi) {
14005 LocalContext context;
14006 v8::Isolate* isolate = context->GetIsolate();
14007 i::GlobalHandles* globals =
14008 reinterpret_cast<i::Isolate*>(isolate)->global_handles();
14009 int initial_handles = globals->global_handles_count();
14010 {
14011 v8::HandleScope scope(isolate);
14012 v8::Local<v8::Object> obj = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014013 CHECK(
14014 obj->Set(context.local(), v8_str("key"), v8::Integer::New(isolate, 231))
14015 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014016 v8::Persistent<v8::Object>* handle =
14017 new v8::Persistent<v8::Object>(isolate, obj);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014018 handle->SetWeak<v8::Persistent<v8::Object>>(
14019 handle, WeakApiCallback, v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014020 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014021 reinterpret_cast<i::Isolate*>(isolate)->heap()->CollectAllGarbage(
14022 i::Heap::kAbortIncrementalMarkingMask);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014023 // Verify disposed.
14024 CHECK_EQ(initial_handles, globals->global_handles_count());
14025}
14026
14027
Steve Blocka7e24c12009-10-30 11:49:00 +000014028v8::Persistent<v8::Object> some_object;
14029v8::Persistent<v8::Object> bad_handle;
14030
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014031
14032void NewPersistentHandleCallback2(
14033 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014034 v8::HandleScope scope(data.GetIsolate());
14035 bad_handle.Reset(data.GetIsolate(), some_object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014036}
14037
14038
14039void NewPersistentHandleCallback1(
14040 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014041 data.GetParameter()->Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014042 data.SetSecondPassCallback(NewPersistentHandleCallback2);
Steve Blocka7e24c12009-10-30 11:49:00 +000014043}
14044
14045
14046THREADED_TEST(NewPersistentHandleFromWeakCallback) {
14047 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014048 v8::Isolate* isolate = context->GetIsolate();
Steve Blocka7e24c12009-10-30 11:49:00 +000014049
14050 v8::Persistent<v8::Object> handle1, handle2;
14051 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014052 v8::HandleScope scope(isolate);
14053 some_object.Reset(isolate, v8::Object::New(isolate));
14054 handle1.Reset(isolate, v8::Object::New(isolate));
14055 handle2.Reset(isolate, v8::Object::New(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000014056 }
14057 // Note: order is implementation dependent alas: currently
14058 // global handle nodes are processed by PostGarbageCollectionProcessing
14059 // in reverse allocation order, so if second allocated handle is deleted,
14060 // weak callback of the first handle would be able to 'reallocate' it.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014061 handle1.SetWeak(&handle1, NewPersistentHandleCallback1,
14062 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014063 handle2.Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014064 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +000014065}
14066
14067
14068v8::Persistent<v8::Object> to_be_disposed;
14069
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014070
14071void DisposeAndForceGcCallback2(
14072 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014073 to_be_disposed.Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014074 CcTest::heap()->CollectAllGarbage();
14075}
14076
14077
14078void DisposeAndForceGcCallback1(
14079 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014080 data.GetParameter()->Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014081 data.SetSecondPassCallback(DisposeAndForceGcCallback2);
Steve Blocka7e24c12009-10-30 11:49:00 +000014082}
14083
14084
14085THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
14086 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014087 v8::Isolate* isolate = context->GetIsolate();
Steve Blocka7e24c12009-10-30 11:49:00 +000014088
14089 v8::Persistent<v8::Object> handle1, handle2;
14090 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014091 v8::HandleScope scope(isolate);
14092 handle1.Reset(isolate, v8::Object::New(isolate));
14093 handle2.Reset(isolate, v8::Object::New(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000014094 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014095 handle1.SetWeak(&handle1, DisposeAndForceGcCallback1,
14096 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014097 to_be_disposed.Reset(isolate, handle2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014098 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +000014099}
14100
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014101void DisposingCallback(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014102 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014103 data.GetParameter()->Reset();
Steve Blockd0582a62009-12-15 09:54:21 +000014104}
14105
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014106void HandleCreatingCallback2(
14107 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014108 v8::HandleScope scope(data.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014109 v8::Global<v8::Object>(data.GetIsolate(), v8::Object::New(data.GetIsolate()));
14110}
14111
14112
14113void HandleCreatingCallback1(
14114 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014115 data.GetParameter()->Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014116 data.SetSecondPassCallback(HandleCreatingCallback2);
Steve Blockd0582a62009-12-15 09:54:21 +000014117}
14118
14119
14120THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014121 v8::Locker locker(CcTest::isolate());
Steve Blockd0582a62009-12-15 09:54:21 +000014122 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014123 v8::Isolate* isolate = context->GetIsolate();
Steve Blockd0582a62009-12-15 09:54:21 +000014124
14125 v8::Persistent<v8::Object> handle1, handle2, handle3;
14126 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014127 v8::HandleScope scope(isolate);
14128 handle3.Reset(isolate, v8::Object::New(isolate));
14129 handle2.Reset(isolate, v8::Object::New(isolate));
14130 handle1.Reset(isolate, v8::Object::New(isolate));
Steve Blockd0582a62009-12-15 09:54:21 +000014131 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014132 handle2.SetWeak(&handle2, DisposingCallback,
14133 v8::WeakCallbackType::kParameter);
14134 handle3.SetWeak(&handle3, HandleCreatingCallback1,
14135 v8::WeakCallbackType::kParameter);
14136 CcTest::heap()->CollectAllGarbage();
14137 EmptyMessageQueues(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000014138}
14139
Steve Blocka7e24c12009-10-30 11:49:00 +000014140
14141THREADED_TEST(CheckForCrossContextObjectLiterals) {
14142 v8::V8::Initialize();
14143
14144 const int nof = 2;
14145 const char* sources[nof] = {
14146 "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
14147 "Object()"
14148 };
14149
14150 for (int i = 0; i < nof; i++) {
14151 const char* source = sources[i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014152 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000014153 LocalContext context;
14154 CompileRun(source);
14155 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014156 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000014157 LocalContext context;
14158 CompileRun(source);
14159 }
14160 }
14161}
14162
14163
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014164static v8::Local<Value> NestedScope(v8::Local<Context> env) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014165 v8::EscapableHandleScope inner(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000014166 env->Enter();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014167 v8::Local<Value> three = v8_num(3);
14168 v8::Local<Value> value = inner.Escape(three);
Steve Blocka7e24c12009-10-30 11:49:00 +000014169 env->Exit();
14170 return value;
14171}
14172
14173
14174THREADED_TEST(NestedHandleScopeAndContexts) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014175 v8::Isolate* isolate = CcTest::isolate();
14176 v8::HandleScope outer(isolate);
14177 v8::Local<Context> env = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000014178 env->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014179 v8::Local<Value> value = NestedScope(env);
14180 v8::Local<String> str(value->ToString(env).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010014181 CHECK(!str.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000014182 env->Exit();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014183}
14184
14185
14186static bool MatchPointers(void* key1, void* key2) {
14187 return key1 == key2;
14188}
14189
14190
14191struct SymbolInfo {
14192 size_t id;
14193 size_t size;
14194 std::string name;
14195};
14196
14197
14198class SetFunctionEntryHookTest {
14199 public:
14200 SetFunctionEntryHookTest() {
14201 CHECK(instance_ == NULL);
14202 instance_ = this;
14203 }
14204 ~SetFunctionEntryHookTest() {
14205 CHECK(instance_ == this);
14206 instance_ = NULL;
14207 }
14208 void Reset() {
14209 symbols_.clear();
14210 symbol_locations_.clear();
14211 invocations_.clear();
14212 }
14213 void RunTest();
14214 void OnJitEvent(const v8::JitCodeEvent* event);
14215 static void JitEvent(const v8::JitCodeEvent* event) {
14216 CHECK(instance_ != NULL);
14217 instance_->OnJitEvent(event);
14218 }
14219
14220 void OnEntryHook(uintptr_t function,
14221 uintptr_t return_addr_location);
14222 static void EntryHook(uintptr_t function,
14223 uintptr_t return_addr_location) {
14224 CHECK(instance_ != NULL);
14225 instance_->OnEntryHook(function, return_addr_location);
14226 }
14227
14228 static void RuntimeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
14229 CHECK(instance_ != NULL);
14230 args.GetReturnValue().Set(v8_num(42));
14231 }
14232 void RunLoopInNewEnv(v8::Isolate* isolate);
14233
14234 // Records addr as location of symbol.
14235 void InsertSymbolAt(i::Address addr, SymbolInfo* symbol);
14236
14237 // Finds the symbol containing addr
14238 SymbolInfo* FindSymbolForAddr(i::Address addr);
14239 // Returns the number of invocations where the caller name contains
14240 // \p caller_name and the function name contains \p function_name.
14241 int CountInvocations(const char* caller_name,
14242 const char* function_name);
14243
14244 i::Handle<i::JSFunction> foo_func_;
14245 i::Handle<i::JSFunction> bar_func_;
14246
14247 typedef std::map<size_t, SymbolInfo> SymbolMap;
14248 typedef std::map<i::Address, SymbolInfo*> SymbolLocationMap;
14249 typedef std::map<std::pair<SymbolInfo*, SymbolInfo*>, int> InvocationMap;
14250 SymbolMap symbols_;
14251 SymbolLocationMap symbol_locations_;
14252 InvocationMap invocations_;
14253
14254 static SetFunctionEntryHookTest* instance_;
14255};
14256SetFunctionEntryHookTest* SetFunctionEntryHookTest::instance_ = NULL;
14257
14258
14259// Returns true if addr is in the range [start, start+len).
14260static bool Overlaps(i::Address start, size_t len, i::Address addr) {
14261 if (start <= addr && start + len > addr)
14262 return true;
14263
14264 return false;
14265}
14266
14267void SetFunctionEntryHookTest::InsertSymbolAt(i::Address addr,
14268 SymbolInfo* symbol) {
14269 // Insert the symbol at the new location.
14270 SymbolLocationMap::iterator it =
14271 symbol_locations_.insert(std::make_pair(addr, symbol)).first;
14272 // Now erase symbols to the left and right that overlap this one.
14273 while (it != symbol_locations_.begin()) {
14274 SymbolLocationMap::iterator left = it;
14275 --left;
14276 if (!Overlaps(left->first, left->second->size, addr))
14277 break;
14278 symbol_locations_.erase(left);
14279 }
14280
14281 // Now erase symbols to the left and right that overlap this one.
14282 while (true) {
14283 SymbolLocationMap::iterator right = it;
14284 ++right;
14285 if (right == symbol_locations_.end())
14286 break;
14287 if (!Overlaps(addr, symbol->size, right->first))
14288 break;
14289 symbol_locations_.erase(right);
14290 }
14291}
14292
14293
14294void SetFunctionEntryHookTest::OnJitEvent(const v8::JitCodeEvent* event) {
14295 switch (event->type) {
14296 case v8::JitCodeEvent::CODE_ADDED: {
14297 CHECK(event->code_start != NULL);
14298 CHECK_NE(0, static_cast<int>(event->code_len));
14299 CHECK(event->name.str != NULL);
14300 size_t symbol_id = symbols_.size();
14301
14302 // Record the new symbol.
14303 SymbolInfo& info = symbols_[symbol_id];
14304 info.id = symbol_id;
14305 info.size = event->code_len;
14306 info.name.assign(event->name.str, event->name.str + event->name.len);
14307
14308 // And record it's location.
14309 InsertSymbolAt(reinterpret_cast<i::Address>(event->code_start), &info);
14310 }
14311 break;
14312
14313 case v8::JitCodeEvent::CODE_MOVED: {
14314 // We would like to never see code move that we haven't seen before,
14315 // but the code creation event does not happen until the line endings
14316 // have been calculated (this is so that we can report the line in the
14317 // script at which the function source is found, see
14318 // Compiler::RecordFunctionCompilation) and the line endings
14319 // calculations can cause a GC, which can move the newly created code
14320 // before its existence can be logged.
14321 SymbolLocationMap::iterator it(
14322 symbol_locations_.find(
14323 reinterpret_cast<i::Address>(event->code_start)));
14324 if (it != symbol_locations_.end()) {
14325 // Found a symbol at this location, move it.
14326 SymbolInfo* info = it->second;
14327 symbol_locations_.erase(it);
14328 InsertSymbolAt(reinterpret_cast<i::Address>(event->new_code_start),
14329 info);
14330 }
14331 }
14332 default:
14333 break;
14334 }
14335}
14336
14337void SetFunctionEntryHookTest::OnEntryHook(
14338 uintptr_t function, uintptr_t return_addr_location) {
14339 // Get the function's code object.
14340 i::Code* function_code = i::Code::GetCodeFromTargetAddress(
14341 reinterpret_cast<i::Address>(function));
14342 CHECK(function_code != NULL);
14343
14344 // Then try and look up the caller's code object.
14345 i::Address caller = *reinterpret_cast<i::Address*>(return_addr_location);
14346
14347 // Count the invocation.
14348 SymbolInfo* caller_symbol = FindSymbolForAddr(caller);
14349 SymbolInfo* function_symbol =
14350 FindSymbolForAddr(reinterpret_cast<i::Address>(function));
14351 ++invocations_[std::make_pair(caller_symbol, function_symbol)];
14352
14353 if (!bar_func_.is_null() && function_code == bar_func_->code()) {
14354 // Check that we have a symbol for the "bar" function at the right location.
14355 SymbolLocationMap::iterator it(
14356 symbol_locations_.find(function_code->instruction_start()));
14357 CHECK(it != symbol_locations_.end());
14358 }
14359
14360 if (!foo_func_.is_null() && function_code == foo_func_->code()) {
14361 // Check that we have a symbol for "foo" at the right location.
14362 SymbolLocationMap::iterator it(
14363 symbol_locations_.find(function_code->instruction_start()));
14364 CHECK(it != symbol_locations_.end());
14365 }
14366}
14367
14368
14369SymbolInfo* SetFunctionEntryHookTest::FindSymbolForAddr(i::Address addr) {
14370 SymbolLocationMap::iterator it(symbol_locations_.lower_bound(addr));
14371 // Do we have a direct hit on a symbol?
14372 if (it != symbol_locations_.end()) {
14373 if (it->first == addr)
14374 return it->second;
14375 }
14376
14377 // If not a direct hit, it'll have to be the previous symbol.
14378 if (it == symbol_locations_.begin())
14379 return NULL;
14380
14381 --it;
14382 size_t offs = addr - it->first;
14383 if (offs < it->second->size)
14384 return it->second;
14385
14386 return NULL;
14387}
14388
14389
14390int SetFunctionEntryHookTest::CountInvocations(
14391 const char* caller_name, const char* function_name) {
14392 InvocationMap::iterator it(invocations_.begin());
14393 int invocations = 0;
14394 for (; it != invocations_.end(); ++it) {
14395 SymbolInfo* caller = it->first.first;
14396 SymbolInfo* function = it->first.second;
14397
14398 // Filter out non-matching functions.
14399 if (function_name != NULL) {
14400 if (function->name.find(function_name) == std::string::npos)
14401 continue;
14402 }
14403
14404 // Filter out non-matching callers.
14405 if (caller_name != NULL) {
14406 if (caller == NULL)
14407 continue;
14408 if (caller->name.find(caller_name) == std::string::npos)
14409 continue;
14410 }
14411
14412 // It matches add the invocation count to the tally.
14413 invocations += it->second;
14414 }
14415
14416 return invocations;
14417}
14418
14419
14420void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
14421 v8::HandleScope outer(isolate);
14422 v8::Local<Context> env = Context::New(isolate);
14423 env->Enter();
14424
14425 Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
14426 t->Set(v8_str("asdf"), v8::FunctionTemplate::New(isolate, RuntimeCallback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014427 CHECK(env->Global()
14428 ->Set(env, v8_str("obj"), t->NewInstance(env).ToLocalChecked())
14429 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014430
14431 const char* script =
14432 "function bar() {\n"
14433 " var sum = 0;\n"
14434 " for (i = 0; i < 100; ++i)\n"
14435 " sum = foo(i);\n"
14436 " return sum;\n"
14437 "}\n"
14438 "function foo(i) { return i * i; }\n"
14439 "// Invoke on the runtime function.\n"
14440 "obj.asdf()";
14441 CompileRun(script);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014442 bar_func_ = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(
14443 *env->Global()->Get(env, v8_str("bar")).ToLocalChecked()));
14444 CHECK(!bar_func_.is_null());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014445
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014446 foo_func_ = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(
14447 *env->Global()->Get(env, v8_str("foo")).ToLocalChecked()));
14448 CHECK(!foo_func_.is_null());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014449
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014450 v8::Local<v8::Value> value = CompileRun("bar();");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014451 CHECK(value->IsNumber());
14452 CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
14453
14454 // Test the optimized codegen path.
14455 value = CompileRun("%OptimizeFunctionOnNextCall(foo);"
14456 "bar();");
14457 CHECK(value->IsNumber());
14458 CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
14459
14460 env->Exit();
14461}
14462
14463
14464void SetFunctionEntryHookTest::RunTest() {
14465 // Work in a new isolate throughout.
14466 v8::Isolate::CreateParams create_params;
14467 create_params.entry_hook = EntryHook;
14468 create_params.code_event_handler = JitEvent;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014469 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014470 v8::Isolate* isolate = v8::Isolate::New(create_params);
14471
14472 {
14473 v8::Isolate::Scope scope(isolate);
14474
14475 RunLoopInNewEnv(isolate);
14476
14477 // Check the exepected invocation counts.
14478 CHECK_EQ(2, CountInvocations(NULL, "bar"));
14479 CHECK_EQ(200, CountInvocations("bar", "foo"));
14480 CHECK_EQ(200, CountInvocations(NULL, "foo"));
14481
14482 // Verify that we have an entry hook on some specific stubs.
14483 CHECK_NE(0, CountInvocations(NULL, "CEntryStub"));
14484 CHECK_NE(0, CountInvocations(NULL, "JSEntryStub"));
14485 CHECK_NE(0, CountInvocations(NULL, "JSEntryTrampoline"));
14486 }
14487 isolate->Dispose();
14488
14489 Reset();
14490
14491 // Make sure a second isolate is unaffected by the previous entry hook.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014492 create_params = v8::Isolate::CreateParams();
14493 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
14494 isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014495 {
14496 v8::Isolate::Scope scope(isolate);
14497
14498 // Reset the entry count to zero and set the entry hook.
14499 RunLoopInNewEnv(isolate);
14500
14501 // We should record no invocations in this isolate.
14502 CHECK_EQ(0, static_cast<int>(invocations_.size()));
14503 }
14504
14505 isolate->Dispose();
14506}
14507
14508
14509TEST(SetFunctionEntryHook) {
14510 // FunctionEntryHook does not work well with experimental natives.
14511 // Experimental natives are compiled during snapshot deserialization.
14512 // This test breaks because InstallGetter (function from snapshot that
14513 // only gets called from experimental natives) is compiled with entry hooks.
14514 i::FLAG_allow_natives_syntax = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014515 i::FLAG_turbo_inlining = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014516 i::FLAG_use_inlining = false;
14517
14518 SetFunctionEntryHookTest test;
14519 test.RunTest();
14520}
14521
14522
14523static i::HashMap* code_map = NULL;
14524static i::HashMap* jitcode_line_info = NULL;
14525static int saw_bar = 0;
14526static int move_events = 0;
14527
14528
14529static bool FunctionNameIs(const char* expected,
14530 const v8::JitCodeEvent* event) {
14531 // Log lines for functions are of the general form:
Ben Murdochda12d292016-06-02 14:46:10 +010014532 // "LazyCompile:<type><function_name>" or Function:<type><function_name>,
14533 // where the type is one of "*", "~" or "".
14534 static const char* kPreamble;
14535 if (!i::FLAG_lazy || (i::FLAG_ignition && i::FLAG_ignition_eager)) {
14536 kPreamble = "Function:";
14537 } else {
14538 kPreamble = "LazyCompile:";
14539 }
14540 static size_t kPreambleLen = strlen(kPreamble);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014541
Ben Murdochda12d292016-06-02 14:46:10 +010014542 if (event->name.len < kPreambleLen ||
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014543 strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
14544 return false;
14545 }
14546
14547 const char* tail = event->name.str + kPreambleLen;
14548 size_t tail_len = event->name.len - kPreambleLen;
14549 size_t expected_len = strlen(expected);
14550 if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
14551 --tail_len;
14552 ++tail;
14553 }
14554
14555 // Check for tails like 'bar :1'.
14556 if (tail_len > expected_len + 2 &&
14557 tail[expected_len] == ' ' &&
14558 tail[expected_len + 1] == ':' &&
14559 tail[expected_len + 2] &&
14560 !strncmp(tail, expected, expected_len)) {
14561 return true;
14562 }
14563
14564 if (tail_len != expected_len)
14565 return false;
14566
14567 return strncmp(tail, expected, expected_len) == 0;
14568}
14569
14570
14571static void event_handler(const v8::JitCodeEvent* event) {
14572 CHECK(event != NULL);
14573 CHECK(code_map != NULL);
14574 CHECK(jitcode_line_info != NULL);
14575
14576 class DummyJitCodeLineInfo {
14577 };
14578
14579 switch (event->type) {
14580 case v8::JitCodeEvent::CODE_ADDED: {
14581 CHECK(event->code_start != NULL);
14582 CHECK_NE(0, static_cast<int>(event->code_len));
14583 CHECK(event->name.str != NULL);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014584 i::HashMap::Entry* entry = code_map->LookupOrInsert(
14585 event->code_start, i::ComputePointerHash(event->code_start));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014586 entry->value = reinterpret_cast<void*>(event->code_len);
14587
14588 if (FunctionNameIs("bar", event)) {
14589 ++saw_bar;
14590 }
14591 }
14592 break;
14593
14594 case v8::JitCodeEvent::CODE_MOVED: {
14595 uint32_t hash = i::ComputePointerHash(event->code_start);
14596 // We would like to never see code move that we haven't seen before,
14597 // but the code creation event does not happen until the line endings
14598 // have been calculated (this is so that we can report the line in the
14599 // script at which the function source is found, see
14600 // Compiler::RecordFunctionCompilation) and the line endings
14601 // calculations can cause a GC, which can move the newly created code
14602 // before its existence can be logged.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014603 i::HashMap::Entry* entry = code_map->Lookup(event->code_start, hash);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014604 if (entry != NULL) {
14605 ++move_events;
14606
14607 CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
14608 code_map->Remove(event->code_start, hash);
14609
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014610 entry = code_map->LookupOrInsert(
14611 event->new_code_start,
14612 i::ComputePointerHash(event->new_code_start));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014613 entry->value = reinterpret_cast<void*>(event->code_len);
14614 }
14615 }
14616 break;
14617
14618 case v8::JitCodeEvent::CODE_REMOVED:
14619 // Object/code removal events are currently not dispatched from the GC.
14620 CHECK(false);
14621 break;
14622
14623 // For CODE_START_LINE_INFO_RECORDING event, we will create one
14624 // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
14625 // record it in jitcode_line_info.
14626 case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
14627 DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
14628 v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
14629 temp_event->user_data = line_info;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014630 i::HashMap::Entry* entry = jitcode_line_info->LookupOrInsert(
14631 line_info, i::ComputePointerHash(line_info));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014632 entry->value = reinterpret_cast<void*>(line_info);
14633 }
14634 break;
14635 // For these two events, we will check whether the event->user_data
14636 // data structure is created before during CODE_START_LINE_INFO_RECORDING
14637 // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
14638 case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
14639 CHECK(event->user_data != NULL);
14640 uint32_t hash = i::ComputePointerHash(event->user_data);
14641 i::HashMap::Entry* entry =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014642 jitcode_line_info->Lookup(event->user_data, hash);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014643 CHECK(entry != NULL);
14644 delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
14645 }
14646 break;
14647
14648 case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
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 }
14655 break;
14656
14657 default:
14658 // Impossible event.
14659 CHECK(false);
14660 break;
14661 }
14662}
14663
14664
14665UNINITIALIZED_TEST(SetJitCodeEventHandler) {
14666 i::FLAG_stress_compaction = true;
14667 i::FLAG_incremental_marking = false;
14668 if (i::FLAG_never_compact) return;
14669 const char* script =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014670 "function bar() {"
14671 " var sum = 0;"
14672 " for (i = 0; i < 10; ++i)"
14673 " sum = foo(i);"
14674 " return sum;"
14675 "}"
14676 "function foo(i) { return i; };"
14677 "bar();";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014678
14679 // Run this test in a new isolate to make sure we don't
14680 // have remnants of state from other code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014681 v8::Isolate::CreateParams create_params;
14682 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
14683 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014684 isolate->Enter();
14685 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
14686 i::Heap* heap = i_isolate->heap();
14687
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014688 // Start with a clean slate.
14689 heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler_Prepare");
14690
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014691 {
14692 v8::HandleScope scope(isolate);
14693 i::HashMap code(MatchPointers);
14694 code_map = &code;
14695
14696 i::HashMap lineinfo(MatchPointers);
14697 jitcode_line_info = &lineinfo;
14698
14699 saw_bar = 0;
14700 move_events = 0;
14701
14702 isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
14703
14704 // Generate new code objects sparsely distributed across several
14705 // different fragmented code-space pages.
14706 const int kIterations = 10;
14707 for (int i = 0; i < kIterations; ++i) {
14708 LocalContext env(isolate);
14709 i::AlwaysAllocateScope always_allocate(i_isolate);
Ben Murdochda12d292016-06-02 14:46:10 +010014710 SimulateFullSpace(i::FLAG_ignition ? heap->old_space()
14711 : heap->code_space());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014712 CompileRun(script);
14713
14714 // Keep a strong reference to the code object in the handle scope.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014715 i::Handle<i::Code> bar_code(
14716 i::Handle<i::JSFunction>::cast(
14717 v8::Utils::OpenHandle(*env->Global()
14718 ->Get(env.local(), v8_str("bar"))
14719 .ToLocalChecked()))
14720 ->code());
14721 i::Handle<i::Code> foo_code(
14722 i::Handle<i::JSFunction>::cast(
14723 v8::Utils::OpenHandle(*env->Global()
14724 ->Get(env.local(), v8_str("foo"))
14725 .ToLocalChecked()))
14726 ->code());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014727
14728 // Clear the compilation cache to get more wastage.
14729 reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear();
14730 }
14731
14732 // Force code movement.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014733 heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler_Move");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014734
14735 isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
14736
14737 CHECK_LE(kIterations, saw_bar);
14738 CHECK_LT(0, move_events);
14739
14740 code_map = NULL;
14741 jitcode_line_info = NULL;
14742 }
14743
14744 isolate->Exit();
14745 isolate->Dispose();
14746
14747 // Do this in a new isolate.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014748 isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014749 isolate->Enter();
14750
14751 // Verify that we get callbacks for existing code objects when we
14752 // request enumeration of existing code.
14753 {
14754 v8::HandleScope scope(isolate);
14755 LocalContext env(isolate);
14756 CompileRun(script);
14757
14758 // Now get code through initial iteration.
14759 i::HashMap code(MatchPointers);
14760 code_map = &code;
14761
14762 i::HashMap lineinfo(MatchPointers);
14763 jitcode_line_info = &lineinfo;
14764
14765 isolate->SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting,
14766 event_handler);
14767 isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
14768
14769 jitcode_line_info = NULL;
14770 // We expect that we got some events. Note that if we could get code removal
14771 // notifications, we could compare two collections, one created by listening
14772 // from the time of creation of an isolate, and the other by subscribing
14773 // with EnumExisting.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014774 CHECK_LT(0u, code.occupancy());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014775
14776 code_map = NULL;
14777 }
14778
14779 isolate->Exit();
14780 isolate->Dispose();
Steve Blocka7e24c12009-10-30 11:49:00 +000014781}
14782
14783
14784THREADED_TEST(ExternalAllocatedMemory) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014785 v8::Isolate* isolate = CcTest::isolate();
14786 v8::HandleScope outer(isolate);
14787 v8::Local<Context> env(Context::New(isolate));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010014788 CHECK(!env.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014789 const int64_t kSize = 1024*1024;
14790 int64_t baseline = isolate->AdjustAmountOfExternalAllocatedMemory(0);
14791 CHECK_EQ(baseline + kSize,
14792 isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
14793 CHECK_EQ(baseline,
14794 isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014795 const int64_t kTriggerGCSize =
14796 v8::internal::Internals::kExternalAllocationLimit + 1;
14797 CHECK_EQ(baseline + kTriggerGCSize,
14798 isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize));
14799 CHECK_EQ(baseline,
14800 isolate->AdjustAmountOfExternalAllocatedMemory(-kTriggerGCSize));
14801}
14802
14803
14804TEST(Regress51719) {
14805 i::FLAG_incremental_marking = false;
14806 CcTest::InitializeVM();
14807
14808 const int64_t kTriggerGCSize =
14809 v8::internal::Internals::kExternalAllocationLimit + 1;
14810 v8::Isolate* isolate = CcTest::isolate();
14811 isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize);
Steve Blocka7e24c12009-10-30 11:49:00 +000014812}
14813
14814
14815// Regression test for issue 54, object templates with internal fields
14816// but no accessors or interceptors did not get their internal field
14817// count set on instances.
14818THREADED_TEST(Regress54) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014819 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014820 v8::Isolate* isolate = context->GetIsolate();
14821 v8::HandleScope outer(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000014822 static v8::Persistent<v8::ObjectTemplate> templ;
14823 if (templ.IsEmpty()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014824 v8::EscapableHandleScope inner(isolate);
14825 v8::Local<v8::ObjectTemplate> local = v8::ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000014826 local->SetInternalFieldCount(1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014827 templ.Reset(isolate, inner.Escape(local));
Steve Blocka7e24c12009-10-30 11:49:00 +000014828 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014829 v8::Local<v8::Object> result =
14830 v8::Local<v8::ObjectTemplate>::New(isolate, templ)
14831 ->NewInstance(context.local())
14832 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000014833 CHECK_EQ(1, result->InternalFieldCount());
14834}
14835
14836
14837// If part of the threaded tests, this test makes ThreadingTest fail
14838// on mac.
14839TEST(CatchStackOverflow) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014840 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014841 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014842 v8::TryCatch try_catch(context->GetIsolate());
14843 v8::Local<v8::Value> result = CompileRun(
14844 "function f() {"
14845 " return f();"
14846 "}"
14847 ""
14848 "f();");
Steve Blocka7e24c12009-10-30 11:49:00 +000014849 CHECK(result.IsEmpty());
14850}
14851
14852
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014853static void CheckTryCatchSourceInfo(v8::Local<v8::Script> script,
Steve Blocka7e24c12009-10-30 11:49:00 +000014854 const char* resource_name,
14855 int line_offset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014856 v8::HandleScope scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014857 v8::TryCatch try_catch(CcTest::isolate());
14858 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
14859 CHECK(script->Run(context).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000014860 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014861 v8::Local<v8::Message> message = try_catch.Message();
Steve Blocka7e24c12009-10-30 11:49:00 +000014862 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014863 CHECK_EQ(10 + line_offset, message->GetLineNumber(context).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000014864 CHECK_EQ(91, message->GetStartPosition());
14865 CHECK_EQ(92, message->GetEndPosition());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014866 CHECK_EQ(2, message->GetStartColumn(context).FromJust());
14867 CHECK_EQ(3, message->GetEndColumn(context).FromJust());
14868 v8::String::Utf8Value line(message->GetSourceLine(context).ToLocalChecked());
14869 CHECK_EQ(0, strcmp(" throw 'nirk';", *line));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014870 v8::String::Utf8Value name(message->GetScriptOrigin().ResourceName());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014871 CHECK_EQ(0, strcmp(resource_name, *name));
Steve Blocka7e24c12009-10-30 11:49:00 +000014872}
14873
14874
14875THREADED_TEST(TryCatchSourceInfo) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014876 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014877 v8::HandleScope scope(context->GetIsolate());
14878 v8::Local<v8::String> source = v8_str(
Steve Blocka7e24c12009-10-30 11:49:00 +000014879 "function Foo() {\n"
14880 " return Bar();\n"
14881 "}\n"
14882 "\n"
14883 "function Bar() {\n"
14884 " return Baz();\n"
14885 "}\n"
14886 "\n"
14887 "function Baz() {\n"
14888 " throw 'nirk';\n"
14889 "}\n"
14890 "\n"
14891 "Foo();\n");
14892
14893 const char* resource_name;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014894 v8::Local<v8::Script> script;
Steve Blocka7e24c12009-10-30 11:49:00 +000014895 resource_name = "test.js";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014896 script = CompileWithOrigin(source, resource_name);
Steve Blocka7e24c12009-10-30 11:49:00 +000014897 CheckTryCatchSourceInfo(script, resource_name, 0);
14898
14899 resource_name = "test1.js";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014900 v8::ScriptOrigin origin1(v8_str(resource_name));
14901 script =
14902 v8::Script::Compile(context.local(), source, &origin1).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000014903 CheckTryCatchSourceInfo(script, resource_name, 0);
14904
14905 resource_name = "test2.js";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014906 v8::ScriptOrigin origin2(v8_str(resource_name),
14907 v8::Integer::New(context->GetIsolate(), 7));
14908 script =
14909 v8::Script::Compile(context.local(), source, &origin2).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000014910 CheckTryCatchSourceInfo(script, resource_name, 7);
14911}
14912
14913
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014914THREADED_TEST(TryCatchSourceInfoForEOSError) {
14915 LocalContext context;
14916 v8::HandleScope scope(context->GetIsolate());
14917 v8::TryCatch try_catch(context->GetIsolate());
14918 CHECK(v8::Script::Compile(context.local(), v8_str("!\n")).IsEmpty());
14919 CHECK(try_catch.HasCaught());
14920 v8::Local<v8::Message> message = try_catch.Message();
14921 CHECK_EQ(1, message->GetLineNumber(context.local()).FromJust());
14922 CHECK_EQ(0, message->GetStartColumn(context.local()).FromJust());
14923}
14924
14925
Steve Blocka7e24c12009-10-30 11:49:00 +000014926THREADED_TEST(CompilationCache) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014927 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014928 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014929 v8::Local<v8::String> source0 = v8_str("1234");
14930 v8::Local<v8::String> source1 = v8_str("1234");
14931 v8::Local<v8::Script> script0 = CompileWithOrigin(source0, "test.js");
14932 v8::Local<v8::Script> script1 = CompileWithOrigin(source1, "test.js");
14933 v8::Local<v8::Script> script2 = v8::Script::Compile(context.local(), source0)
14934 .ToLocalChecked(); // different origin
14935 CHECK_EQ(1234, script0->Run(context.local())
14936 .ToLocalChecked()
14937 ->Int32Value(context.local())
14938 .FromJust());
14939 CHECK_EQ(1234, script1->Run(context.local())
14940 .ToLocalChecked()
14941 ->Int32Value(context.local())
14942 .FromJust());
14943 CHECK_EQ(1234, script2->Run(context.local())
14944 .ToLocalChecked()
14945 ->Int32Value(context.local())
14946 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000014947}
14948
14949
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014950static void FunctionNameCallback(
14951 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014952 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014953 args.GetReturnValue().Set(v8_num(42));
Steve Blocka7e24c12009-10-30 11:49:00 +000014954}
14955
14956
14957THREADED_TEST(CallbackFunctionName) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014958 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014959 v8::Isolate* isolate = context->GetIsolate();
14960 v8::HandleScope scope(isolate);
14961 Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
14962 t->Set(v8_str("asdf"),
14963 v8::FunctionTemplate::New(isolate, FunctionNameCallback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014964 CHECK(context->Global()
14965 ->Set(context.local(), v8_str("obj"),
14966 t->NewInstance(context.local()).ToLocalChecked())
14967 .FromJust());
14968 v8::Local<v8::Value> value = CompileRun("obj.asdf.name");
Steve Blocka7e24c12009-10-30 11:49:00 +000014969 CHECK(value->IsString());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014970 v8::String::Utf8Value name(value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014971 CHECK_EQ(0, strcmp("asdf", *name));
Steve Blocka7e24c12009-10-30 11:49:00 +000014972}
14973
14974
14975THREADED_TEST(DateAccess) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014976 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014977 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014978 v8::Local<v8::Value> date =
14979 v8::Date::New(context.local(), 1224744689038.0).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000014980 CHECK(date->IsDate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014981 CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
Steve Blocka7e24c12009-10-30 11:49:00 +000014982}
14983
14984
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014985void CheckProperties(v8::Isolate* isolate, v8::Local<v8::Value> val,
14986 unsigned elmc, const char* elmv[]) {
14987 v8::Local<v8::Context> context = isolate->GetCurrentContext();
14988 v8::Local<v8::Object> obj = val.As<v8::Object>();
14989 v8::Local<v8::Array> props = obj->GetPropertyNames(context).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000014990 CHECK_EQ(elmc, props->Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014991 for (unsigned i = 0; i < elmc; i++) {
14992 v8::String::Utf8Value elm(
14993 props->Get(context, v8::Integer::New(isolate, i)).ToLocalChecked());
14994 CHECK_EQ(0, strcmp(elmv[i], *elm));
Steve Blocka7e24c12009-10-30 11:49:00 +000014995 }
14996}
14997
14998
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014999void CheckOwnProperties(v8::Isolate* isolate, v8::Local<v8::Value> val,
15000 unsigned elmc, const char* elmv[]) {
15001 v8::Local<v8::Context> context = isolate->GetCurrentContext();
15002 v8::Local<v8::Object> obj = val.As<v8::Object>();
15003 v8::Local<v8::Array> props =
15004 obj->GetOwnPropertyNames(context).ToLocalChecked();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000015005 CHECK_EQ(elmc, props->Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015006 for (unsigned i = 0; i < elmc; i++) {
15007 v8::String::Utf8Value elm(
15008 props->Get(context, v8::Integer::New(isolate, i)).ToLocalChecked());
15009 CHECK_EQ(0, strcmp(elmv[i], *elm));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000015010 }
15011}
15012
15013
Steve Blocka7e24c12009-10-30 11:49:00 +000015014THREADED_TEST(PropertyEnumeration) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015015 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015016 v8::Isolate* isolate = context->GetIsolate();
15017 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015018 v8::Local<v8::Value> obj = CompileRun(
Steve Blocka7e24c12009-10-30 11:49:00 +000015019 "var result = [];"
15020 "result[0] = {};"
15021 "result[1] = {a: 1, b: 2};"
15022 "result[2] = [1, 2, 3];"
15023 "var proto = {x: 1, y: 2, z: 3};"
15024 "var x = { __proto__: proto, w: 0, z: 1 };"
15025 "result[3] = x;"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015026 "result;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015027 v8::Local<v8::Array> elms = obj.As<v8::Array>();
15028 CHECK_EQ(4u, elms->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +000015029 int elmc0 = 0;
15030 const char** elmv0 = NULL;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015031 CheckProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015032 isolate,
15033 elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
15034 elmc0, elmv0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015035 CheckOwnProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015036 isolate,
15037 elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
15038 elmc0, elmv0);
Steve Blocka7e24c12009-10-30 11:49:00 +000015039 int elmc1 = 2;
15040 const char* elmv1[] = {"a", "b"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015041 CheckProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015042 isolate,
15043 elms->Get(context.local(), v8::Integer::New(isolate, 1)).ToLocalChecked(),
15044 elmc1, elmv1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015045 CheckOwnProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015046 isolate,
15047 elms->Get(context.local(), v8::Integer::New(isolate, 1)).ToLocalChecked(),
15048 elmc1, elmv1);
Steve Blocka7e24c12009-10-30 11:49:00 +000015049 int elmc2 = 3;
15050 const char* elmv2[] = {"0", "1", "2"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015051 CheckProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015052 isolate,
15053 elms->Get(context.local(), v8::Integer::New(isolate, 2)).ToLocalChecked(),
15054 elmc2, elmv2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015055 CheckOwnProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015056 isolate,
15057 elms->Get(context.local(), v8::Integer::New(isolate, 2)).ToLocalChecked(),
15058 elmc2, elmv2);
Steve Blocka7e24c12009-10-30 11:49:00 +000015059 int elmc3 = 4;
15060 const char* elmv3[] = {"w", "z", "x", "y"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015061 CheckProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015062 isolate,
15063 elms->Get(context.local(), v8::Integer::New(isolate, 3)).ToLocalChecked(),
15064 elmc3, elmv3);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000015065 int elmc4 = 2;
15066 const char* elmv4[] = {"w", "z"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015067 CheckOwnProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015068 isolate,
15069 elms->Get(context.local(), v8::Integer::New(isolate, 3)).ToLocalChecked(),
15070 elmc4, elmv4);
Steve Blocka7e24c12009-10-30 11:49:00 +000015071}
15072
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015073
Steve Block44f0eee2011-05-26 01:26:41 +010015074THREADED_TEST(PropertyEnumeration2) {
Steve Block44f0eee2011-05-26 01:26:41 +010015075 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015076 v8::Isolate* isolate = context->GetIsolate();
15077 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015078 v8::Local<v8::Value> obj = CompileRun(
Steve Block44f0eee2011-05-26 01:26:41 +010015079 "var result = [];"
15080 "result[0] = {};"
15081 "result[1] = {a: 1, b: 2};"
15082 "result[2] = [1, 2, 3];"
15083 "var proto = {x: 1, y: 2, z: 3};"
15084 "var x = { __proto__: proto, w: 0, z: 1 };"
15085 "result[3] = x;"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015086 "result;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015087 v8::Local<v8::Array> elms = obj.As<v8::Array>();
15088 CHECK_EQ(4u, elms->Length());
Steve Block44f0eee2011-05-26 01:26:41 +010015089 int elmc0 = 0;
15090 const char** elmv0 = NULL;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015091 CheckProperties(
15092 isolate,
15093 elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
15094 elmc0, elmv0);
Steve Block44f0eee2011-05-26 01:26:41 +010015095
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015096 v8::Local<v8::Value> val =
15097 elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked();
15098 v8::Local<v8::Array> props =
15099 val.As<v8::Object>()->GetPropertyNames(context.local()).ToLocalChecked();
15100 CHECK_EQ(0u, props->Length());
Steve Block44f0eee2011-05-26 01:26:41 +010015101 for (uint32_t i = 0; i < props->Length(); i++) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015102 printf("p[%u]\n", i);
Steve Block44f0eee2011-05-26 01:26:41 +010015103 }
15104}
Steve Blocka7e24c12009-10-30 11:49:00 +000015105
Steve Blocka7e24c12009-10-30 11:49:00 +000015106
15107THREADED_TEST(AccessChecksReenabledCorrectly) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015108 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015109 v8::Isolate* isolate = context->GetIsolate();
15110 v8::HandleScope scope(isolate);
15111 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015112 templ->SetAccessCheckCallback(AccessAlwaysBlocked);
Steve Blocka7e24c12009-10-30 11:49:00 +000015113 templ->Set(v8_str("a"), v8_str("a"));
15114 // Add more than 8 (see kMaxFastProperties) properties
15115 // so that the constructor will force copying map.
15116 // Cannot sprintf, gcc complains unsafety.
15117 char buf[4];
15118 for (char i = '0'; i <= '9' ; i++) {
15119 buf[0] = i;
15120 for (char j = '0'; j <= '9'; j++) {
15121 buf[1] = j;
15122 for (char k = '0'; k <= '9'; k++) {
15123 buf[2] = k;
15124 buf[3] = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015125 templ->Set(v8_str(buf), v8::Number::New(isolate, k));
Steve Blocka7e24c12009-10-30 11:49:00 +000015126 }
15127 }
15128 }
15129
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015130 Local<v8::Object> instance_1 =
15131 templ->NewInstance(context.local()).ToLocalChecked();
15132 CHECK(context->Global()
15133 ->Set(context.local(), v8_str("obj_1"), instance_1)
15134 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015135
15136 Local<Value> value_1 = CompileRun("obj_1.a");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015137 CHECK(value_1.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000015138
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015139 Local<v8::Object> instance_2 =
15140 templ->NewInstance(context.local()).ToLocalChecked();
15141 CHECK(context->Global()
15142 ->Set(context.local(), v8_str("obj_2"), instance_2)
15143 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015144
15145 Local<Value> value_2 = CompileRun("obj_2.a");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015146 CHECK(value_2.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000015147}
15148
15149
Leon Clarkef7060e22010-06-03 12:02:55 +010015150// Tests that ScriptData can be serialized and deserialized.
15151TEST(PreCompileSerialization) {
Ben Murdochda12d292016-06-02 14:46:10 +010015152 // Producing cached parser data while parsing eagerly is not supported.
15153 if (!i::FLAG_lazy || (i::FLAG_ignition && i::FLAG_ignition_eager)) return;
15154
Leon Clarkef7060e22010-06-03 12:02:55 +010015155 v8::V8::Initialize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015156 LocalContext env;
15157 v8::Isolate* isolate = env->GetIsolate();
15158 HandleScope handle_scope(isolate);
Leon Clarkef7060e22010-06-03 12:02:55 +010015159
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015160 i::FLAG_min_preparse_length = 0;
15161 const char* script = "function foo(a) { return a+1; }";
15162 v8::ScriptCompiler::Source source(v8_str(script));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015163 v8::ScriptCompiler::Compile(env.local(), &source,
15164 v8::ScriptCompiler::kProduceParserCache)
15165 .ToLocalChecked();
Leon Clarkef7060e22010-06-03 12:02:55 +010015166 // Serialize.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015167 const v8::ScriptCompiler::CachedData* cd = source.GetCachedData();
15168 i::byte* serialized_data = i::NewArray<i::byte>(cd->length);
15169 i::MemCopy(serialized_data, cd->data, cd->length);
Leon Clarkef7060e22010-06-03 12:02:55 +010015170
15171 // Deserialize.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015172 i::ScriptData* deserialized = new i::ScriptData(serialized_data, cd->length);
Leon Clarkef7060e22010-06-03 12:02:55 +010015173
15174 // Verify that the original is the same as the deserialized.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015175 CHECK_EQ(cd->length, deserialized->length());
15176 CHECK_EQ(0, memcmp(cd->data, deserialized->data(), cd->length));
Leon Clarkef7060e22010-06-03 12:02:55 +010015177
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015178 delete deserialized;
15179 i::DeleteArray(serialized_data);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010015180}
15181
15182
Steve Blocka7e24c12009-10-30 11:49:00 +000015183// This tests that we do not allow dictionary load/call inline caches
15184// to use functions that have not yet been compiled. The potential
15185// problem of loading a function that has not yet been compiled can
15186// arise because we share code between contexts via the compilation
15187// cache.
15188THREADED_TEST(DictionaryICLoadedFunction) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015189 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000015190 // Test LoadIC.
15191 for (int i = 0; i < 2; i++) {
15192 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015193 CHECK(context->Global()
15194 ->Set(context.local(), v8_str("tmp"), v8::True(CcTest::isolate()))
15195 .FromJust());
15196 context->Global()->Delete(context.local(), v8_str("tmp")).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +000015197 CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
15198 }
15199 // Test CallIC.
15200 for (int i = 0; i < 2; i++) {
15201 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015202 CHECK(context->Global()
15203 ->Set(context.local(), v8_str("tmp"), v8::True(CcTest::isolate()))
15204 .FromJust());
15205 context->Global()->Delete(context.local(), v8_str("tmp")).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +000015206 CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
15207 }
15208}
15209
15210
15211// Test that cross-context new calls use the context of the callee to
15212// create the new JavaScript object.
15213THREADED_TEST(CrossContextNew) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015214 v8::Isolate* isolate = CcTest::isolate();
15215 v8::HandleScope scope(isolate);
15216 v8::Local<Context> context0 = Context::New(isolate);
15217 v8::Local<Context> context1 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000015218
15219 // Allow cross-domain access.
15220 Local<String> token = v8_str("<security token>");
15221 context0->SetSecurityToken(token);
15222 context1->SetSecurityToken(token);
15223
15224 // Set an 'x' property on the Object prototype and define a
15225 // constructor function in context0.
15226 context0->Enter();
15227 CompileRun("Object.prototype.x = 42; function C() {};");
15228 context0->Exit();
15229
15230 // Call the constructor function from context0 and check that the
15231 // result has the 'x' property.
15232 context1->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015233 CHECK(context1->Global()
15234 ->Set(context1, v8_str("other"), context0->Global())
15235 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015236 Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
15237 CHECK(value->IsInt32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015238 CHECK_EQ(42, value->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015239 context1->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +000015240}
15241
15242
15243// Verify that we can clone an object
15244TEST(ObjectClone) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015245 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015246 v8::Isolate* isolate = env->GetIsolate();
15247 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000015248
15249 const char* sample =
15250 "var rv = {};" \
15251 "rv.alpha = 'hello';" \
15252 "rv.beta = 123;" \
15253 "rv;";
15254
15255 // Create an object, verify basics.
15256 Local<Value> val = CompileRun(sample);
15257 CHECK(val->IsObject());
Steve Block6ded16b2010-05-10 14:33:55 +010015258 Local<v8::Object> obj = val.As<v8::Object>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015259 obj->Set(env.local(), v8_str("gamma"), v8_str("cloneme")).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +000015260
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015261 CHECK(v8_str("hello")
15262 ->Equals(env.local(),
15263 obj->Get(env.local(), v8_str("alpha")).ToLocalChecked())
15264 .FromJust());
15265 CHECK(v8::Integer::New(isolate, 123)
15266 ->Equals(env.local(),
15267 obj->Get(env.local(), v8_str("beta")).ToLocalChecked())
15268 .FromJust());
15269 CHECK(v8_str("cloneme")
15270 ->Equals(env.local(),
15271 obj->Get(env.local(), v8_str("gamma")).ToLocalChecked())
15272 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015273
15274 // Clone it.
15275 Local<v8::Object> clone = obj->Clone();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015276 CHECK(v8_str("hello")
15277 ->Equals(env.local(),
15278 clone->Get(env.local(), v8_str("alpha")).ToLocalChecked())
15279 .FromJust());
15280 CHECK(v8::Integer::New(isolate, 123)
15281 ->Equals(env.local(),
15282 clone->Get(env.local(), v8_str("beta")).ToLocalChecked())
15283 .FromJust());
15284 CHECK(v8_str("cloneme")
15285 ->Equals(env.local(),
15286 clone->Get(env.local(), v8_str("gamma")).ToLocalChecked())
15287 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015288
15289 // Set a property on the clone, verify each object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015290 CHECK(clone->Set(env.local(), v8_str("beta"), v8::Integer::New(isolate, 456))
15291 .FromJust());
15292 CHECK(v8::Integer::New(isolate, 123)
15293 ->Equals(env.local(),
15294 obj->Get(env.local(), v8_str("beta")).ToLocalChecked())
15295 .FromJust());
15296 CHECK(v8::Integer::New(isolate, 456)
15297 ->Equals(env.local(),
15298 clone->Get(env.local(), v8_str("beta")).ToLocalChecked())
15299 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015300}
15301
15302
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015303class OneByteVectorResource : public v8::String::ExternalOneByteStringResource {
Steve Blocka7e24c12009-10-30 11:49:00 +000015304 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015305 explicit OneByteVectorResource(i::Vector<const char> vector)
Steve Blocka7e24c12009-10-30 11:49:00 +000015306 : data_(vector) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015307 virtual ~OneByteVectorResource() {}
Steve Blocka7e24c12009-10-30 11:49:00 +000015308 virtual size_t length() const { return data_.length(); }
15309 virtual const char* data() const { return data_.start(); }
15310 private:
15311 i::Vector<const char> data_;
15312};
15313
15314
15315class UC16VectorResource : public v8::String::ExternalStringResource {
15316 public:
15317 explicit UC16VectorResource(i::Vector<const i::uc16> vector)
15318 : data_(vector) {}
15319 virtual ~UC16VectorResource() {}
15320 virtual size_t length() const { return data_.length(); }
15321 virtual const i::uc16* data() const { return data_.start(); }
15322 private:
15323 i::Vector<const i::uc16> data_;
15324};
15325
15326
15327static void MorphAString(i::String* string,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015328 OneByteVectorResource* one_byte_resource,
Steve Blocka7e24c12009-10-30 11:49:00 +000015329 UC16VectorResource* uc16_resource) {
15330 CHECK(i::StringShape(string).IsExternal());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015331 if (string->IsOneByteRepresentation()) {
15332 // Check old map is not internalized or long.
15333 CHECK(string->map() == CcTest::heap()->external_one_byte_string_map());
Steve Blocka7e24c12009-10-30 11:49:00 +000015334 // Morph external string to be TwoByte string.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015335 string->set_map(CcTest::heap()->external_string_map());
Steve Blocka7e24c12009-10-30 11:49:00 +000015336 i::ExternalTwoByteString* morphed =
15337 i::ExternalTwoByteString::cast(string);
15338 morphed->set_resource(uc16_resource);
15339 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015340 // Check old map is not internalized or long.
15341 CHECK(string->map() == CcTest::heap()->external_string_map());
15342 // Morph external string to be one-byte string.
15343 string->set_map(CcTest::heap()->external_one_byte_string_map());
15344 i::ExternalOneByteString* morphed = i::ExternalOneByteString::cast(string);
15345 morphed->set_resource(one_byte_resource);
Steve Blocka7e24c12009-10-30 11:49:00 +000015346 }
15347}
15348
15349
15350// Test that we can still flatten a string if the components it is built up
15351// from have been turned into 16 bit strings in the mean time.
15352THREADED_TEST(MorphCompositeStringTest) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010015353 char utf_buffer[129];
Steve Blocka7e24c12009-10-30 11:49:00 +000015354 const char* c_string = "Now is the time for all good men"
15355 " to come to the aid of the party";
15356 uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
15357 {
Steve Blocka7e24c12009-10-30 11:49:00 +000015358 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015359 i::Factory* factory = CcTest::i_isolate()->factory();
15360 v8::HandleScope scope(env->GetIsolate());
15361 OneByteVectorResource one_byte_resource(
Steve Blockd0582a62009-12-15 09:54:21 +000015362 i::Vector<const char>(c_string, i::StrLength(c_string)));
Steve Blocka7e24c12009-10-30 11:49:00 +000015363 UC16VectorResource uc16_resource(
Steve Blockd0582a62009-12-15 09:54:21 +000015364 i::Vector<const uint16_t>(two_byte_string,
15365 i::StrLength(c_string)));
Steve Blocka7e24c12009-10-30 11:49:00 +000015366
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015367 Local<String> lhs(
15368 v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
15369 &one_byte_resource).ToHandleChecked()));
15370 Local<String> rhs(
15371 v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
15372 &one_byte_resource).ToHandleChecked()));
Steve Blocka7e24c12009-10-30 11:49:00 +000015373
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015374 CHECK(env->Global()->Set(env.local(), v8_str("lhs"), lhs).FromJust());
15375 CHECK(env->Global()->Set(env.local(), v8_str("rhs"), rhs).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015376
15377 CompileRun(
15378 "var cons = lhs + rhs;"
15379 "var slice = lhs.substring(1, lhs.length - 1);"
15380 "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
15381
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015382 CHECK(lhs->IsOneByte());
15383 CHECK(rhs->IsOneByte());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010015384
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015385 MorphAString(*v8::Utils::OpenHandle(*lhs), &one_byte_resource,
15386 &uc16_resource);
15387 MorphAString(*v8::Utils::OpenHandle(*rhs), &one_byte_resource,
15388 &uc16_resource);
Steve Blocka7e24c12009-10-30 11:49:00 +000015389
Ben Murdoch3ef787d2012-04-12 10:51:47 +010015390 // This should UTF-8 without flattening, since everything is ASCII.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015391 Local<String> cons =
15392 v8_compile("cons")->Run(env.local()).ToLocalChecked().As<String>();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010015393 CHECK_EQ(128, cons->Utf8Length());
15394 int nchars = -1;
15395 CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
15396 CHECK_EQ(128, nchars);
15397 CHECK_EQ(0, strcmp(
15398 utf_buffer,
15399 "Now is the time for all good men to come to the aid of the party"
15400 "Now is the time for all good men to come to the aid of the party"));
15401
Steve Blocka7e24c12009-10-30 11:49:00 +000015402 // Now do some stuff to make sure the strings are flattened, etc.
15403 CompileRun(
15404 "/[^a-z]/.test(cons);"
15405 "/[^a-z]/.test(slice);"
15406 "/[^a-z]/.test(slice_on_cons);");
15407 const char* expected_cons =
15408 "Now is the time for all good men to come to the aid of the party"
15409 "Now is the time for all good men to come to the aid of the party";
15410 const char* expected_slice =
15411 "ow is the time for all good men to come to the aid of the part";
15412 const char* expected_slice_on_cons =
15413 "ow is the time for all good men to come to the aid of the party"
15414 "Now is the time for all good men to come to the aid of the part";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015415 CHECK(v8_str(expected_cons)
15416 ->Equals(env.local(), env->Global()
15417 ->Get(env.local(), v8_str("cons"))
15418 .ToLocalChecked())
15419 .FromJust());
15420 CHECK(v8_str(expected_slice)
15421 ->Equals(env.local(), env->Global()
15422 ->Get(env.local(), v8_str("slice"))
15423 .ToLocalChecked())
15424 .FromJust());
15425 CHECK(v8_str(expected_slice_on_cons)
15426 ->Equals(env.local(),
15427 env->Global()
15428 ->Get(env.local(), v8_str("slice_on_cons"))
15429 .ToLocalChecked())
15430 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015431 }
Ben Murdoch3bec4d22010-07-22 14:51:16 +010015432 i::DeleteArray(two_byte_string);
Steve Blocka7e24c12009-10-30 11:49:00 +000015433}
15434
15435
15436TEST(CompileExternalTwoByteSource) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015437 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015438 v8::HandleScope scope(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000015439
15440 // This is a very short list of sources, which currently is to check for a
15441 // regression caused by r2703.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015442 const char* one_byte_sources[] = {
15443 "0.5",
15444 "-0.5", // This mainly testes PushBack in the Scanner.
15445 "--0.5", // This mainly testes PushBack in the Scanner.
15446 NULL};
Steve Blocka7e24c12009-10-30 11:49:00 +000015447
15448 // Compile the sources as external two byte strings.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015449 for (int i = 0; one_byte_sources[i] != NULL; i++) {
15450 uint16_t* two_byte_string = AsciiToTwoByteString(one_byte_sources[i]);
15451 TestResource* uc16_resource = new TestResource(two_byte_string);
15452 v8::Local<v8::String> source =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015453 v8::String::NewExternalTwoByte(context->GetIsolate(), uc16_resource)
15454 .ToLocalChecked();
15455 v8::Script::Compile(context.local(), source).FromMaybe(Local<Script>());
Steve Blocka7e24c12009-10-30 11:49:00 +000015456 }
15457}
15458
15459
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015460#ifndef V8_INTERPRETED_REGEXP
15461
15462struct RegExpInterruptionData {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015463 v8::base::Atomic32 loop_count;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015464 UC16VectorResource* string_resource;
15465 v8::Persistent<v8::String> string;
15466} regexp_interruption_data;
15467
15468
15469class RegExpInterruptionThread : public v8::base::Thread {
Steve Blocka7e24c12009-10-30 11:49:00 +000015470 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015471 explicit RegExpInterruptionThread(v8::Isolate* isolate)
15472 : Thread(Options("TimeoutThread")), isolate_(isolate) {}
Steve Blocka7e24c12009-10-30 11:49:00 +000015473
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015474 virtual void Run() {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015475 for (v8::base::NoBarrier_Store(&regexp_interruption_data.loop_count, 0);
15476 v8::base::NoBarrier_Load(&regexp_interruption_data.loop_count) < 7;
15477 v8::base::NoBarrier_AtomicIncrement(
15478 &regexp_interruption_data.loop_count, 1)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015479 // Wait a bit before requesting GC.
15480 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015481 reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
Steve Blocka7e24c12009-10-30 11:49:00 +000015482 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015483 // Wait a bit before terminating.
15484 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
15485 isolate_->TerminateExecution();
Steve Blocka7e24c12009-10-30 11:49:00 +000015486 }
Steve Blocka7e24c12009-10-30 11:49:00 +000015487
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000015488 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015489 v8::Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +000015490};
15491
15492
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015493void RunBeforeGC(v8::Isolate* isolate, v8::GCType type,
15494 v8::GCCallbackFlags flags) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015495 if (v8::base::NoBarrier_Load(&regexp_interruption_data.loop_count) != 2) {
15496 return;
15497 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015498 v8::HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015499 v8::Local<v8::String> string = v8::Local<v8::String>::New(
15500 CcTest::isolate(), regexp_interruption_data.string);
15501 string->MakeExternal(regexp_interruption_data.string_resource);
Steve Blocka7e24c12009-10-30 11:49:00 +000015502}
15503
15504
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015505// Test that RegExp execution can be interrupted. Specifically, we test
15506// * interrupting with GC
15507// * turn the subject string from one-byte internal to two-byte external string
15508// * force termination
15509TEST(RegExpInterruption) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015510 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015511 v8::HandleScope scope(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015512
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015513 RegExpInterruptionThread timeout_thread(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015514
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015515 env->GetIsolate()->AddGCPrologueCallback(RunBeforeGC);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015516 static const char* one_byte_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
15517 i::uc16* uc16_content = AsciiToTwoByteString(one_byte_content);
15518 v8::Local<v8::String> string = v8_str(one_byte_content);
15519
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015520 env->Global()->Set(env.local(), v8_str("a"), string).FromJust();
15521 regexp_interruption_data.string.Reset(env->GetIsolate(), string);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015522 regexp_interruption_data.string_resource = new UC16VectorResource(
15523 i::Vector<const i::uc16>(uc16_content, i::StrLength(one_byte_content)));
15524
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015525 v8::TryCatch try_catch(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015526 timeout_thread.Start();
15527
15528 CompileRun("/((a*)*)*b/.exec(a)");
15529 CHECK(try_catch.HasTerminated());
15530
15531 timeout_thread.Join();
15532
15533 regexp_interruption_data.string.Reset();
15534 i::DeleteArray(uc16_content);
15535}
15536
15537#endif // V8_INTERPRETED_REGEXP
15538
15539
15540// Test that we cannot set a property on the global object if there
Steve Blocka7e24c12009-10-30 11:49:00 +000015541// is a read-only property in the prototype chain.
15542TEST(ReadOnlyPropertyInGlobalProto) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015543 v8::Isolate* isolate = CcTest::isolate();
15544 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015545 v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000015546 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015547 v8::Local<v8::Object> global = context->Global();
15548 v8::Local<v8::Object> global_proto = v8::Local<v8::Object>::Cast(
15549 global->Get(context.local(), v8_str("__proto__")).ToLocalChecked());
15550 global_proto->DefineOwnProperty(context.local(), v8_str("x"),
15551 v8::Integer::New(isolate, 0), v8::ReadOnly)
15552 .FromJust();
15553 global_proto->DefineOwnProperty(context.local(), v8_str("y"),
15554 v8::Integer::New(isolate, 0), v8::ReadOnly)
15555 .FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +000015556 // Check without 'eval' or 'with'.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015557 v8::Local<v8::Value> res =
Steve Blocka7e24c12009-10-30 11:49:00 +000015558 CompileRun("function f() { x = 42; return x; }; f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015559 CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015560 // Check with 'eval'.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015561 res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015562 CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015563 // Check with 'with'.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015564 res = CompileRun("function f() { with (this) { y = 44 }; return y; }; 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}
15567
Steve Blocka7e24c12009-10-30 11:49:00 +000015568
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015569TEST(CreateDataProperty) {
15570 LocalContext env;
15571 v8::Isolate* isolate = env->GetIsolate();
15572 v8::HandleScope handle_scope(isolate);
15573
15574 CompileRun(
15575 "var a = {};"
15576 "var b = [];"
15577 "Object.defineProperty(a, 'foo', {value: 23});"
15578 "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
15579
15580 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
15581 env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
15582 v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(
15583 env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
15584 {
15585 // Can't change a non-configurable properties.
15586 v8::TryCatch try_catch(isolate);
15587 CHECK(!obj->CreateDataProperty(env.local(), v8_str("foo"),
15588 v8::Integer::New(isolate, 42)).FromJust());
15589 CHECK(!try_catch.HasCaught());
15590 CHECK(obj->CreateDataProperty(env.local(), v8_str("bar"),
15591 v8::Integer::New(isolate, 42)).FromJust());
15592 CHECK(!try_catch.HasCaught());
15593 v8::Local<v8::Value> val =
15594 obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
15595 CHECK(val->IsNumber());
15596 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015597 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015598
15599 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015600 // Set a regular property.
15601 v8::TryCatch try_catch(isolate);
15602 CHECK(obj->CreateDataProperty(env.local(), v8_str("blub"),
15603 v8::Integer::New(isolate, 42)).FromJust());
15604 CHECK(!try_catch.HasCaught());
15605 v8::Local<v8::Value> val =
15606 obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
15607 CHECK(val->IsNumber());
15608 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15609 }
15610
15611 {
15612 // Set an indexed property.
15613 v8::TryCatch try_catch(isolate);
15614 CHECK(obj->CreateDataProperty(env.local(), v8_str("1"),
15615 v8::Integer::New(isolate, 42)).FromJust());
15616 CHECK(!try_catch.HasCaught());
15617 v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
15618 CHECK(val->IsNumber());
15619 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15620 }
15621
15622 {
15623 // Special cases for arrays.
15624 v8::TryCatch try_catch(isolate);
15625 CHECK(!arr->CreateDataProperty(env.local(), v8_str("length"),
15626 v8::Integer::New(isolate, 1)).FromJust());
15627 CHECK(!try_catch.HasCaught());
15628 }
15629 {
15630 // Special cases for arrays: index exceeds the array's length
15631 v8::TryCatch try_catch(isolate);
15632 CHECK(arr->CreateDataProperty(env.local(), 1, v8::Integer::New(isolate, 23))
15633 .FromJust());
15634 CHECK(!try_catch.HasCaught());
15635 CHECK_EQ(2U, arr->Length());
15636 v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
15637 CHECK(val->IsNumber());
15638 CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
15639
15640 // Set an existing entry.
15641 CHECK(arr->CreateDataProperty(env.local(), 0, v8::Integer::New(isolate, 42))
15642 .FromJust());
15643 CHECK(!try_catch.HasCaught());
15644 val = arr->Get(env.local(), 0).ToLocalChecked();
15645 CHECK(val->IsNumber());
15646 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15647 }
15648
15649 CompileRun("Object.freeze(a);");
15650 {
15651 // Can't change non-extensible objects.
15652 v8::TryCatch try_catch(isolate);
15653 CHECK(!obj->CreateDataProperty(env.local(), v8_str("baz"),
15654 v8::Integer::New(isolate, 42)).FromJust());
15655 CHECK(!try_catch.HasCaught());
15656 }
15657
15658 v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
15659 templ->SetAccessCheckCallback(AccessAlwaysBlocked);
15660 v8::Local<v8::Object> access_checked =
15661 templ->NewInstance(env.local()).ToLocalChecked();
15662 {
15663 v8::TryCatch try_catch(isolate);
15664 CHECK(access_checked->CreateDataProperty(env.local(), v8_str("foo"),
15665 v8::Integer::New(isolate, 42))
15666 .IsNothing());
15667 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015668 }
15669}
15670
15671
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015672TEST(DefineOwnProperty) {
15673 LocalContext env;
15674 v8::Isolate* isolate = env->GetIsolate();
15675 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000015676
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015677 CompileRun(
15678 "var a = {};"
15679 "var b = [];"
15680 "Object.defineProperty(a, 'foo', {value: 23});"
15681 "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
Steve Blocka7e24c12009-10-30 11:49:00 +000015682
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015683 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
15684 env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
15685 v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(
15686 env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
15687 {
15688 // Can't change a non-configurable properties.
15689 v8::TryCatch try_catch(isolate);
15690 CHECK(!obj->DefineOwnProperty(env.local(), v8_str("foo"),
15691 v8::Integer::New(isolate, 42)).FromJust());
15692 CHECK(!try_catch.HasCaught());
15693 CHECK(obj->DefineOwnProperty(env.local(), v8_str("bar"),
15694 v8::Integer::New(isolate, 42)).FromJust());
15695 CHECK(!try_catch.HasCaught());
15696 v8::Local<v8::Value> val =
15697 obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
15698 CHECK(val->IsNumber());
15699 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15700 }
15701
15702 {
15703 // Set a regular property.
15704 v8::TryCatch try_catch(isolate);
15705 CHECK(obj->DefineOwnProperty(env.local(), v8_str("blub"),
15706 v8::Integer::New(isolate, 42)).FromJust());
15707 CHECK(!try_catch.HasCaught());
15708 v8::Local<v8::Value> val =
15709 obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
15710 CHECK(val->IsNumber());
15711 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15712 }
15713
15714 {
15715 // Set an indexed property.
15716 v8::TryCatch try_catch(isolate);
15717 CHECK(obj->DefineOwnProperty(env.local(), v8_str("1"),
15718 v8::Integer::New(isolate, 42)).FromJust());
15719 CHECK(!try_catch.HasCaught());
15720 v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
15721 CHECK(val->IsNumber());
15722 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15723 }
15724
15725 {
15726 // Special cases for arrays.
15727 v8::TryCatch try_catch(isolate);
15728 CHECK(!arr->DefineOwnProperty(env.local(), v8_str("length"),
15729 v8::Integer::New(isolate, 1)).FromJust());
15730 CHECK(!try_catch.HasCaught());
15731 }
15732 {
15733 // Special cases for arrays: index exceeds the array's length
15734 v8::TryCatch try_catch(isolate);
15735 CHECK(arr->DefineOwnProperty(env.local(), v8_str("1"),
15736 v8::Integer::New(isolate, 23)).FromJust());
15737 CHECK(!try_catch.HasCaught());
15738 CHECK_EQ(2U, arr->Length());
15739 v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
15740 CHECK(val->IsNumber());
15741 CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
15742
15743 // Set an existing entry.
15744 CHECK(arr->DefineOwnProperty(env.local(), v8_str("0"),
15745 v8::Integer::New(isolate, 42)).FromJust());
15746 CHECK(!try_catch.HasCaught());
15747 val = arr->Get(env.local(), 0).ToLocalChecked();
15748 CHECK(val->IsNumber());
15749 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15750 }
15751
15752 {
15753 // Set a non-writable property.
15754 v8::TryCatch try_catch(isolate);
15755 CHECK(obj->DefineOwnProperty(env.local(), v8_str("lala"),
15756 v8::Integer::New(isolate, 42),
15757 v8::ReadOnly).FromJust());
15758 CHECK(!try_catch.HasCaught());
15759 v8::Local<v8::Value> val =
15760 obj->Get(env.local(), v8_str("lala")).ToLocalChecked();
15761 CHECK(val->IsNumber());
15762 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15763 CHECK_EQ(v8::ReadOnly, obj->GetPropertyAttributes(
15764 env.local(), v8_str("lala")).FromJust());
15765 CHECK(!try_catch.HasCaught());
15766 }
15767
15768 CompileRun("Object.freeze(a);");
15769 {
15770 // Can't change non-extensible objects.
15771 v8::TryCatch try_catch(isolate);
15772 CHECK(!obj->DefineOwnProperty(env.local(), v8_str("baz"),
15773 v8::Integer::New(isolate, 42)).FromJust());
15774 CHECK(!try_catch.HasCaught());
15775 }
15776
15777 v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
15778 templ->SetAccessCheckCallback(AccessAlwaysBlocked);
15779 v8::Local<v8::Object> access_checked =
15780 templ->NewInstance(env.local()).ToLocalChecked();
15781 {
15782 v8::TryCatch try_catch(isolate);
15783 CHECK(access_checked->DefineOwnProperty(env.local(), v8_str("foo"),
15784 v8::Integer::New(isolate, 42))
15785 .IsNothing());
15786 CHECK(try_catch.HasCaught());
15787 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015788}
15789
15790
15791THREADED_TEST(GetCurrentContextWhenNotInContext) {
15792 i::Isolate* isolate = CcTest::i_isolate();
15793 CHECK(isolate != NULL);
15794 CHECK(isolate->context() == NULL);
15795 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
15796 v8::HandleScope scope(v8_isolate);
15797 // The following should not crash, but return an empty handle.
15798 v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
15799 CHECK(current.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000015800}
15801
15802
Steve Blocka7e24c12009-10-30 11:49:00 +000015803// Check that a variable declaration with no explicit initialization
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015804// value does shadow an existing property in the prototype chain.
Steve Blocka7e24c12009-10-30 11:49:00 +000015805THREADED_TEST(InitGlobalVarInProtoChain) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015806 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015807 v8::HandleScope scope(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000015808 // Introduce a variable in the prototype chain.
15809 CompileRun("__proto__.x = 42");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015810 v8::Local<v8::Value> result = CompileRun("var x = 43; x");
Steve Blocka7e24c12009-10-30 11:49:00 +000015811 CHECK(!result->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015812 CHECK_EQ(43, result->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015813}
15814
15815
15816// Regression test for issue 398.
15817// If a function is added to an object, creating a constant function
15818// field, and the result is cloned, replacing the constant function on the
15819// original should not affect the clone.
15820// See http://code.google.com/p/v8/issues/detail?id=398
15821THREADED_TEST(ReplaceConstantFunction) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015822 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015823 v8::Isolate* isolate = context->GetIsolate();
15824 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015825 v8::Local<v8::Object> obj = v8::Object::New(isolate);
15826 v8::Local<v8::FunctionTemplate> func_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015827 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015828 v8::Local<v8::String> foo_string = v8_str("foo");
15829 obj->Set(context.local(), foo_string,
15830 func_templ->GetFunction(context.local()).ToLocalChecked())
15831 .FromJust();
15832 v8::Local<v8::Object> obj_clone = obj->Clone();
15833 obj_clone->Set(context.local(), foo_string, v8_str("Hello")).FromJust();
15834 CHECK(!obj->Get(context.local(), foo_string).ToLocalChecked()->IsUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +000015835}
15836
15837
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015838static void CheckElementValue(i::Isolate* isolate,
15839 int expected,
15840 i::Handle<i::Object> obj,
15841 int offset) {
15842 i::Object* element =
15843 *i::Object::GetElement(isolate, obj, offset).ToHandleChecked();
15844 CHECK_EQ(expected, i::Smi::cast(element)->value());
Steve Blocka7e24c12009-10-30 11:49:00 +000015845}
15846
15847
Steve Block3ce2e202009-11-05 08:53:23 +000015848template <class ExternalArrayClass, class ElementType>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015849static void ObjectWithExternalArrayTestHelper(Local<Context> context,
15850 v8::Local<Object> obj,
15851 int element_count,
15852 i::ExternalArrayType array_type,
15853 int64_t low, int64_t high) {
15854 i::Handle<i::JSReceiver> jsobj = v8::Utils::OpenHandle(*obj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015855 i::Isolate* isolate = jsobj->GetIsolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015856 obj->Set(context, v8_str("field"),
15857 v8::Int32::New(reinterpret_cast<v8::Isolate*>(isolate), 1503))
15858 .FromJust();
15859 CHECK(context->Global()->Set(context, v8_str("ext_array"), obj).FromJust());
15860 v8::Local<v8::Value> result = CompileRun("ext_array.field");
15861 CHECK_EQ(1503, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015862 result = CompileRun("ext_array[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015863 CHECK_EQ(1, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015864
Steve Block3ce2e202009-11-05 08:53:23 +000015865 // Check assigned smis
15866 result = CompileRun("for (var i = 0; i < 8; i++) {"
15867 " ext_array[i] = i;"
15868 "}"
15869 "var sum = 0;"
15870 "for (var i = 0; i < 8; i++) {"
15871 " sum += ext_array[i];"
15872 "}"
15873 "sum;");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015874
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015875 CHECK_EQ(28, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015876 // Check pass through of assigned smis
15877 result = CompileRun("var sum = 0;"
15878 "for (var i = 0; i < 8; i++) {"
15879 " sum += ext_array[i] = ext_array[i] = -i;"
15880 "}"
15881 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015882 CHECK_EQ(-28, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015883
Steve Block3ce2e202009-11-05 08:53:23 +000015884
15885 // Check assigned smis in reverse order
15886 result = CompileRun("for (var i = 8; --i >= 0; ) {"
15887 " ext_array[i] = i;"
15888 "}"
15889 "var sum = 0;"
15890 "for (var i = 0; i < 8; i++) {"
15891 " sum += ext_array[i];"
15892 "}"
15893 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015894 CHECK_EQ(28, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015895
15896 // Check pass through of assigned HeapNumbers
15897 result = CompileRun("var sum = 0;"
15898 "for (var i = 0; i < 16; i+=2) {"
15899 " sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
15900 "}"
15901 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015902 CHECK_EQ(-28, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015903
15904 // Check assigned HeapNumbers
15905 result = CompileRun("for (var i = 0; i < 16; i+=2) {"
15906 " ext_array[i] = (i * 0.5);"
15907 "}"
15908 "var sum = 0;"
15909 "for (var i = 0; i < 16; i+=2) {"
15910 " sum += ext_array[i];"
15911 "}"
15912 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015913 CHECK_EQ(28, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015914
15915 // Check assigned HeapNumbers in reverse order
15916 result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
15917 " ext_array[i] = (i * 0.5);"
15918 "}"
15919 "var sum = 0;"
15920 "for (var i = 0; i < 16; i+=2) {"
15921 " sum += ext_array[i];"
15922 "}"
15923 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015924 CHECK_EQ(28, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015925
15926 i::ScopedVector<char> test_buf(1024);
15927
15928 // Check legal boundary conditions.
15929 // The repeated loads and stores ensure the ICs are exercised.
15930 const char* boundary_program =
15931 "var res = 0;"
15932 "for (var i = 0; i < 16; i++) {"
15933 " ext_array[i] = %lld;"
15934 " if (i > 8) {"
15935 " res = ext_array[i];"
15936 " }"
15937 "}"
15938 "res;";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015939 i::SNPrintF(test_buf,
15940 boundary_program,
15941 low);
Steve Block3ce2e202009-11-05 08:53:23 +000015942 result = CompileRun(test_buf.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015943 CHECK_EQ(low, result->IntegerValue(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015944
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015945 i::SNPrintF(test_buf,
15946 boundary_program,
15947 high);
Steve Block3ce2e202009-11-05 08:53:23 +000015948 result = CompileRun(test_buf.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015949 CHECK_EQ(high, result->IntegerValue(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015950
15951 // Check misprediction of type in IC.
15952 result = CompileRun("var tmp_array = ext_array;"
15953 "var sum = 0;"
15954 "for (var i = 0; i < 8; i++) {"
15955 " tmp_array[i] = i;"
15956 " sum += tmp_array[i];"
15957 " if (i == 4) {"
15958 " tmp_array = {};"
15959 " }"
15960 "}"
15961 "sum;");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010015962 // Force GC to trigger verification.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015963 CcTest::heap()->CollectAllGarbage();
15964 CHECK_EQ(28, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015965
15966 // Make sure out-of-range loads do not throw.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015967 i::SNPrintF(test_buf,
15968 "var caught_exception = false;"
15969 "try {"
15970 " ext_array[%d];"
15971 "} catch (e) {"
15972 " caught_exception = true;"
15973 "}"
15974 "caught_exception;",
15975 element_count);
Steve Block3ce2e202009-11-05 08:53:23 +000015976 result = CompileRun(test_buf.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015977 CHECK_EQ(false, result->BooleanValue(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015978
15979 // Make sure out-of-range stores do not throw.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015980 i::SNPrintF(test_buf,
15981 "var caught_exception = false;"
15982 "try {"
15983 " ext_array[%d] = 1;"
15984 "} catch (e) {"
15985 " caught_exception = true;"
15986 "}"
15987 "caught_exception;",
15988 element_count);
Steve Block3ce2e202009-11-05 08:53:23 +000015989 result = CompileRun(test_buf.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015990 CHECK_EQ(false, result->BooleanValue(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015991
15992 // Check other boundary conditions, values and operations.
15993 result = CompileRun("for (var i = 0; i < 8; i++) {"
15994 " ext_array[7] = undefined;"
15995 "}"
15996 "ext_array[7];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015997 CHECK_EQ(0, result->Int32Value(context).FromJust());
15998 if (array_type == i::kExternalFloat64Array ||
15999 array_type == i::kExternalFloat32Array) {
16000 CHECK(std::isnan(
16001 i::Object::GetElement(isolate, jsobj, 7).ToHandleChecked()->Number()));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016002 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016003 CheckElementValue(isolate, 0, jsobj, 7);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016004 }
Steve Block3ce2e202009-11-05 08:53:23 +000016005
16006 result = CompileRun("for (var i = 0; i < 8; i++) {"
16007 " ext_array[6] = '2.3';"
16008 "}"
16009 "ext_array[6];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016010 CHECK_EQ(2, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016011 CHECK_EQ(2,
16012 static_cast<int>(
16013 i::Object::GetElement(
16014 isolate, jsobj, 6).ToHandleChecked()->Number()));
Steve Block3ce2e202009-11-05 08:53:23 +000016015
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016016 if (array_type != i::kExternalFloat32Array &&
16017 array_type != i::kExternalFloat64Array) {
Steve Block3ce2e202009-11-05 08:53:23 +000016018 // Though the specification doesn't state it, be explicit about
16019 // converting NaNs and +/-Infinity to zero.
16020 result = CompileRun("for (var i = 0; i < 8; i++) {"
16021 " ext_array[i] = 5;"
16022 "}"
16023 "for (var i = 0; i < 8; i++) {"
16024 " ext_array[i] = NaN;"
16025 "}"
16026 "ext_array[5];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016027 CHECK_EQ(0, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016028 CheckElementValue(isolate, 0, jsobj, 5);
Steve Block3ce2e202009-11-05 08:53:23 +000016029
16030 result = CompileRun("for (var i = 0; i < 8; i++) {"
16031 " ext_array[i] = 5;"
16032 "}"
16033 "for (var i = 0; i < 8; i++) {"
16034 " ext_array[i] = Infinity;"
16035 "}"
16036 "ext_array[5];");
Steve Block44f0eee2011-05-26 01:26:41 +010016037 int expected_value =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016038 (array_type == i::kExternalUint8ClampedArray) ? 255 : 0;
16039 CHECK_EQ(expected_value, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016040 CheckElementValue(isolate, expected_value, jsobj, 5);
Steve Block3ce2e202009-11-05 08:53:23 +000016041
16042 result = CompileRun("for (var i = 0; i < 8; i++) {"
16043 " ext_array[i] = 5;"
16044 "}"
16045 "for (var i = 0; i < 8; i++) {"
16046 " ext_array[i] = -Infinity;"
16047 "}"
16048 "ext_array[5];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016049 CHECK_EQ(0, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016050 CheckElementValue(isolate, 0, jsobj, 5);
Steve Block1e0659c2011-05-24 12:43:12 +010016051
16052 // Check truncation behavior of integral arrays.
16053 const char* unsigned_data =
16054 "var source_data = [0.6, 10.6];"
16055 "var expected_results = [0, 10];";
16056 const char* signed_data =
16057 "var source_data = [0.6, 10.6, -0.6, -10.6];"
16058 "var expected_results = [0, 10, 0, -10];";
Steve Block44f0eee2011-05-26 01:26:41 +010016059 const char* pixel_data =
16060 "var source_data = [0.6, 10.6];"
16061 "var expected_results = [1, 11];";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016062 bool is_unsigned = (array_type == i::kExternalUint8Array ||
16063 array_type == i::kExternalUint16Array ||
16064 array_type == i::kExternalUint32Array);
16065 bool is_pixel_data = array_type == i::kExternalUint8ClampedArray;
Steve Block1e0659c2011-05-24 12:43:12 +010016066
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016067 i::SNPrintF(test_buf,
16068 "%s"
16069 "var all_passed = true;"
16070 "for (var i = 0; i < source_data.length; i++) {"
16071 " for (var j = 0; j < 8; j++) {"
16072 " ext_array[j] = source_data[i];"
16073 " }"
16074 " all_passed = all_passed &&"
16075 " (ext_array[5] == expected_results[i]);"
16076 "}"
16077 "all_passed;",
16078 (is_unsigned ?
16079 unsigned_data :
16080 (is_pixel_data ? pixel_data : signed_data)));
Steve Block1e0659c2011-05-24 12:43:12 +010016081 result = CompileRun(test_buf.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016082 CHECK_EQ(true, result->BooleanValue(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016083 }
16084
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016085 i::Handle<ExternalArrayClass> array(ExternalArrayClass::cast(
16086 i::Handle<i::JSObject>::cast(jsobj)->elements()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016087 for (int i = 0; i < element_count; i++) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010016088 array->set(i, static_cast<ElementType>(i));
16089 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016090
Ben Murdoch8b112d22011-06-08 16:22:53 +010016091 // Test complex assignments
16092 result = CompileRun("function ee_op_test_complex_func(sum) {"
16093 " for (var i = 0; i < 40; ++i) {"
16094 " sum += (ext_array[i] += 1);"
16095 " sum += (ext_array[i] -= 1);"
16096 " } "
16097 " return sum;"
16098 "}"
16099 "sum=0;"
16100 "for (var i=0;i<10000;++i) {"
16101 " sum=ee_op_test_complex_func(sum);"
16102 "}"
16103 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016104 CHECK_EQ(16000000, result->Int32Value(context).FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010016105
16106 // Test count operations
16107 result = CompileRun("function ee_op_test_count_func(sum) {"
16108 " for (var i = 0; i < 40; ++i) {"
16109 " sum += (++ext_array[i]);"
16110 " sum += (--ext_array[i]);"
16111 " } "
16112 " return sum;"
16113 "}"
16114 "sum=0;"
16115 "for (var i=0;i<10000;++i) {"
16116 " sum=ee_op_test_count_func(sum);"
16117 "}"
16118 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016119 CHECK_EQ(16000000, result->Int32Value(context).FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010016120
Steve Block3ce2e202009-11-05 08:53:23 +000016121 result = CompileRun("ext_array[3] = 33;"
16122 "delete ext_array[3];"
16123 "ext_array[3];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016124 CHECK_EQ(33, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016125
16126 result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
16127 "ext_array[2] = 12; ext_array[3] = 13;"
16128 "ext_array.__defineGetter__('2',"
16129 "function() { return 120; });"
16130 "ext_array[2];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016131 CHECK_EQ(12, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016132
16133 result = CompileRun("var js_array = new Array(40);"
16134 "js_array[0] = 77;"
16135 "js_array;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016136 CHECK_EQ(77, v8::Object::Cast(*result)
16137 ->Get(context, v8_str("0"))
16138 .ToLocalChecked()
16139 ->Int32Value(context)
16140 .FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016141
16142 result = CompileRun("ext_array[1] = 23;"
16143 "ext_array.__proto__ = [];"
16144 "js_array.__proto__ = ext_array;"
16145 "js_array.concat(ext_array);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016146 CHECK_EQ(77, v8::Object::Cast(*result)
16147 ->Get(context, v8_str("0"))
16148 .ToLocalChecked()
16149 ->Int32Value(context)
16150 .FromJust());
16151 CHECK_EQ(23, v8::Object::Cast(*result)
16152 ->Get(context, v8_str("1"))
16153 .ToLocalChecked()
16154 ->Int32Value(context)
16155 .FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016156
16157 result = CompileRun("ext_array[1] = 23;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016158 CHECK_EQ(23, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016159}
16160
16161
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016162template <class FixedTypedArrayClass, i::ElementsKind elements_kind,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016163 class ElementType>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016164static void FixedTypedArrayTestHelper(i::ExternalArrayType array_type,
16165 ElementType low, ElementType high) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016166 i::FLAG_allow_natives_syntax = true;
16167 LocalContext context;
16168 i::Isolate* isolate = CcTest::i_isolate();
16169 i::Factory* factory = isolate->factory();
16170 v8::HandleScope scope(context->GetIsolate());
16171 const int kElementCount = 260;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016172 i::Handle<i::JSTypedArray> jsobj =
16173 factory->NewJSTypedArray(elements_kind, kElementCount);
16174 i::Handle<FixedTypedArrayClass> fixed_array(
16175 FixedTypedArrayClass::cast(jsobj->elements()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016176 CHECK_EQ(FixedTypedArrayClass::kInstanceType,
16177 fixed_array->map()->instance_type());
16178 CHECK_EQ(kElementCount, fixed_array->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016179 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016180 for (int i = 0; i < kElementCount; i++) {
16181 fixed_array->set(i, static_cast<ElementType>(i));
16182 }
16183 // Force GC to trigger verification.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016184 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016185 for (int i = 0; i < kElementCount; i++) {
16186 CHECK_EQ(static_cast<int64_t>(static_cast<ElementType>(i)),
16187 static_cast<int64_t>(fixed_array->get_scalar(i)));
16188 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016189 v8::Local<v8::Object> obj = v8::Utils::ToLocal(jsobj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016190
16191 ObjectWithExternalArrayTestHelper<FixedTypedArrayClass, ElementType>(
16192 context.local(), obj, kElementCount, array_type,
16193 static_cast<int64_t>(low),
16194 static_cast<int64_t>(high));
16195}
16196
16197
16198THREADED_TEST(FixedUint8Array) {
16199 FixedTypedArrayTestHelper<i::FixedUint8Array, i::UINT8_ELEMENTS, uint8_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016200 i::kExternalUint8Array, 0x0, 0xFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016201}
16202
16203
16204THREADED_TEST(FixedUint8ClampedArray) {
16205 FixedTypedArrayTestHelper<i::FixedUint8ClampedArray,
16206 i::UINT8_CLAMPED_ELEMENTS, uint8_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016207 i::kExternalUint8ClampedArray, 0x0, 0xFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016208}
16209
16210
16211THREADED_TEST(FixedInt8Array) {
16212 FixedTypedArrayTestHelper<i::FixedInt8Array, i::INT8_ELEMENTS, int8_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016213 i::kExternalInt8Array, -0x80, 0x7F);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016214}
16215
16216
16217THREADED_TEST(FixedUint16Array) {
16218 FixedTypedArrayTestHelper<i::FixedUint16Array, i::UINT16_ELEMENTS, uint16_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016219 i::kExternalUint16Array, 0x0, 0xFFFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016220}
16221
16222
16223THREADED_TEST(FixedInt16Array) {
16224 FixedTypedArrayTestHelper<i::FixedInt16Array, i::INT16_ELEMENTS, int16_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016225 i::kExternalInt16Array, -0x8000, 0x7FFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016226}
16227
16228
16229THREADED_TEST(FixedUint32Array) {
16230 FixedTypedArrayTestHelper<i::FixedUint32Array, i::UINT32_ELEMENTS, uint32_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016231 i::kExternalUint32Array, 0x0, UINT_MAX);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016232}
16233
16234
16235THREADED_TEST(FixedInt32Array) {
16236 FixedTypedArrayTestHelper<i::FixedInt32Array, i::INT32_ELEMENTS, int32_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016237 i::kExternalInt32Array, INT_MIN, INT_MAX);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016238}
16239
16240
16241THREADED_TEST(FixedFloat32Array) {
16242 FixedTypedArrayTestHelper<i::FixedFloat32Array, i::FLOAT32_ELEMENTS, float>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016243 i::kExternalFloat32Array, -500, 500);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016244}
16245
16246
16247THREADED_TEST(FixedFloat64Array) {
16248 FixedTypedArrayTestHelper<i::FixedFloat64Array, i::FLOAT64_ELEMENTS, float>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016249 i::kExternalFloat64Array, -500, 500);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016250}
16251
16252
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016253template <typename ElementType, typename TypedArray, class ExternalArrayClass,
16254 class ArrayBufferType>
16255void TypedArrayTestHelper(i::ExternalArrayType array_type, int64_t low,
16256 int64_t high) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016257 const int kElementCount = 50;
16258
16259 i::ScopedVector<ElementType> backing_store(kElementCount+2);
16260
16261 LocalContext env;
16262 v8::Isolate* isolate = env->GetIsolate();
16263 v8::HandleScope handle_scope(isolate);
16264
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016265 Local<ArrayBufferType> ab =
16266 ArrayBufferType::New(isolate, backing_store.start(),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016267 (kElementCount + 2) * sizeof(ElementType));
16268 Local<TypedArray> ta =
16269 TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
16270 CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
16271 CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016272 CHECK_EQ(2 * sizeof(ElementType), ta->ByteOffset());
16273 CHECK_EQ(kElementCount * sizeof(ElementType), ta->ByteLength());
16274 CHECK(ab->Equals(env.local(), ta->Buffer()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016275
16276 ElementType* data = backing_store.start() + 2;
16277 for (int i = 0; i < kElementCount; i++) {
16278 data[i] = static_cast<ElementType>(i);
16279 }
16280
16281 ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
16282 env.local(), ta, kElementCount, array_type, low, high);
16283}
16284
16285
16286THREADED_TEST(Uint8Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016287 TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
16288 v8::ArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016289}
16290
16291
16292THREADED_TEST(Int8Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016293 TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
16294 v8::ArrayBuffer>(i::kExternalInt8Array, -0x80, 0x7F);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016295}
16296
16297
16298THREADED_TEST(Uint16Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016299 TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
16300 v8::ArrayBuffer>(i::kExternalUint16Array, 0, 0xFFFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016301}
16302
16303
16304THREADED_TEST(Int16Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016305 TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
16306 v8::ArrayBuffer>(i::kExternalInt16Array, -0x8000,
16307 0x7FFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016308}
16309
16310
16311THREADED_TEST(Uint32Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016312 TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
16313 v8::ArrayBuffer>(i::kExternalUint32Array, 0, UINT_MAX);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016314}
16315
16316
16317THREADED_TEST(Int32Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016318 TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
16319 v8::ArrayBuffer>(i::kExternalInt32Array, INT_MIN,
16320 INT_MAX);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016321}
16322
16323
16324THREADED_TEST(Float32Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016325 TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
16326 v8::ArrayBuffer>(i::kExternalFloat32Array, -500, 500);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016327}
16328
16329
16330THREADED_TEST(Float64Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016331 TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
16332 v8::ArrayBuffer>(i::kExternalFloat64Array, -500, 500);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016333}
16334
16335
16336THREADED_TEST(Uint8ClampedArray) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016337 TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
16338 i::FixedUint8ClampedArray, v8::ArrayBuffer>(
16339 i::kExternalUint8ClampedArray, 0, 0xFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016340}
16341
16342
16343THREADED_TEST(DataView) {
16344 const int kSize = 50;
16345
16346 i::ScopedVector<uint8_t> backing_store(kSize+2);
16347
16348 LocalContext env;
16349 v8::Isolate* isolate = env->GetIsolate();
16350 v8::HandleScope handle_scope(isolate);
16351
16352 Local<v8::ArrayBuffer> ab =
16353 v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016354 Local<v8::DataView> dv = v8::DataView::New(ab, 2, kSize);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016355 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016356 CHECK_EQ(2u, dv->ByteOffset());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016357 CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016358 CHECK(ab->Equals(env.local(), dv->Buffer()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016359}
16360
16361
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016362THREADED_TEST(SkipArrayBufferBackingStoreDuringGC) {
16363 LocalContext env;
16364 v8::Isolate* isolate = env->GetIsolate();
16365 v8::HandleScope handle_scope(isolate);
16366
16367 // Make sure the pointer looks like a heap object
16368 uint8_t* store_ptr = reinterpret_cast<uint8_t*>(i::kHeapObjectTag);
16369
16370 // Create ArrayBuffer with pointer-that-cannot-be-visited in the backing store
16371 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, store_ptr, 8);
16372
16373 // Should not crash
16374 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
16375 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
16376 CcTest::heap()->CollectAllGarbage();
16377 CcTest::heap()->CollectAllGarbage();
16378
16379 // Should not move the pointer
16380 CHECK_EQ(ab->GetContents().Data(), store_ptr);
16381}
16382
16383
16384THREADED_TEST(SkipArrayBufferDuringScavenge) {
16385 LocalContext env;
16386 v8::Isolate* isolate = env->GetIsolate();
16387 v8::HandleScope handle_scope(isolate);
16388
16389 // Make sure the pointer looks like a heap object
16390 Local<v8::Object> tmp = v8::Object::New(isolate);
16391 uint8_t* store_ptr =
16392 reinterpret_cast<uint8_t*>(*reinterpret_cast<uintptr_t*>(*tmp));
16393
16394 // Make `store_ptr` point to from space
16395 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
16396
16397 // Create ArrayBuffer with pointer-that-cannot-be-visited in the backing store
16398 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, store_ptr, 8);
16399
16400 // Should not crash,
16401 // i.e. backing store pointer should not be treated as a heap object pointer
16402 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
16403 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
16404
16405 // Use `ab` to silence compiler warning
16406 CHECK_EQ(ab->GetContents().Data(), store_ptr);
16407}
16408
16409
16410THREADED_TEST(SharedUint8Array) {
16411 i::FLAG_harmony_sharedarraybuffer = true;
16412 TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
16413 v8::SharedArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
16414}
16415
16416
16417THREADED_TEST(SharedInt8Array) {
16418 i::FLAG_harmony_sharedarraybuffer = true;
16419 TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
16420 v8::SharedArrayBuffer>(i::kExternalInt8Array, -0x80,
16421 0x7F);
16422}
16423
16424
16425THREADED_TEST(SharedUint16Array) {
16426 i::FLAG_harmony_sharedarraybuffer = true;
16427 TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
16428 v8::SharedArrayBuffer>(i::kExternalUint16Array, 0,
16429 0xFFFF);
16430}
16431
16432
16433THREADED_TEST(SharedInt16Array) {
16434 i::FLAG_harmony_sharedarraybuffer = true;
16435 TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
16436 v8::SharedArrayBuffer>(i::kExternalInt16Array, -0x8000,
16437 0x7FFF);
16438}
16439
16440
16441THREADED_TEST(SharedUint32Array) {
16442 i::FLAG_harmony_sharedarraybuffer = true;
16443 TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
16444 v8::SharedArrayBuffer>(i::kExternalUint32Array, 0,
16445 UINT_MAX);
16446}
16447
16448
16449THREADED_TEST(SharedInt32Array) {
16450 i::FLAG_harmony_sharedarraybuffer = true;
16451 TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
16452 v8::SharedArrayBuffer>(i::kExternalInt32Array, INT_MIN,
16453 INT_MAX);
16454}
16455
16456
16457THREADED_TEST(SharedFloat32Array) {
16458 i::FLAG_harmony_sharedarraybuffer = true;
16459 TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
16460 v8::SharedArrayBuffer>(i::kExternalFloat32Array, -500,
16461 500);
16462}
16463
16464
16465THREADED_TEST(SharedFloat64Array) {
16466 i::FLAG_harmony_sharedarraybuffer = true;
16467 TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
16468 v8::SharedArrayBuffer>(i::kExternalFloat64Array, -500,
16469 500);
16470}
16471
16472
16473THREADED_TEST(SharedUint8ClampedArray) {
16474 i::FLAG_harmony_sharedarraybuffer = true;
16475 TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
16476 i::FixedUint8ClampedArray, v8::SharedArrayBuffer>(
16477 i::kExternalUint8ClampedArray, 0, 0xFF);
16478}
16479
16480
16481THREADED_TEST(SharedDataView) {
16482 i::FLAG_harmony_sharedarraybuffer = true;
16483 const int kSize = 50;
16484
16485 i::ScopedVector<uint8_t> backing_store(kSize + 2);
16486
16487 LocalContext env;
16488 v8::Isolate* isolate = env->GetIsolate();
16489 v8::HandleScope handle_scope(isolate);
16490
16491 Local<v8::SharedArrayBuffer> ab =
16492 v8::SharedArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
16493 Local<v8::DataView> dv =
16494 v8::DataView::New(ab, 2, kSize);
16495 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
16496 CHECK_EQ(2u, dv->ByteOffset());
16497 CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
16498 CHECK(ab->Equals(env.local(), dv->Buffer()).FromJust());
16499}
16500
16501
16502#define IS_ARRAY_BUFFER_VIEW_TEST(View) \
16503 THREADED_TEST(Is##View) { \
16504 LocalContext env; \
16505 v8::Isolate* isolate = env->GetIsolate(); \
16506 v8::HandleScope handle_scope(isolate); \
16507 \
16508 Local<Value> result = CompileRun( \
16509 "var ab = new ArrayBuffer(128);" \
16510 "new " #View "(ab)"); \
16511 CHECK(result->IsArrayBufferView()); \
16512 CHECK(result->Is##View()); \
16513 CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>()); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016514 }
16515
16516IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
16517IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
16518IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
16519IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
16520IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
16521IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
16522IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
16523IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
16524IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
16525IS_ARRAY_BUFFER_VIEW_TEST(DataView)
16526
16527#undef IS_ARRAY_BUFFER_VIEW_TEST
16528
16529
16530
Steve Blocka7e24c12009-10-30 11:49:00 +000016531THREADED_TEST(ScriptContextDependence) {
Steve Blocka7e24c12009-10-30 11:49:00 +000016532 LocalContext c1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016533 v8::HandleScope scope(c1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000016534 const char *source = "foo";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016535 v8::Local<v8::Script> dep = v8_compile(source);
16536 v8::ScriptCompiler::Source script_source(
16537 v8::String::NewFromUtf8(c1->GetIsolate(), source,
16538 v8::NewStringType::kNormal)
16539 .ToLocalChecked());
16540 v8::Local<v8::UnboundScript> indep =
16541 v8::ScriptCompiler::CompileUnboundScript(c1->GetIsolate(), &script_source)
16542 .ToLocalChecked();
16543 c1->Global()
16544 ->Set(c1.local(), v8::String::NewFromUtf8(c1->GetIsolate(), "foo",
16545 v8::NewStringType::kNormal)
16546 .ToLocalChecked(),
16547 v8::Integer::New(c1->GetIsolate(), 100))
16548 .FromJust();
16549 CHECK_EQ(
16550 dep->Run(c1.local()).ToLocalChecked()->Int32Value(c1.local()).FromJust(),
16551 100);
16552 CHECK_EQ(indep->BindToCurrentContext()
16553 ->Run(c1.local())
16554 .ToLocalChecked()
16555 ->Int32Value(c1.local())
16556 .FromJust(),
16557 100);
Steve Blocka7e24c12009-10-30 11:49:00 +000016558 LocalContext c2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016559 c2->Global()
16560 ->Set(c2.local(), v8::String::NewFromUtf8(c2->GetIsolate(), "foo",
16561 v8::NewStringType::kNormal)
16562 .ToLocalChecked(),
16563 v8::Integer::New(c2->GetIsolate(), 101))
16564 .FromJust();
16565 CHECK_EQ(
16566 dep->Run(c2.local()).ToLocalChecked()->Int32Value(c2.local()).FromJust(),
16567 100);
16568 CHECK_EQ(indep->BindToCurrentContext()
16569 ->Run(c2.local())
16570 .ToLocalChecked()
16571 ->Int32Value(c2.local())
16572 .FromJust(),
16573 101);
Steve Blocka7e24c12009-10-30 11:49:00 +000016574}
16575
16576
16577THREADED_TEST(StackTrace) {
Steve Blocka7e24c12009-10-30 11:49:00 +000016578 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016579 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016580 v8::TryCatch try_catch(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000016581 const char *source = "function foo() { FAIL.FAIL; }; foo();";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016582 v8::Local<v8::String> src = v8_str(source);
16583 v8::Local<v8::String> origin = v8_str("stack-trace-test");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016584 v8::ScriptCompiler::Source script_source(src, v8::ScriptOrigin(origin));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016585 CHECK(v8::ScriptCompiler::CompileUnboundScript(context->GetIsolate(),
16586 &script_source)
16587 .ToLocalChecked()
16588 ->BindToCurrentContext()
16589 ->Run(context.local())
16590 .IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000016591 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016592 v8::String::Utf8Value stack(
16593 try_catch.StackTrace(context.local()).ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +000016594 CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
16595}
16596
16597
Kristian Monsen25f61362010-05-21 11:50:48 +010016598// Checks that a StackFrame has certain expected values.
16599void checkStackFrame(const char* expected_script_name,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016600 const char* expected_func_name, int expected_line_number,
16601 int expected_column, bool is_eval, bool is_constructor,
16602 v8::Local<v8::StackFrame> frame) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016603 v8::HandleScope scope(CcTest::isolate());
Kristian Monsen25f61362010-05-21 11:50:48 +010016604 v8::String::Utf8Value func_name(frame->GetFunctionName());
16605 v8::String::Utf8Value script_name(frame->GetScriptName());
16606 if (*script_name == NULL) {
16607 // The situation where there is no associated script, like for evals.
16608 CHECK(expected_script_name == NULL);
16609 } else {
16610 CHECK(strstr(*script_name, expected_script_name) != NULL);
16611 }
16612 CHECK(strstr(*func_name, expected_func_name) != NULL);
16613 CHECK_EQ(expected_line_number, frame->GetLineNumber());
16614 CHECK_EQ(expected_column, frame->GetColumn());
16615 CHECK_EQ(is_eval, frame->IsEval());
16616 CHECK_EQ(is_constructor, frame->IsConstructor());
16617}
16618
16619
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016620void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
16621 v8::HandleScope scope(args.GetIsolate());
Kristian Monsen25f61362010-05-21 11:50:48 +010016622 const char* origin = "capture-stack-trace-test";
16623 const int kOverviewTest = 1;
16624 const int kDetailedTest = 2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016625 const int kFunctionName = 3;
16626 const int kDisplayName = 4;
16627 const int kFunctionNameAndDisplayName = 5;
16628 const int kDisplayNameIsNotString = 6;
16629 const int kFunctionNameIsNotString = 7;
Kristian Monsen25f61362010-05-21 11:50:48 +010016630
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016631 CHECK(args.Length() == 1);
Kristian Monsen25f61362010-05-21 11:50:48 +010016632
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016633 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
16634 int testGroup = args[0]->Int32Value(context).FromJust();
Kristian Monsen25f61362010-05-21 11:50:48 +010016635 if (testGroup == kOverviewTest) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016636 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016637 args.GetIsolate(), 10, v8::StackTrace::kOverview);
Kristian Monsen25f61362010-05-21 11:50:48 +010016638 CHECK_EQ(4, stackTrace->GetFrameCount());
16639 checkStackFrame(origin, "bar", 2, 10, false, false,
16640 stackTrace->GetFrame(0));
16641 checkStackFrame(origin, "foo", 6, 3, false, false,
16642 stackTrace->GetFrame(1));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000016643 // This is the source string inside the eval which has the call to foo.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016644 checkStackFrame(NULL, "", 1, 1, false, false, stackTrace->GetFrame(2));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000016645 // The last frame is an anonymous function which has the initial eval call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016646 checkStackFrame(origin, "", 8, 7, false, false, stackTrace->GetFrame(3));
Kristian Monsen25f61362010-05-21 11:50:48 +010016647
16648 CHECK(stackTrace->AsArray()->IsArray());
16649 } else if (testGroup == kDetailedTest) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016650 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016651 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
Kristian Monsen25f61362010-05-21 11:50:48 +010016652 CHECK_EQ(4, stackTrace->GetFrameCount());
16653 checkStackFrame(origin, "bat", 4, 22, false, false,
16654 stackTrace->GetFrame(0));
16655 checkStackFrame(origin, "baz", 8, 3, false, true,
16656 stackTrace->GetFrame(1));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +010016657 bool is_eval = true;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000016658 // This is the source string inside the eval which has the call to baz.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016659 checkStackFrame(NULL, "", 1, 1, is_eval, false, stackTrace->GetFrame(2));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000016660 // The last frame is an anonymous function which has the initial eval call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016661 checkStackFrame(origin, "", 10, 1, false, false, stackTrace->GetFrame(3));
Kristian Monsen25f61362010-05-21 11:50:48 +010016662
16663 CHECK(stackTrace->AsArray()->IsArray());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016664 } else if (testGroup == kFunctionName) {
16665 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
16666 args.GetIsolate(), 5, v8::StackTrace::kOverview);
16667 CHECK_EQ(3, stackTrace->GetFrameCount());
16668 checkStackFrame(origin, "function.name", 2, 24, false, false,
16669 stackTrace->GetFrame(0));
16670 } else if (testGroup == kDisplayName) {
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.displayName", 2, 24, false, false,
16675 stackTrace->GetFrame(0));
16676 } else if (testGroup == kFunctionNameAndDisplayName) {
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 == kDisplayNameIsNotString) {
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.name", 2, 24, false, false,
16687 stackTrace->GetFrame(0));
16688 } else if (testGroup == kFunctionNameIsNotString) {
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, "f", 2, 24, false, false, stackTrace->GetFrame(0));
Kristian Monsen25f61362010-05-21 11:50:48 +010016693 }
Kristian Monsen25f61362010-05-21 11:50:48 +010016694}
16695
16696
16697// Tests the C++ StackTrace API.
Ben Murdochb0fe1622011-05-05 13:52:32 +010016698// TODO(3074796): Reenable this as a THREADED_TEST once it passes.
16699// THREADED_TEST(CaptureStackTrace) {
16700TEST(CaptureStackTrace) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016701 v8::Isolate* isolate = CcTest::isolate();
16702 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016703 v8::Local<v8::String> origin = v8_str("capture-stack-trace-test");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016704 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Kristian Monsen25f61362010-05-21 11:50:48 +010016705 templ->Set(v8_str("AnalyzeStackInNativeCode"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016706 v8::FunctionTemplate::New(isolate, AnalyzeStackInNativeCode));
Kristian Monsen25f61362010-05-21 11:50:48 +010016707 LocalContext context(0, templ);
16708
16709 // Test getting OVERVIEW information. Should ignore information that is not
16710 // script name, function name, line number, and column offset.
16711 const char *overview_source =
16712 "function bar() {\n"
16713 " var y; AnalyzeStackInNativeCode(1);\n"
16714 "}\n"
16715 "function foo() {\n"
16716 "\n"
16717 " bar();\n"
16718 "}\n"
16719 "var x;eval('new foo();');";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016720 v8::Local<v8::String> overview_src = v8_str(overview_source);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016721 v8::ScriptCompiler::Source script_source(overview_src,
16722 v8::ScriptOrigin(origin));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016723 v8::Local<Value> overview_result(
16724 v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source)
16725 .ToLocalChecked()
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016726 ->BindToCurrentContext()
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016727 ->Run(context.local())
16728 .ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016729 CHECK(!overview_result.IsEmpty());
16730 CHECK(overview_result->IsObject());
Kristian Monsen25f61362010-05-21 11:50:48 +010016731
16732 // Test getting DETAILED information.
16733 const char *detailed_source =
16734 "function bat() {AnalyzeStackInNativeCode(2);\n"
16735 "}\n"
16736 "\n"
16737 "function baz() {\n"
16738 " bat();\n"
16739 "}\n"
16740 "eval('new baz();');";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016741 v8::Local<v8::String> detailed_src = v8_str(detailed_source);
Kristian Monsen25f61362010-05-21 11:50:48 +010016742 // Make the script using a non-zero line and column offset.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016743 v8::Local<v8::Integer> line_offset = v8::Integer::New(isolate, 3);
16744 v8::Local<v8::Integer> column_offset = v8::Integer::New(isolate, 5);
Kristian Monsen25f61362010-05-21 11:50:48 +010016745 v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016746 v8::ScriptCompiler::Source script_source2(detailed_src, detailed_origin);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016747 v8::Local<v8::UnboundScript> detailed_script(
16748 v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source2)
16749 .ToLocalChecked());
16750 v8::Local<Value> detailed_result(detailed_script->BindToCurrentContext()
16751 ->Run(context.local())
16752 .ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016753 CHECK(!detailed_result.IsEmpty());
16754 CHECK(detailed_result->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016755
16756 // Test using function.name and function.displayName in stack trace
16757 const char* function_name_source =
16758 "function bar(function_name, display_name, testGroup) {\n"
16759 " var f = function() { AnalyzeStackInNativeCode(testGroup); };\n"
16760 " if (function_name) {\n"
16761 " Object.defineProperty(f, 'name', { value: function_name });\n"
16762 " }\n"
16763 " if (display_name) {\n"
16764 " f.displayName = display_name;"
16765 " }\n"
16766 " f()\n"
16767 "}\n"
16768 "bar('function.name', undefined, 3);\n"
16769 "bar(undefined, 'function.displayName', 4);\n"
16770 "bar('function.name', 'function.displayName', 5);\n"
16771 "bar('function.name', 239, 6);\n"
16772 "bar(239, undefined, 7);\n";
16773 v8::Local<v8::String> function_name_src =
16774 v8::String::NewFromUtf8(isolate, function_name_source,
16775 v8::NewStringType::kNormal)
16776 .ToLocalChecked();
16777 v8::ScriptCompiler::Source script_source3(function_name_src,
16778 v8::ScriptOrigin(origin));
16779 v8::Local<Value> function_name_result(
16780 v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source3)
16781 .ToLocalChecked()
16782 ->BindToCurrentContext()
16783 ->Run(context.local())
16784 .ToLocalChecked());
16785 CHECK(!function_name_result.IsEmpty());
Kristian Monsen25f61362010-05-21 11:50:48 +010016786}
16787
16788
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016789static void StackTraceForUncaughtExceptionListener(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016790 v8::Local<v8::Message> message, v8::Local<Value>) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016791 report_count++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016792 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016793 CHECK_EQ(2, stack_trace->GetFrameCount());
16794 checkStackFrame("origin", "foo", 2, 3, false, false,
16795 stack_trace->GetFrame(0));
16796 checkStackFrame("origin", "bar", 5, 3, false, false,
16797 stack_trace->GetFrame(1));
16798}
16799
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016800
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016801TEST(CaptureStackTraceForUncaughtException) {
16802 report_count = 0;
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016803 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016804 v8::Isolate* isolate = env->GetIsolate();
16805 v8::HandleScope scope(isolate);
16806 isolate->AddMessageListener(StackTraceForUncaughtExceptionListener);
16807 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016808
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016809 CompileRunWithOrigin(
16810 "function foo() {\n"
16811 " throw 1;\n"
16812 "};\n"
16813 "function bar() {\n"
16814 " foo();\n"
16815 "};",
16816 "origin");
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016817 v8::Local<v8::Object> global = env->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016818 Local<Value> trouble =
16819 global->Get(env.local(), v8_str("bar")).ToLocalChecked();
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016820 CHECK(trouble->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016821 CHECK(Function::Cast(*trouble)->Call(env.local(), global, 0, NULL).IsEmpty());
16822 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
16823 isolate->RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016824 CHECK_EQ(1, report_count);
16825}
16826
16827
16828TEST(GetStackTraceForUncaughtExceptionFromSimpleStackTrace) {
16829 report_count = 0;
16830 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016831 v8::Isolate* isolate = env->GetIsolate();
16832 v8::HandleScope scope(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016833
16834 // Create an Error object first.
16835 CompileRunWithOrigin(
16836 "function foo() {\n"
16837 "e=new Error('err');\n"
16838 "};\n"
16839 "function bar() {\n"
16840 " foo();\n"
16841 "};\n"
16842 "var e;",
16843 "origin");
16844 v8::Local<v8::Object> global = env->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016845 Local<Value> trouble =
16846 global->Get(env.local(), v8_str("bar")).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016847 CHECK(trouble->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016848 Function::Cast(*trouble)->Call(env.local(), global, 0, NULL).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016849
16850 // Enable capturing detailed stack trace late, and throw the exception.
16851 // The detailed stack trace should be extracted from the simple stack.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016852 isolate->AddMessageListener(StackTraceForUncaughtExceptionListener);
16853 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016854 CompileRunWithOrigin("throw e", "origin");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016855 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
16856 isolate->RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016857 CHECK_EQ(1, report_count);
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016858}
16859
16860
Steve Block1e0659c2011-05-24 12:43:12 +010016861TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
Steve Block1e0659c2011-05-24 12:43:12 +010016862 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016863 v8::Isolate* isolate = env->GetIsolate();
16864 v8::HandleScope scope(isolate);
16865 isolate->SetCaptureStackTraceForUncaughtExceptions(true, 1024,
16866 v8::StackTrace::kDetailed);
Steve Block1e0659c2011-05-24 12:43:12 +010016867
16868 CompileRun(
16869 "var setters = ['column', 'lineNumber', 'scriptName',\n"
16870 " 'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
16871 " 'isConstructor'];\n"
16872 "for (var i = 0; i < setters.length; i++) {\n"
16873 " var prop = setters[i];\n"
16874 " Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
16875 "}\n");
16876 CompileRun("throw 'exception';");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016877 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
Steve Block1e0659c2011-05-24 12:43:12 +010016878}
16879
16880
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016881static void StackTraceFunctionNameListener(v8::Local<v8::Message> message,
16882 v8::Local<Value>) {
16883 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
16884 CHECK_EQ(5, stack_trace->GetFrameCount());
16885 checkStackFrame("origin", "foo:0", 4, 7, false, false,
16886 stack_trace->GetFrame(0));
16887 checkStackFrame("origin", "foo:1", 5, 27, false, false,
16888 stack_trace->GetFrame(1));
16889 checkStackFrame("origin", "foo", 5, 27, false, false,
16890 stack_trace->GetFrame(2));
16891 checkStackFrame("origin", "foo", 5, 27, false, false,
16892 stack_trace->GetFrame(3));
16893 checkStackFrame("origin", "", 1, 14, false, false, stack_trace->GetFrame(4));
16894}
16895
16896
16897TEST(GetStackTraceContainsFunctionsWithFunctionName) {
16898 LocalContext env;
16899 v8::Isolate* isolate = env->GetIsolate();
16900 v8::HandleScope scope(isolate);
16901
16902 CompileRunWithOrigin(
16903 "function gen(name, counter) {\n"
16904 " var f = function foo() {\n"
16905 " if (counter === 0)\n"
16906 " throw 1;\n"
16907 " gen(name, counter - 1)();\n"
16908 " };\n"
16909 " if (counter == 3) {\n"
16910 " Object.defineProperty(f, 'name', {get: function(){ throw 239; }});\n"
16911 " } else {\n"
16912 " Object.defineProperty(f, 'name', {writable:true});\n"
16913 " if (counter == 2)\n"
16914 " f.name = 42;\n"
16915 " else\n"
16916 " f.name = name + ':' + counter;\n"
16917 " }\n"
16918 " return f;\n"
16919 "};",
16920 "origin");
16921
16922 isolate->AddMessageListener(StackTraceFunctionNameListener);
16923 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
16924 CompileRunWithOrigin("gen('foo', 3)();", "origin");
16925 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
16926 isolate->RemoveMessageListeners(StackTraceFunctionNameListener);
16927}
16928
16929
16930static void RethrowStackTraceHandler(v8::Local<v8::Message> message,
16931 v8::Local<v8::Value> data) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016932 // Use the frame where JavaScript is called from.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016933 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016934 CHECK(!stack_trace.IsEmpty());
16935 int frame_count = stack_trace->GetFrameCount();
16936 CHECK_EQ(3, frame_count);
16937 int line_number[] = {1, 2, 5};
16938 for (int i = 0; i < frame_count; i++) {
16939 CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
16940 }
16941}
16942
16943
16944// Test that we only return the stack trace at the site where the exception
16945// is first thrown (not where it is rethrown).
16946TEST(RethrowStackTrace) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016947 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016948 v8::Isolate* isolate = env->GetIsolate();
16949 v8::HandleScope scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016950 // We make sure that
16951 // - the stack trace of the ReferenceError in g() is reported.
16952 // - the stack trace is not overwritten when e1 is rethrown by t().
16953 // - the stack trace of e2 does not overwrite that of e1.
16954 const char* source =
16955 "function g() { error; } \n"
16956 "function f() { g(); } \n"
16957 "function t(e) { throw e; } \n"
16958 "try { \n"
16959 " f(); \n"
16960 "} catch (e1) { \n"
16961 " try { \n"
16962 " error; \n"
16963 " } catch (e2) { \n"
16964 " t(e1); \n"
16965 " } \n"
16966 "} \n";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016967 isolate->AddMessageListener(RethrowStackTraceHandler);
16968 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016969 CompileRun(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016970 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
16971 isolate->RemoveMessageListeners(RethrowStackTraceHandler);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016972}
16973
16974
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016975static void RethrowPrimitiveStackTraceHandler(v8::Local<v8::Message> message,
16976 v8::Local<v8::Value> data) {
16977 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016978 CHECK(!stack_trace.IsEmpty());
16979 int frame_count = stack_trace->GetFrameCount();
16980 CHECK_EQ(2, frame_count);
16981 int line_number[] = {3, 7};
16982 for (int i = 0; i < frame_count; i++) {
16983 CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
16984 }
16985}
16986
16987
16988// Test that we do not recognize identity for primitive exceptions.
16989TEST(RethrowPrimitiveStackTrace) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016990 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016991 v8::Isolate* isolate = env->GetIsolate();
16992 v8::HandleScope scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016993 // We do not capture stack trace for non Error objects on creation time.
16994 // Instead, we capture the stack trace on last throw.
16995 const char* source =
16996 "function g() { throw 404; } \n"
16997 "function f() { g(); } \n"
16998 "function t(e) { throw e; } \n"
16999 "try { \n"
17000 " f(); \n"
17001 "} catch (e1) { \n"
17002 " t(e1) \n"
17003 "} \n";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017004 isolate->AddMessageListener(RethrowPrimitiveStackTraceHandler);
17005 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017006 CompileRun(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017007 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
17008 isolate->RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017009}
17010
17011
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017012static void RethrowExistingStackTraceHandler(v8::Local<v8::Message> message,
17013 v8::Local<v8::Value> data) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017014 // Use the frame where JavaScript is called from.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017015 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017016 CHECK(!stack_trace.IsEmpty());
17017 CHECK_EQ(1, stack_trace->GetFrameCount());
17018 CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
17019}
17020
17021
17022// Test that the stack trace is captured when the error object is created and
17023// not where it is thrown.
17024TEST(RethrowExistingStackTrace) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017025 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017026 v8::Isolate* isolate = env->GetIsolate();
17027 v8::HandleScope scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017028 const char* source =
17029 "var e = new Error(); \n"
17030 "throw e; \n";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017031 isolate->AddMessageListener(RethrowExistingStackTraceHandler);
17032 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017033 CompileRun(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017034 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
17035 isolate->RemoveMessageListeners(RethrowExistingStackTraceHandler);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017036}
17037
17038
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017039static void RethrowBogusErrorStackTraceHandler(v8::Local<v8::Message> message,
17040 v8::Local<v8::Value> data) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017041 // Use the frame where JavaScript is called from.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017042 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017043 CHECK(!stack_trace.IsEmpty());
17044 CHECK_EQ(1, stack_trace->GetFrameCount());
17045 CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
17046}
17047
17048
17049// Test that the stack trace is captured where the bogus Error object is thrown.
17050TEST(RethrowBogusErrorStackTrace) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017051 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017052 v8::Isolate* isolate = env->GetIsolate();
17053 v8::HandleScope scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017054 const char* source =
17055 "var e = {__proto__: new Error()} \n"
17056 "throw e; \n";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017057 isolate->AddMessageListener(RethrowBogusErrorStackTraceHandler);
17058 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017059 CompileRun(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017060 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
17061 isolate->RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017062}
17063
17064
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017065v8::PromiseRejectEvent reject_event = v8::kPromiseRejectWithNoHandler;
17066int promise_reject_counter = 0;
17067int promise_revoke_counter = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017068int promise_reject_msg_line_number = -1;
17069int promise_reject_msg_column_number = -1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017070int promise_reject_line_number = -1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017071int promise_reject_column_number = -1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017072int promise_reject_frame_count = -1;
17073
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017074void PromiseRejectCallback(v8::PromiseRejectMessage reject_message) {
17075 v8::Local<v8::Object> global = CcTest::global();
17076 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
17077 if (reject_message.GetEvent() == v8::kPromiseRejectWithNoHandler) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017078 promise_reject_counter++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017079 global->Set(context, v8_str("rejected"), reject_message.GetPromise())
17080 .FromJust();
17081 global->Set(context, v8_str("value"), reject_message.GetValue()).FromJust();
17082 v8::Local<v8::Message> message = v8::Exception::CreateMessage(
17083 CcTest::isolate(), reject_message.GetValue());
17084 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
17085
17086 promise_reject_msg_line_number = message->GetLineNumber(context).FromJust();
17087 promise_reject_msg_column_number =
17088 message->GetStartColumn(context).FromJust() + 1;
17089
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017090 if (!stack_trace.IsEmpty()) {
17091 promise_reject_frame_count = stack_trace->GetFrameCount();
17092 if (promise_reject_frame_count > 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017093 CHECK(stack_trace->GetFrame(0)
17094 ->GetScriptName()
17095 ->Equals(context, v8_str("pro"))
17096 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017097 promise_reject_line_number = stack_trace->GetFrame(0)->GetLineNumber();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017098 promise_reject_column_number = stack_trace->GetFrame(0)->GetColumn();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017099 } else {
17100 promise_reject_line_number = -1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017101 promise_reject_column_number = -1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017102 }
17103 }
17104 } else {
17105 promise_revoke_counter++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017106 global->Set(context, v8_str("revoked"), reject_message.GetPromise())
17107 .FromJust();
17108 CHECK(reject_message.GetValue().IsEmpty());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017109 }
17110}
17111
17112
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017113v8::Local<v8::Promise> GetPromise(const char* name) {
17114 return v8::Local<v8::Promise>::Cast(
17115 CcTest::global()
17116 ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(name))
17117 .ToLocalChecked());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017118}
17119
17120
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017121v8::Local<v8::Value> RejectValue() {
17122 return CcTest::global()
17123 ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value"))
17124 .ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017125}
17126
17127
17128void ResetPromiseStates() {
17129 promise_reject_counter = 0;
17130 promise_revoke_counter = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017131 promise_reject_msg_line_number = -1;
17132 promise_reject_msg_column_number = -1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017133 promise_reject_line_number = -1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017134 promise_reject_column_number = -1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017135 promise_reject_frame_count = -1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017136
17137 v8::Local<v8::Object> global = CcTest::global();
17138 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
17139 global->Set(context, v8_str("rejected"), v8_str("")).FromJust();
17140 global->Set(context, v8_str("value"), v8_str("")).FromJust();
17141 global->Set(context, v8_str("revoked"), v8_str("")).FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017142}
17143
17144
17145TEST(PromiseRejectCallback) {
17146 LocalContext env;
17147 v8::Isolate* isolate = env->GetIsolate();
17148 v8::HandleScope scope(isolate);
17149
17150 isolate->SetPromiseRejectCallback(PromiseRejectCallback);
17151
17152 ResetPromiseStates();
17153
17154 // Create promise p0.
17155 CompileRun(
17156 "var reject; \n"
17157 "var p0 = new Promise( \n"
17158 " function(res, rej) { \n"
17159 " reject = rej; \n"
17160 " } \n"
17161 "); \n");
17162 CHECK(!GetPromise("p0")->HasHandler());
17163 CHECK_EQ(0, promise_reject_counter);
17164 CHECK_EQ(0, promise_revoke_counter);
17165
17166 // Add resolve handler (and default reject handler) to p0.
17167 CompileRun("var p1 = p0.then(function(){});");
17168 CHECK(GetPromise("p0")->HasHandler());
17169 CHECK(!GetPromise("p1")->HasHandler());
17170 CHECK_EQ(0, promise_reject_counter);
17171 CHECK_EQ(0, promise_revoke_counter);
17172
17173 // Reject p0.
17174 CompileRun("reject('ppp');");
17175 CHECK(GetPromise("p0")->HasHandler());
17176 CHECK(!GetPromise("p1")->HasHandler());
17177 CHECK_EQ(1, promise_reject_counter);
17178 CHECK_EQ(0, promise_revoke_counter);
17179 CHECK_EQ(v8::kPromiseRejectWithNoHandler, reject_event);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017180 CHECK(
17181 GetPromise("rejected")->Equals(env.local(), GetPromise("p1")).FromJust());
17182 CHECK(RejectValue()->Equals(env.local(), v8_str("ppp")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017183
17184 // Reject p0 again. Callback is not triggered again.
17185 CompileRun("reject();");
17186 CHECK(GetPromise("p0")->HasHandler());
17187 CHECK(!GetPromise("p1")->HasHandler());
17188 CHECK_EQ(1, promise_reject_counter);
17189 CHECK_EQ(0, promise_revoke_counter);
17190
17191 // Add resolve handler to p1.
17192 CompileRun("var p2 = p1.then(function(){});");
17193 CHECK(GetPromise("p0")->HasHandler());
17194 CHECK(GetPromise("p1")->HasHandler());
17195 CHECK(!GetPromise("p2")->HasHandler());
17196 CHECK_EQ(2, promise_reject_counter);
17197 CHECK_EQ(1, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017198 CHECK(
17199 GetPromise("rejected")->Equals(env.local(), GetPromise("p2")).FromJust());
17200 CHECK(RejectValue()->Equals(env.local(), v8_str("ppp")).FromJust());
17201 CHECK(
17202 GetPromise("revoked")->Equals(env.local(), GetPromise("p1")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017203
17204 ResetPromiseStates();
17205
17206 // Create promise q0.
17207 CompileRun(
17208 "var q0 = new Promise( \n"
17209 " function(res, rej) { \n"
17210 " reject = rej; \n"
17211 " } \n"
17212 "); \n");
17213 CHECK(!GetPromise("q0")->HasHandler());
17214 CHECK_EQ(0, promise_reject_counter);
17215 CHECK_EQ(0, promise_revoke_counter);
17216
17217 // Add reject handler to q0.
17218 CompileRun("var q1 = q0.catch(function() {});");
17219 CHECK(GetPromise("q0")->HasHandler());
17220 CHECK(!GetPromise("q1")->HasHandler());
17221 CHECK_EQ(0, promise_reject_counter);
17222 CHECK_EQ(0, promise_revoke_counter);
17223
17224 // Reject q0.
17225 CompileRun("reject('qq')");
17226 CHECK(GetPromise("q0")->HasHandler());
17227 CHECK(!GetPromise("q1")->HasHandler());
17228 CHECK_EQ(0, promise_reject_counter);
17229 CHECK_EQ(0, promise_revoke_counter);
17230
17231 // Add a new reject handler, which rejects by returning Promise.reject().
17232 // The returned promise q_ triggers a reject callback at first, only to
17233 // revoke it when returning it causes q2 to be rejected.
17234 CompileRun(
17235 "var q_;"
17236 "var q2 = q0.catch( \n"
17237 " function() { \n"
17238 " q_ = Promise.reject('qqq'); \n"
17239 " return q_; \n"
17240 " } \n"
17241 "); \n");
17242 CHECK(GetPromise("q0")->HasHandler());
17243 CHECK(!GetPromise("q1")->HasHandler());
17244 CHECK(!GetPromise("q2")->HasHandler());
17245 CHECK(GetPromise("q_")->HasHandler());
17246 CHECK_EQ(2, promise_reject_counter);
17247 CHECK_EQ(1, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017248 CHECK(
17249 GetPromise("rejected")->Equals(env.local(), GetPromise("q2")).FromJust());
17250 CHECK(
17251 GetPromise("revoked")->Equals(env.local(), GetPromise("q_")).FromJust());
17252 CHECK(RejectValue()->Equals(env.local(), v8_str("qqq")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017253
17254 // Add a reject handler to the resolved q1, which rejects by throwing.
17255 CompileRun(
17256 "var q3 = q1.then( \n"
17257 " function() { \n"
17258 " throw 'qqqq'; \n"
17259 " } \n"
17260 "); \n");
17261 CHECK(GetPromise("q0")->HasHandler());
17262 CHECK(GetPromise("q1")->HasHandler());
17263 CHECK(!GetPromise("q2")->HasHandler());
17264 CHECK(!GetPromise("q3")->HasHandler());
17265 CHECK_EQ(3, promise_reject_counter);
17266 CHECK_EQ(1, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017267 CHECK(
17268 GetPromise("rejected")->Equals(env.local(), GetPromise("q3")).FromJust());
17269 CHECK(RejectValue()->Equals(env.local(), v8_str("qqqq")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017270
17271 ResetPromiseStates();
17272
17273 // Create promise r0, which has three handlers, two of which handle rejects.
17274 CompileRun(
17275 "var r0 = new Promise( \n"
17276 " function(res, rej) { \n"
17277 " reject = rej; \n"
17278 " } \n"
17279 "); \n"
17280 "var r1 = r0.catch(function() {}); \n"
17281 "var r2 = r0.then(function() {}); \n"
17282 "var r3 = r0.then(function() {}, \n"
17283 " function() {}); \n");
17284 CHECK(GetPromise("r0")->HasHandler());
17285 CHECK(!GetPromise("r1")->HasHandler());
17286 CHECK(!GetPromise("r2")->HasHandler());
17287 CHECK(!GetPromise("r3")->HasHandler());
17288 CHECK_EQ(0, promise_reject_counter);
17289 CHECK_EQ(0, promise_revoke_counter);
17290
17291 // Reject r0.
17292 CompileRun("reject('rrr')");
17293 CHECK(GetPromise("r0")->HasHandler());
17294 CHECK(!GetPromise("r1")->HasHandler());
17295 CHECK(!GetPromise("r2")->HasHandler());
17296 CHECK(!GetPromise("r3")->HasHandler());
17297 CHECK_EQ(1, promise_reject_counter);
17298 CHECK_EQ(0, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017299 CHECK(
17300 GetPromise("rejected")->Equals(env.local(), GetPromise("r2")).FromJust());
17301 CHECK(RejectValue()->Equals(env.local(), v8_str("rrr")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017302
17303 // Add reject handler to r2.
17304 CompileRun("var r4 = r2.catch(function() {});");
17305 CHECK(GetPromise("r0")->HasHandler());
17306 CHECK(!GetPromise("r1")->HasHandler());
17307 CHECK(GetPromise("r2")->HasHandler());
17308 CHECK(!GetPromise("r3")->HasHandler());
17309 CHECK(!GetPromise("r4")->HasHandler());
17310 CHECK_EQ(1, promise_reject_counter);
17311 CHECK_EQ(1, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017312 CHECK(
17313 GetPromise("revoked")->Equals(env.local(), GetPromise("r2")).FromJust());
17314 CHECK(RejectValue()->Equals(env.local(), v8_str("rrr")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017315
17316 // Add reject handlers to r4.
17317 CompileRun("var r5 = r4.then(function() {}, function() {});");
17318 CHECK(GetPromise("r0")->HasHandler());
17319 CHECK(!GetPromise("r1")->HasHandler());
17320 CHECK(GetPromise("r2")->HasHandler());
17321 CHECK(!GetPromise("r3")->HasHandler());
17322 CHECK(GetPromise("r4")->HasHandler());
17323 CHECK(!GetPromise("r5")->HasHandler());
17324 CHECK_EQ(1, promise_reject_counter);
17325 CHECK_EQ(1, promise_revoke_counter);
17326
17327 ResetPromiseStates();
17328
17329 // Create promise s0, which has three handlers, none of which handle rejects.
17330 CompileRun(
17331 "var s0 = new Promise( \n"
17332 " function(res, rej) { \n"
17333 " reject = rej; \n"
17334 " } \n"
17335 "); \n"
17336 "var s1 = s0.then(function() {}); \n"
17337 "var s2 = s0.then(function() {}); \n"
17338 "var s3 = s0.then(function() {}); \n");
17339 CHECK(GetPromise("s0")->HasHandler());
17340 CHECK(!GetPromise("s1")->HasHandler());
17341 CHECK(!GetPromise("s2")->HasHandler());
17342 CHECK(!GetPromise("s3")->HasHandler());
17343 CHECK_EQ(0, promise_reject_counter);
17344 CHECK_EQ(0, promise_revoke_counter);
17345
17346 // Reject s0.
17347 CompileRun("reject('sss')");
17348 CHECK(GetPromise("s0")->HasHandler());
17349 CHECK(!GetPromise("s1")->HasHandler());
17350 CHECK(!GetPromise("s2")->HasHandler());
17351 CHECK(!GetPromise("s3")->HasHandler());
17352 CHECK_EQ(3, promise_reject_counter);
17353 CHECK_EQ(0, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017354 CHECK(RejectValue()->Equals(env.local(), v8_str("sss")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017355
17356 // Test stack frames.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017357 env->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017358
17359 ResetPromiseStates();
17360
17361 // Create promise t0, which is rejected in the constructor with an error.
17362 CompileRunWithOrigin(
17363 "var t0 = new Promise( \n"
17364 " function(res, rej) { \n"
17365 " reference_error; \n"
17366 " } \n"
17367 "); \n",
17368 "pro", 0, 0);
17369 CHECK(!GetPromise("t0")->HasHandler());
17370 CHECK_EQ(1, promise_reject_counter);
17371 CHECK_EQ(0, promise_revoke_counter);
17372 CHECK_EQ(2, promise_reject_frame_count);
17373 CHECK_EQ(3, promise_reject_line_number);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017374 CHECK_EQ(5, promise_reject_column_number);
17375 CHECK_EQ(3, promise_reject_msg_line_number);
17376 CHECK_EQ(5, promise_reject_msg_column_number);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017377
17378 ResetPromiseStates();
17379
17380 // Create promise u0 and chain u1 to it, which is rejected via throw.
17381 CompileRunWithOrigin(
17382 "var u0 = Promise.resolve(); \n"
17383 "var u1 = u0.then( \n"
17384 " function() { \n"
17385 " (function() { \n"
17386 " throw new Error(); \n"
17387 " })(); \n"
17388 " } \n"
17389 " ); \n",
17390 "pro", 0, 0);
17391 CHECK(GetPromise("u0")->HasHandler());
17392 CHECK(!GetPromise("u1")->HasHandler());
17393 CHECK_EQ(1, promise_reject_counter);
17394 CHECK_EQ(0, promise_revoke_counter);
17395 CHECK_EQ(2, promise_reject_frame_count);
17396 CHECK_EQ(5, promise_reject_line_number);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017397 CHECK_EQ(23, promise_reject_column_number);
17398 CHECK_EQ(5, promise_reject_msg_line_number);
17399 CHECK_EQ(23, promise_reject_msg_column_number);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017400
17401 // Throw in u3, which handles u1's rejection.
17402 CompileRunWithOrigin(
17403 "function f() { \n"
17404 " return (function() { \n"
17405 " return new Error(); \n"
17406 " })(); \n"
17407 "} \n"
17408 "var u2 = Promise.reject(f()); \n"
17409 "var u3 = u1.catch( \n"
17410 " function() { \n"
17411 " return u2; \n"
17412 " } \n"
17413 " ); \n",
17414 "pro", 0, 0);
17415 CHECK(GetPromise("u0")->HasHandler());
17416 CHECK(GetPromise("u1")->HasHandler());
17417 CHECK(GetPromise("u2")->HasHandler());
17418 CHECK(!GetPromise("u3")->HasHandler());
17419 CHECK_EQ(3, promise_reject_counter);
17420 CHECK_EQ(2, promise_revoke_counter);
17421 CHECK_EQ(3, promise_reject_frame_count);
17422 CHECK_EQ(3, promise_reject_line_number);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017423 CHECK_EQ(12, promise_reject_column_number);
17424 CHECK_EQ(3, promise_reject_msg_line_number);
17425 CHECK_EQ(12, promise_reject_msg_column_number);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017426
17427 ResetPromiseStates();
17428
17429 // Create promise rejected promise v0, which is incorrectly handled by v1
17430 // via chaining cycle.
17431 CompileRunWithOrigin(
17432 "var v0 = Promise.reject(); \n"
17433 "var v1 = v0.catch( \n"
17434 " function() { \n"
17435 " return v1; \n"
17436 " } \n"
17437 " ); \n",
17438 "pro", 0, 0);
17439 CHECK(GetPromise("v0")->HasHandler());
17440 CHECK(!GetPromise("v1")->HasHandler());
17441 CHECK_EQ(2, promise_reject_counter);
17442 CHECK_EQ(1, promise_revoke_counter);
17443 CHECK_EQ(0, promise_reject_frame_count);
17444 CHECK_EQ(-1, promise_reject_line_number);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017445 CHECK_EQ(-1, promise_reject_column_number);
17446
17447 ResetPromiseStates();
17448
17449 // Create promise t1, which rejects by throwing syntax error from eval.
17450 CompileRunWithOrigin(
17451 "var t1 = new Promise( \n"
17452 " function(res, rej) { \n"
17453 " var content = '\\n\\\n"
17454 " }'; \n"
17455 " eval(content); \n"
17456 " } \n"
17457 "); \n",
17458 "pro", 0, 0);
17459 CHECK(!GetPromise("t1")->HasHandler());
17460 CHECK_EQ(1, promise_reject_counter);
17461 CHECK_EQ(0, promise_revoke_counter);
17462 CHECK_EQ(2, promise_reject_frame_count);
17463 CHECK_EQ(5, promise_reject_line_number);
17464 CHECK_EQ(10, promise_reject_column_number);
17465 CHECK_EQ(2, promise_reject_msg_line_number);
17466 CHECK_EQ(7, promise_reject_msg_column_number);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017467}
17468
17469
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017470void AnalyzeStackOfEvalWithSourceURL(
17471 const v8::FunctionCallbackInfo<v8::Value>& args) {
17472 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017473 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017474 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
Ben Murdochf87a2032010-10-22 12:50:53 +010017475 CHECK_EQ(5, stackTrace->GetFrameCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017476 v8::Local<v8::String> url = v8_str("eval_url");
Ben Murdochf87a2032010-10-22 12:50:53 +010017477 for (int i = 0; i < 3; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017478 v8::Local<v8::String> name =
Ben Murdochf87a2032010-10-22 12:50:53 +010017479 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17480 CHECK(!name.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017481 CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
Ben Murdochf87a2032010-10-22 12:50:53 +010017482 }
Ben Murdochf87a2032010-10-22 12:50:53 +010017483}
17484
17485
17486TEST(SourceURLInStackTrace) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017487 v8::Isolate* isolate = CcTest::isolate();
17488 v8::HandleScope scope(isolate);
17489 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdochf87a2032010-10-22 12:50:53 +010017490 templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017491 v8::FunctionTemplate::New(isolate,
17492 AnalyzeStackOfEvalWithSourceURL));
Ben Murdochf87a2032010-10-22 12:50:53 +010017493 LocalContext context(0, templ);
17494
17495 const char *source =
17496 "function outer() {\n"
17497 "function bar() {\n"
17498 " AnalyzeStackOfEvalWithSourceURL();\n"
17499 "}\n"
17500 "function foo() {\n"
17501 "\n"
17502 " bar();\n"
17503 "}\n"
17504 "foo();\n"
17505 "}\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017506 "eval('(' + outer +')()%s');";
17507
17508 i::ScopedVector<char> code(1024);
17509 i::SNPrintF(code, source, "//# sourceURL=eval_url");
17510 CHECK(CompileRun(code.start())->IsUndefined());
17511 i::SNPrintF(code, source, "//@ sourceURL=eval_url");
17512 CHECK(CompileRun(code.start())->IsUndefined());
17513}
17514
17515
17516static int scriptIdInStack[2];
17517
17518void AnalyzeScriptIdInStack(
17519 const v8::FunctionCallbackInfo<v8::Value>& args) {
17520 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017521 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017522 args.GetIsolate(), 10, v8::StackTrace::kScriptId);
17523 CHECK_EQ(2, stackTrace->GetFrameCount());
17524 for (int i = 0; i < 2; i++) {
17525 scriptIdInStack[i] = stackTrace->GetFrame(i)->GetScriptId();
17526 }
17527}
17528
17529
17530TEST(ScriptIdInStackTrace) {
17531 v8::Isolate* isolate = CcTest::isolate();
17532 v8::HandleScope scope(isolate);
17533 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17534 templ->Set(v8_str("AnalyzeScriptIdInStack"),
17535 v8::FunctionTemplate::New(isolate, AnalyzeScriptIdInStack));
17536 LocalContext context(0, templ);
17537
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017538 v8::Local<v8::String> scriptSource = v8_str(
17539 "function foo() {\n"
17540 " AnalyzeScriptIdInStack();"
17541 "}\n"
17542 "foo();\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017543 v8::Local<v8::Script> script = CompileWithOrigin(scriptSource, "test");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017544 script->Run(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017545 for (int i = 0; i < 2; i++) {
17546 CHECK(scriptIdInStack[i] != v8::Message::kNoScriptIdInfo);
17547 CHECK_EQ(scriptIdInStack[i], script->GetUnboundScript()->GetId());
17548 }
17549}
17550
17551
17552void AnalyzeStackOfInlineScriptWithSourceURL(
17553 const v8::FunctionCallbackInfo<v8::Value>& args) {
17554 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017555 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017556 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
17557 CHECK_EQ(4, stackTrace->GetFrameCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017558 v8::Local<v8::String> url = v8_str("source_url");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017559 for (int i = 0; i < 3; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017560 v8::Local<v8::String> name =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017561 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17562 CHECK(!name.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017563 CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017564 }
17565}
17566
17567
17568TEST(InlineScriptWithSourceURLInStackTrace) {
17569 v8::Isolate* isolate = CcTest::isolate();
17570 v8::HandleScope scope(isolate);
17571 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17572 templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
17573 v8::FunctionTemplate::New(
17574 CcTest::isolate(), AnalyzeStackOfInlineScriptWithSourceURL));
17575 LocalContext context(0, templ);
17576
17577 const char *source =
17578 "function outer() {\n"
17579 "function bar() {\n"
17580 " AnalyzeStackOfInlineScriptWithSourceURL();\n"
17581 "}\n"
17582 "function foo() {\n"
17583 "\n"
17584 " bar();\n"
17585 "}\n"
17586 "foo();\n"
17587 "}\n"
17588 "outer()\n%s";
17589
17590 i::ScopedVector<char> code(1024);
17591 i::SNPrintF(code, source, "//# sourceURL=source_url");
17592 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
17593 i::SNPrintF(code, source, "//@ sourceURL=source_url");
17594 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
17595}
17596
17597
17598void AnalyzeStackOfDynamicScriptWithSourceURL(
17599 const v8::FunctionCallbackInfo<v8::Value>& args) {
17600 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017601 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017602 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
17603 CHECK_EQ(4, stackTrace->GetFrameCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017604 v8::Local<v8::String> url = v8_str("source_url");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017605 for (int i = 0; i < 3; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017606 v8::Local<v8::String> name =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017607 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17608 CHECK(!name.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017609 CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017610 }
17611}
17612
17613
17614TEST(DynamicWithSourceURLInStackTrace) {
17615 v8::Isolate* isolate = CcTest::isolate();
17616 v8::HandleScope scope(isolate);
17617 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17618 templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
17619 v8::FunctionTemplate::New(
17620 CcTest::isolate(), AnalyzeStackOfDynamicScriptWithSourceURL));
17621 LocalContext context(0, templ);
17622
17623 const char *source =
17624 "function outer() {\n"
17625 "function bar() {\n"
17626 " AnalyzeStackOfDynamicScriptWithSourceURL();\n"
17627 "}\n"
17628 "function foo() {\n"
17629 "\n"
17630 " bar();\n"
17631 "}\n"
17632 "foo();\n"
17633 "}\n"
17634 "outer()\n%s";
17635
17636 i::ScopedVector<char> code(1024);
17637 i::SNPrintF(code, source, "//# sourceURL=source_url");
17638 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
17639 i::SNPrintF(code, source, "//@ sourceURL=source_url");
17640 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
17641}
17642
17643
17644TEST(DynamicWithSourceURLInStackTraceString) {
17645 LocalContext context;
17646 v8::HandleScope scope(context->GetIsolate());
17647
17648 const char *source =
17649 "function outer() {\n"
17650 " function foo() {\n"
17651 " FAIL.FAIL;\n"
17652 " }\n"
17653 " foo();\n"
17654 "}\n"
17655 "outer()\n%s";
17656
17657 i::ScopedVector<char> code(1024);
17658 i::SNPrintF(code, source, "//# sourceURL=source_url");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017659 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017660 CompileRunWithOrigin(code.start(), "", 0, 0);
17661 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017662 v8::String::Utf8Value stack(
17663 try_catch.StackTrace(context.local()).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017664 CHECK(strstr(*stack, "at foo (source_url:3:5)") != NULL);
17665}
17666
17667
17668TEST(EvalWithSourceURLInMessageScriptResourceNameOrSourceURL) {
17669 LocalContext context;
17670 v8::HandleScope scope(context->GetIsolate());
17671
17672 const char *source =
17673 "function outer() {\n"
17674 " var scriptContents = \"function foo() { FAIL.FAIL; }\\\n"
17675 " //# sourceURL=source_url\";\n"
17676 " eval(scriptContents);\n"
17677 " foo(); }\n"
17678 "outer();\n"
17679 "//# sourceURL=outer_url";
17680
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017681 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017682 CompileRun(source);
17683 CHECK(try_catch.HasCaught());
17684
17685 Local<v8::Message> message = try_catch.Message();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017686 Local<Value> sourceURL = message->GetScriptOrigin().ResourceName();
17687 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(sourceURL), "source_url"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017688}
17689
17690
17691TEST(RecursionWithSourceURLInMessageScriptResourceNameOrSourceURL) {
17692 LocalContext context;
17693 v8::HandleScope scope(context->GetIsolate());
17694
17695 const char *source =
17696 "function outer() {\n"
17697 " var scriptContents = \"function boo(){ boo(); }\\\n"
17698 " //# sourceURL=source_url\";\n"
17699 " eval(scriptContents);\n"
17700 " boo(); }\n"
17701 "outer();\n"
17702 "//# sourceURL=outer_url";
17703
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017704 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017705 CompileRun(source);
17706 CHECK(try_catch.HasCaught());
17707
17708 Local<v8::Message> message = try_catch.Message();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017709 Local<Value> sourceURL = message->GetScriptOrigin().ResourceName();
17710 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(sourceURL), "source_url"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017711}
17712
17713
17714static void CreateGarbageInOldSpace() {
17715 i::Factory* factory = CcTest::i_isolate()->factory();
17716 v8::HandleScope scope(CcTest::isolate());
17717 i::AlwaysAllocateScope always_allocate(CcTest::i_isolate());
17718 for (int i = 0; i < 1000; i++) {
17719 factory->NewFixedArray(1000, i::TENURED);
17720 }
Ben Murdochf87a2032010-10-22 12:50:53 +010017721}
17722
17723
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017724// Test that idle notification can be handled and eventually collects garbage.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017725TEST(TestIdleNotification) {
17726 if (!i::FLAG_incremental_marking) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017727 const intptr_t MB = 1024 * 1024;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017728 const double IdlePauseInSeconds = 1.0;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017729 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017730 v8::HandleScope scope(env->GetIsolate());
17731 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
17732 CreateGarbageInOldSpace();
17733 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
17734 CHECK_GT(size_with_garbage, initial_size + MB);
17735 bool finished = false;
17736 for (int i = 0; i < 200 && !finished; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017737 if (i < 10 && CcTest::heap()->incremental_marking()->IsStopped()) {
17738 CcTest::heap()->StartIdleIncrementalMarking();
17739 }
17740 finished = env->GetIsolate()->IdleNotificationDeadline(
17741 (v8::base::TimeTicks::HighResolutionNow().ToInternalValue() /
17742 static_cast<double>(v8::base::Time::kMicrosecondsPerSecond)) +
17743 IdlePauseInSeconds);
17744 if (CcTest::heap()->mark_compact_collector()->sweeping_in_progress()) {
17745 CcTest::heap()->mark_compact_collector()->EnsureSweepingCompleted();
17746 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017747 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017748 intptr_t final_size = CcTest::heap()->SizeOfObjects();
17749 CHECK(finished);
17750 CHECK_LT(final_size, initial_size + 1);
Ben Murdochc7cc0282012-03-05 14:35:55 +000017751}
17752
Steve Blocka7e24c12009-10-30 11:49:00 +000017753
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017754TEST(Regress2333) {
17755 LocalContext env;
17756 for (int i = 0; i < 3; i++) {
17757 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
17758 }
17759}
17760
Steve Blocka7e24c12009-10-30 11:49:00 +000017761static uint32_t* stack_limit;
17762
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017763static void GetStackLimitCallback(
17764 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Block44f0eee2011-05-26 01:26:41 +010017765 stack_limit = reinterpret_cast<uint32_t*>(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017766 CcTest::i_isolate()->stack_guard()->real_climit());
Steve Blocka7e24c12009-10-30 11:49:00 +000017767}
17768
17769
17770// Uses the address of a local variable to determine the stack top now.
17771// Given a size, returns an address that is that far from the current
17772// top of stack.
17773static uint32_t* ComputeStackLimit(uint32_t size) {
17774 uint32_t* answer = &size - (size / sizeof(size));
17775 // If the size is very large and the stack is very near the bottom of
17776 // memory then the calculation above may wrap around and give an address
17777 // that is above the (downwards-growing) stack. In that case we return
17778 // a very low address.
17779 if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
17780 return answer;
17781}
17782
17783
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017784// We need at least 165kB for an x64 debug build with clang and ASAN.
17785static const int stack_breathing_room = 256 * i::KB;
17786
17787
17788TEST(SetStackLimit) {
17789 uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
Steve Blocka7e24c12009-10-30 11:49:00 +000017790
17791 // Set stack limit.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017792 CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
Steve Blocka7e24c12009-10-30 11:49:00 +000017793
17794 // Execute a script.
Steve Blocka7e24c12009-10-30 11:49:00 +000017795 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017796 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000017797 Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017798 v8::FunctionTemplate::New(env->GetIsolate(), GetStackLimitCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017799 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
17800 CHECK(env->Global()
17801 ->Set(env.local(), v8_str("get_stack_limit"), fun)
17802 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000017803 CompileRun("get_stack_limit();");
17804
17805 CHECK(stack_limit == set_limit);
17806}
17807
17808
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017809TEST(SetStackLimitInThread) {
Steve Blocka7e24c12009-10-30 11:49:00 +000017810 uint32_t* set_limit;
17811 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017812 v8::Locker locker(CcTest::isolate());
17813 set_limit = ComputeStackLimit(stack_breathing_room);
Steve Blocka7e24c12009-10-30 11:49:00 +000017814
17815 // Set stack limit.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017816 CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
Steve Blocka7e24c12009-10-30 11:49:00 +000017817
17818 // Execute a script.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017819 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000017820 LocalContext env;
17821 Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017822 v8::FunctionTemplate::New(CcTest::isolate(), GetStackLimitCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017823 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
17824 CHECK(env->Global()
17825 ->Set(env.local(), v8_str("get_stack_limit"), fun)
17826 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000017827 CompileRun("get_stack_limit();");
17828
17829 CHECK(stack_limit == set_limit);
17830 }
17831 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017832 v8::Locker locker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000017833 CHECK(stack_limit == set_limit);
17834 }
17835}
Steve Block3ce2e202009-11-05 08:53:23 +000017836
17837
17838THREADED_TEST(GetHeapStatistics) {
Steve Block3ce2e202009-11-05 08:53:23 +000017839 LocalContext c1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017840 v8::HandleScope scope(c1->GetIsolate());
Steve Block3ce2e202009-11-05 08:53:23 +000017841 v8::HeapStatistics heap_statistics;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017842 CHECK_EQ(0u, heap_statistics.total_heap_size());
17843 CHECK_EQ(0u, heap_statistics.used_heap_size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017844 c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
Steve Blockd0582a62009-12-15 09:54:21 +000017845 CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
17846 CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
17847}
17848
17849
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017850class VisitorImpl : public v8::ExternalResourceVisitor {
17851 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017852 explicit VisitorImpl(TestResource** resource) {
17853 for (int i = 0; i < 4; i++) {
17854 resource_[i] = resource[i];
17855 found_resource_[i] = false;
17856 }
17857 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017858 virtual ~VisitorImpl() {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017859 virtual void VisitExternalString(v8::Local<v8::String> string) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017860 if (!string->IsExternal()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017861 CHECK(string->IsExternalOneByte());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017862 return;
17863 }
17864 v8::String::ExternalStringResource* resource =
17865 string->GetExternalStringResource();
17866 CHECK(resource);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017867 for (int i = 0; i < 4; i++) {
17868 if (resource_[i] == resource) {
17869 CHECK(!found_resource_[i]);
17870 found_resource_[i] = true;
17871 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017872 }
17873 }
17874 void CheckVisitedResources() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017875 for (int i = 0; i < 4; i++) {
17876 CHECK(found_resource_[i]);
17877 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017878 }
17879
17880 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017881 v8::String::ExternalStringResource* resource_[4];
17882 bool found_resource_[4];
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017883};
17884
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017885
17886TEST(ExternalizeOldSpaceTwoByteCons) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017887 v8::Isolate* isolate = CcTest::isolate();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017888 LocalContext env;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017889 v8::HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017890 v8::Local<v8::String> cons =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017891 CompileRun("'Romeo Montague ' + 'Juliet Capulet'")
17892 ->ToString(env.local())
17893 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017894 CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
17895 CcTest::heap()->CollectAllAvailableGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017896 CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017897
17898 TestResource* resource = new TestResource(
17899 AsciiToTwoByteString("Romeo Montague Juliet Capulet"));
17900 cons->MakeExternal(resource);
17901
17902 CHECK(cons->IsExternal());
17903 CHECK_EQ(resource, cons->GetExternalStringResource());
17904 String::Encoding encoding;
17905 CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
17906 CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
17907}
17908
17909
17910TEST(ExternalizeOldSpaceOneByteCons) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017911 v8::Isolate* isolate = CcTest::isolate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017912 LocalContext env;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017913 v8::HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017914 v8::Local<v8::String> cons =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017915 CompileRun("'Romeo Montague ' + 'Juliet Capulet'")
17916 ->ToString(env.local())
17917 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017918 CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
17919 CcTest::heap()->CollectAllAvailableGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017920 CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017921
17922 TestOneByteResource* resource =
17923 new TestOneByteResource(i::StrDup("Romeo Montague Juliet Capulet"));
17924 cons->MakeExternal(resource);
17925
17926 CHECK(cons->IsExternalOneByte());
17927 CHECK_EQ(resource, cons->GetExternalOneByteStringResource());
17928 String::Encoding encoding;
17929 CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
17930 CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
17931}
17932
17933
17934TEST(VisitExternalStrings) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017935 v8::Isolate* isolate = CcTest::isolate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017936 LocalContext env;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017937 v8::HandleScope scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017938 const char* string = "Some string";
17939 uint16_t* two_byte_string = AsciiToTwoByteString(string);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017940 TestResource* resource[4];
17941 resource[0] = new TestResource(two_byte_string);
17942 v8::Local<v8::String> string0 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017943 v8::String::NewExternalTwoByte(env->GetIsolate(), resource[0])
17944 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017945 resource[1] = new TestResource(two_byte_string, NULL, false);
17946 v8::Local<v8::String> string1 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017947 v8::String::NewExternalTwoByte(env->GetIsolate(), resource[1])
17948 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017949
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017950 // Externalized symbol.
17951 resource[2] = new TestResource(two_byte_string, NULL, false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017952 v8::Local<v8::String> string2 =
17953 v8::String::NewFromUtf8(env->GetIsolate(), string,
17954 v8::NewStringType::kInternalized)
17955 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017956 CHECK(string2->MakeExternal(resource[2]));
17957
17958 // Symbolized External.
17959 resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
17960 v8::Local<v8::String> string3 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017961 v8::String::NewExternalTwoByte(env->GetIsolate(), resource[3])
17962 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017963 CcTest::heap()->CollectAllAvailableGarbage(); // Tenure string.
17964 // Turn into a symbol.
17965 i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
17966 CHECK(!CcTest::i_isolate()->factory()->InternalizeString(
17967 string3_i).is_null());
17968 CHECK(string3_i->IsInternalizedString());
17969
17970 // We need to add usages for string* to avoid warnings in GCC 4.7
17971 CHECK(string0->IsExternal());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017972 CHECK(string1->IsExternal());
17973 CHECK(string2->IsExternal());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017974 CHECK(string3->IsExternal());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017975
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017976 VisitorImpl visitor(resource);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017977 isolate->VisitExternalResources(&visitor);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017978 visitor.CheckVisitedResources();
17979}
17980
17981
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017982TEST(ExternalStringCollectedAtTearDown) {
17983 int destroyed = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017984 v8::Isolate::CreateParams create_params;
17985 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
17986 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017987 { v8::Isolate::Scope isolate_scope(isolate);
17988 v8::HandleScope handle_scope(isolate);
17989 const char* s = "One string to test them all, one string to find them.";
17990 TestOneByteResource* inscription =
17991 new TestOneByteResource(i::StrDup(s), &destroyed);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017992 v8::Local<v8::String> ring =
17993 v8::String::NewExternalOneByte(isolate, inscription).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017994 // Ring is still alive. Orcs are roaming freely across our lands.
17995 CHECK_EQ(0, destroyed);
17996 USE(ring);
17997 }
17998
17999 isolate->Dispose();
18000 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
18001 CHECK_EQ(1, destroyed);
18002}
18003
18004
18005TEST(ExternalInternalizedStringCollectedAtTearDown) {
18006 int destroyed = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018007 v8::Isolate::CreateParams create_params;
18008 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
18009 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018010 { v8::Isolate::Scope isolate_scope(isolate);
18011 LocalContext env(isolate);
18012 v8::HandleScope handle_scope(isolate);
18013 CompileRun("var ring = 'One string to test them all';");
18014 const char* s = "One string to test them all";
18015 TestOneByteResource* inscription =
18016 new TestOneByteResource(i::StrDup(s), &destroyed);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018017 v8::Local<v8::String> ring =
18018 CompileRun("ring")->ToString(env.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018019 CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
18020 ring->MakeExternal(inscription);
18021 // Ring is still alive. Orcs are roaming freely across our lands.
18022 CHECK_EQ(0, destroyed);
18023 USE(ring);
18024 }
18025
18026 isolate->Dispose();
18027 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
18028 CHECK_EQ(1, destroyed);
18029}
18030
18031
18032TEST(ExternalInternalizedStringCollectedAtGC) {
18033 int destroyed = 0;
18034 { LocalContext env;
18035 v8::HandleScope handle_scope(env->GetIsolate());
18036 CompileRun("var ring = 'One string to test them all';");
18037 const char* s = "One string to test them all";
18038 TestOneByteResource* inscription =
18039 new TestOneByteResource(i::StrDup(s), &destroyed);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018040 v8::Local<v8::String> ring = CompileRun("ring").As<v8::String>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018041 CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
18042 ring->MakeExternal(inscription);
18043 // Ring is still alive. Orcs are roaming freely across our lands.
18044 CHECK_EQ(0, destroyed);
18045 USE(ring);
18046 }
18047
18048 // Garbage collector deals swift blows to evil.
18049 CcTest::i_isolate()->compilation_cache()->Clear();
18050 CcTest::heap()->CollectAllAvailableGarbage();
18051
18052 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
18053 CHECK_EQ(1, destroyed);
18054}
18055
18056
Steve Blockd0582a62009-12-15 09:54:21 +000018057static double DoubleFromBits(uint64_t value) {
18058 double target;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018059 i::MemCopy(&target, &value, sizeof(target));
Steve Blockd0582a62009-12-15 09:54:21 +000018060 return target;
18061}
18062
18063
18064static uint64_t DoubleToBits(double value) {
18065 uint64_t target;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018066 i::MemCopy(&target, &value, sizeof(target));
Steve Blockd0582a62009-12-15 09:54:21 +000018067 return target;
18068}
18069
18070
18071static double DoubleToDateTime(double input) {
18072 double date_limit = 864e13;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018073 if (std::isnan(input) || input < -date_limit || input > date_limit) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018074 return std::numeric_limits<double>::quiet_NaN();
Steve Blockd0582a62009-12-15 09:54:21 +000018075 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018076 return (input < 0) ? -(std::floor(-input)) : std::floor(input);
Steve Blockd0582a62009-12-15 09:54:21 +000018077}
18078
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018079
Steve Blockd0582a62009-12-15 09:54:21 +000018080// We don't have a consistent way to write 64-bit constants syntactically, so we
18081// split them into two 32-bit constants and combine them programmatically.
18082static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
18083 return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
18084}
18085
18086
18087THREADED_TEST(QuietSignalingNaNs) {
Steve Blockd0582a62009-12-15 09:54:21 +000018088 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018089 v8::Isolate* isolate = context->GetIsolate();
18090 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018091 v8::TryCatch try_catch(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018092
18093 // Special double values.
18094 double snan = DoubleFromBits(0x7ff00000, 0x00000001);
18095 double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
18096 double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
18097 double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
18098 double min_normal = DoubleFromBits(0x00100000, 0x00000000);
18099 double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
18100 double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
18101
18102 // Date values are capped at +/-100000000 days (times 864e5 ms per day)
18103 // on either side of the epoch.
18104 double date_limit = 864e13;
18105
18106 double test_values[] = {
18107 snan,
18108 qnan,
18109 infinity,
18110 max_normal,
18111 date_limit + 1,
18112 date_limit,
18113 min_normal,
18114 max_denormal,
18115 min_denormal,
18116 0,
18117 -0,
18118 -min_denormal,
18119 -max_denormal,
18120 -min_normal,
18121 -date_limit,
18122 -date_limit - 1,
18123 -max_normal,
18124 -infinity,
18125 -qnan,
18126 -snan
18127 };
18128 int num_test_values = 20;
18129
18130 for (int i = 0; i < num_test_values; i++) {
18131 double test_value = test_values[i];
18132
18133 // Check that Number::New preserves non-NaNs and quiets SNaNs.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018134 v8::Local<v8::Value> number = v8::Number::New(isolate, test_value);
18135 double stored_number = number->NumberValue(context.local()).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018136 if (!std::isnan(test_value)) {
Steve Blockd0582a62009-12-15 09:54:21 +000018137 CHECK_EQ(test_value, stored_number);
18138 } else {
18139 uint64_t stored_bits = DoubleToBits(stored_number);
18140 // Check if quiet nan (bits 51..62 all set).
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018141#if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018142 !defined(_MIPS_ARCH_MIPS64R6) && !defined(_MIPS_ARCH_MIPS32R6) && \
18143 !defined(USE_SIMULATOR)
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018144 // Most significant fraction bit for quiet nan is set to 0
18145 // on MIPS architecture. Allowed by IEEE-754.
18146 CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
18147#else
Steve Blockd0582a62009-12-15 09:54:21 +000018148 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018149#endif
Steve Blockd0582a62009-12-15 09:54:21 +000018150 }
18151
18152 // Check that Date::New preserves non-NaNs in the date range and
18153 // quiets SNaNs.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018154 v8::Local<v8::Value> date =
18155 v8::Date::New(context.local(), test_value).ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +000018156 double expected_stored_date = DoubleToDateTime(test_value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018157 double stored_date = date->NumberValue(context.local()).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018158 if (!std::isnan(expected_stored_date)) {
Steve Blockd0582a62009-12-15 09:54:21 +000018159 CHECK_EQ(expected_stored_date, stored_date);
18160 } else {
18161 uint64_t stored_bits = DoubleToBits(stored_date);
18162 // Check if quiet nan (bits 51..62 all set).
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018163#if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018164 !defined(_MIPS_ARCH_MIPS64R6) && !defined(_MIPS_ARCH_MIPS32R6) && \
18165 !defined(USE_SIMULATOR)
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018166 // Most significant fraction bit for quiet nan is set to 0
18167 // on MIPS architecture. Allowed by IEEE-754.
18168 CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
18169#else
Steve Blockd0582a62009-12-15 09:54:21 +000018170 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018171#endif
Steve Blockd0582a62009-12-15 09:54:21 +000018172 }
18173 }
18174}
18175
18176
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018177static void SpaghettiIncident(
18178 const v8::FunctionCallbackInfo<v8::Value>& args) {
18179 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018180 v8::TryCatch tc(args.GetIsolate());
18181 v8::MaybeLocal<v8::String> str(
18182 args[0]->ToString(args.GetIsolate()->GetCurrentContext()));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018183 USE(str);
Steve Blockd0582a62009-12-15 09:54:21 +000018184 if (tc.HasCaught())
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018185 tc.ReThrow();
Steve Blockd0582a62009-12-15 09:54:21 +000018186}
18187
18188
18189// Test that an exception can be propagated down through a spaghetti
18190// stack using ReThrow.
18191THREADED_TEST(SpaghettiStackReThrow) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018192 v8::Isolate* isolate = CcTest::isolate();
18193 v8::HandleScope scope(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018194 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018195 context->Global()
18196 ->Set(context.local(), v8_str("s"),
18197 v8::FunctionTemplate::New(isolate, SpaghettiIncident)
18198 ->GetFunction(context.local())
18199 .ToLocalChecked())
18200 .FromJust();
18201 v8::TryCatch try_catch(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018202 CompileRun(
18203 "var i = 0;"
18204 "var o = {"
18205 " toString: function () {"
18206 " if (i == 10) {"
18207 " throw 'Hey!';"
18208 " } else {"
18209 " i++;"
18210 " return s(o);"
18211 " }"
18212 " }"
18213 "};"
18214 "s(o);");
18215 CHECK(try_catch.HasCaught());
18216 v8::String::Utf8Value value(try_catch.Exception());
18217 CHECK_EQ(0, strcmp(*value, "Hey!"));
18218}
18219
18220
Steve Blockd0582a62009-12-15 09:54:21 +000018221TEST(Regress528) {
18222 v8::V8::Initialize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018223 v8::Isolate* isolate = CcTest::isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018224 i::FLAG_retain_maps_for_n_gc = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018225 v8::HandleScope scope(isolate);
18226 v8::Local<Context> other_context;
Steve Blockd0582a62009-12-15 09:54:21 +000018227 int gc_count;
18228
18229 // Create a context used to keep the code from aging in the compilation
18230 // cache.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018231 other_context = Context::New(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018232
18233 // Context-dependent context data creates reference from the compilation
18234 // cache to the global object.
18235 const char* source_simple = "1";
Steve Blockd0582a62009-12-15 09:54:21 +000018236 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018237 v8::HandleScope scope(isolate);
18238 v8::Local<Context> context = Context::New(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018239
18240 context->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018241 Local<v8::String> obj = v8_str("");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018242 context->SetEmbedderData(0, obj);
Steve Blockd0582a62009-12-15 09:54:21 +000018243 CompileRun(source_simple);
18244 context->Exit();
18245 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018246 isolate->ContextDisposedNotification();
Steve Blockd0582a62009-12-15 09:54:21 +000018247 for (gc_count = 1; gc_count < 10; gc_count++) {
18248 other_context->Enter();
18249 CompileRun(source_simple);
18250 other_context->Exit();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018251 CcTest::heap()->CollectAllGarbage();
Steve Blockd0582a62009-12-15 09:54:21 +000018252 if (GetGlobalObjectsCount() == 1) break;
18253 }
18254 CHECK_GE(2, gc_count);
18255 CHECK_EQ(1, GetGlobalObjectsCount());
18256
18257 // Eval in a function creates reference from the compilation cache to the
18258 // global object.
18259 const char* source_eval = "function f(){eval('1')}; f()";
Steve Blockd0582a62009-12-15 09:54:21 +000018260 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018261 v8::HandleScope scope(isolate);
18262 v8::Local<Context> context = Context::New(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018263
18264 context->Enter();
18265 CompileRun(source_eval);
18266 context->Exit();
18267 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018268 isolate->ContextDisposedNotification();
Steve Blockd0582a62009-12-15 09:54:21 +000018269 for (gc_count = 1; gc_count < 10; gc_count++) {
18270 other_context->Enter();
18271 CompileRun(source_eval);
18272 other_context->Exit();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018273 CcTest::heap()->CollectAllGarbage();
Steve Blockd0582a62009-12-15 09:54:21 +000018274 if (GetGlobalObjectsCount() == 1) break;
18275 }
18276 CHECK_GE(2, gc_count);
18277 CHECK_EQ(1, GetGlobalObjectsCount());
18278
18279 // Looking up the line number for an exception creates reference from the
18280 // compilation cache to the global object.
18281 const char* source_exception = "function f(){throw 1;} f()";
Steve Blockd0582a62009-12-15 09:54:21 +000018282 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018283 v8::HandleScope scope(isolate);
18284 v8::Local<Context> context = Context::New(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018285
18286 context->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018287 v8::TryCatch try_catch(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018288 CompileRun(source_exception);
18289 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018290 v8::Local<v8::Message> message = try_catch.Message();
Steve Blockd0582a62009-12-15 09:54:21 +000018291 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018292 CHECK_EQ(1, message->GetLineNumber(context).FromJust());
Steve Blockd0582a62009-12-15 09:54:21 +000018293 context->Exit();
18294 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018295 isolate->ContextDisposedNotification();
Steve Blockd0582a62009-12-15 09:54:21 +000018296 for (gc_count = 1; gc_count < 10; gc_count++) {
18297 other_context->Enter();
18298 CompileRun(source_exception);
18299 other_context->Exit();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018300 CcTest::heap()->CollectAllGarbage();
Steve Blockd0582a62009-12-15 09:54:21 +000018301 if (GetGlobalObjectsCount() == 1) break;
18302 }
18303 CHECK_GE(2, gc_count);
18304 CHECK_EQ(1, GetGlobalObjectsCount());
18305
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018306 isolate->ContextDisposedNotification();
Steve Block3ce2e202009-11-05 08:53:23 +000018307}
Andrei Popescu402d9372010-02-26 13:31:12 +000018308
18309
18310THREADED_TEST(ScriptOrigin) {
Andrei Popescu402d9372010-02-26 13:31:12 +000018311 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018312 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018313 v8::ScriptOrigin origin = v8::ScriptOrigin(
18314 v8_str("test"), v8::Integer::New(env->GetIsolate(), 1),
18315 v8::Integer::New(env->GetIsolate(), 1), v8::True(env->GetIsolate()),
18316 v8::Local<v8::Integer>(), v8::True(env->GetIsolate()),
18317 v8_str("http://sourceMapUrl"), v8::True(env->GetIsolate()));
18318 v8::Local<v8::String> script = v8_str("function f() {}\n\nfunction g() {}");
18319 v8::Script::Compile(env.local(), script, &origin)
18320 .ToLocalChecked()
18321 ->Run(env.local())
18322 .ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000018323 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018324 env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
Andrei Popescu402d9372010-02-26 13:31:12 +000018325 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018326 env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
Andrei Popescu402d9372010-02-26 13:31:12 +000018327
18328 v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018329 CHECK_EQ(0, strcmp("test",
18330 *v8::String::Utf8Value(script_origin_f.ResourceName())));
18331 CHECK_EQ(
18332 1,
18333 script_origin_f.ResourceLineOffset()->Int32Value(env.local()).FromJust());
18334 CHECK(script_origin_f.Options().IsSharedCrossOrigin());
18335 CHECK(script_origin_f.Options().IsEmbedderDebugScript());
18336 CHECK(script_origin_f.Options().IsOpaque());
18337 printf("is name = %d\n", script_origin_f.SourceMapUrl()->IsUndefined());
18338
18339 CHECK_EQ(0, strcmp("http://sourceMapUrl",
18340 *v8::String::Utf8Value(script_origin_f.SourceMapUrl())));
Andrei Popescu402d9372010-02-26 13:31:12 +000018341
18342 v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018343 CHECK_EQ(0, strcmp("test",
18344 *v8::String::Utf8Value(script_origin_g.ResourceName())));
18345 CHECK_EQ(
18346 1,
18347 script_origin_g.ResourceLineOffset()->Int32Value(env.local()).FromJust());
18348 CHECK(script_origin_g.Options().IsSharedCrossOrigin());
18349 CHECK(script_origin_g.Options().IsEmbedderDebugScript());
18350 CHECK(script_origin_g.Options().IsOpaque());
18351 CHECK_EQ(0, strcmp("http://sourceMapUrl",
18352 *v8::String::Utf8Value(script_origin_g.SourceMapUrl())));
Andrei Popescu402d9372010-02-26 13:31:12 +000018353}
18354
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018355
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018356THREADED_TEST(FunctionGetInferredName) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018357 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018358 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018359 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
18360 v8::Local<v8::String> script =
18361 v8_str("var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
18362 v8::Script::Compile(env.local(), script, &origin)
18363 .ToLocalChecked()
18364 ->Run(env.local())
18365 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018366 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018367 env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
18368 CHECK_EQ(0,
18369 strcmp("foo.bar.baz", *v8::String::Utf8Value(f->GetInferredName())));
18370}
18371
18372
18373THREADED_TEST(FunctionGetDebugName) {
Ben Murdochda12d292016-06-02 14:46:10 +010018374 i::FLAG_harmony_function_name = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018375 LocalContext env;
18376 v8::HandleScope scope(env->GetIsolate());
18377 const char* code =
18378 "var error = false;"
18379 "function a() { this.x = 1; };"
18380 "a.displayName = 'display_a';"
18381 "var b = (function() {"
18382 " var f = function() { this.x = 2; };"
18383 " f.displayName = 'display_b';"
18384 " return f;"
18385 "})();"
18386 "var c = function() {};"
18387 "c.__defineGetter__('displayName', function() {"
18388 " error = true;"
18389 " throw new Error();"
18390 "});"
18391 "function d() {};"
18392 "d.__defineGetter__('displayName', function() {"
18393 " error = true;"
18394 " return 'wrong_display_name';"
18395 "});"
18396 "function e() {};"
18397 "e.displayName = 'wrong_display_name';"
18398 "e.__defineSetter__('displayName', function() {"
18399 " error = true;"
18400 " throw new Error();"
18401 "});"
18402 "function f() {};"
18403 "f.displayName = { 'foo': 6, toString: function() {"
18404 " error = true;"
18405 " return 'wrong_display_name';"
18406 "}};"
18407 "var g = function() {"
18408 " arguments.callee.displayName = 'set_in_runtime';"
18409 "}; g();"
18410 "var h = function() {};"
18411 "h.displayName = 'displayName';"
18412 "Object.defineProperty(h, 'name', { value: 'function.name' });"
18413 "var i = function() {};"
18414 "i.displayName = 239;"
18415 "Object.defineProperty(i, 'name', { value: 'function.name' });"
18416 "var j = function() {};"
18417 "Object.defineProperty(j, 'name', { value: 'function.name' });"
Ben Murdochda12d292016-06-02 14:46:10 +010018418 "var foo = { bar : { baz : (0, function() {})}}; var k = foo.bar.baz;"
18419 "var foo = { bar : { baz : function() {} }}; var l = foo.bar.baz;";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018420 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
18421 v8::Script::Compile(env.local(), v8_str(code), &origin)
18422 .ToLocalChecked()
18423 ->Run(env.local())
18424 .ToLocalChecked();
18425 v8::Local<v8::Value> error =
18426 env->Global()->Get(env.local(), v8_str("error")).ToLocalChecked();
18427 CHECK_EQ(false, error->BooleanValue(env.local()).FromJust());
18428 const char* functions[] = {"a", "display_a",
18429 "b", "display_b",
18430 "c", "c",
18431 "d", "d",
18432 "e", "e",
18433 "f", "f",
18434 "g", "set_in_runtime",
18435 "h", "displayName",
18436 "i", "function.name",
18437 "j", "function.name",
Ben Murdochda12d292016-06-02 14:46:10 +010018438 "k", "foo.bar.baz",
18439 "l", "baz"};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018440 for (size_t i = 0; i < sizeof(functions) / sizeof(functions[0]) / 2; ++i) {
18441 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
18442 env->Global()
18443 ->Get(env.local(),
18444 v8::String::NewFromUtf8(env->GetIsolate(), functions[i * 2],
18445 v8::NewStringType::kNormal)
18446 .ToLocalChecked())
18447 .ToLocalChecked());
18448 CHECK_EQ(0, strcmp(functions[i * 2 + 1],
18449 *v8::String::Utf8Value(f->GetDebugName())));
18450 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018451}
Andrei Popescu402d9372010-02-26 13:31:12 +000018452
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018453
18454THREADED_TEST(FunctionGetDisplayName) {
Andrei Popescu402d9372010-02-26 13:31:12 +000018455 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018456 v8::HandleScope scope(env->GetIsolate());
18457 const char* code = "var error = false;"
18458 "function a() { this.x = 1; };"
18459 "a.displayName = 'display_a';"
18460 "var b = (function() {"
18461 " var f = function() { this.x = 2; };"
18462 " f.displayName = 'display_b';"
18463 " return f;"
18464 "})();"
18465 "var c = function() {};"
18466 "c.__defineGetter__('displayName', function() {"
18467 " error = true;"
18468 " throw new Error();"
18469 "});"
18470 "function d() {};"
18471 "d.__defineGetter__('displayName', function() {"
18472 " error = true;"
18473 " return 'wrong_display_name';"
18474 "});"
18475 "function e() {};"
18476 "e.displayName = 'wrong_display_name';"
18477 "e.__defineSetter__('displayName', function() {"
18478 " error = true;"
18479 " throw new Error();"
18480 "});"
18481 "function f() {};"
18482 "f.displayName = { 'foo': 6, toString: function() {"
18483 " error = true;"
18484 " return 'wrong_display_name';"
18485 "}};"
18486 "var g = function() {"
18487 " arguments.callee.displayName = 'set_in_runtime';"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018488 "}; g();";
18489 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
18490 v8::Script::Compile(env.local(), v8_str(code), &origin)
18491 .ToLocalChecked()
18492 ->Run(env.local())
18493 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018494 v8::Local<v8::Value> error =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018495 env->Global()->Get(env.local(), v8_str("error")).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018496 v8::Local<v8::Function> a = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018497 env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018498 v8::Local<v8::Function> b = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018499 env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018500 v8::Local<v8::Function> c = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018501 env->Global()->Get(env.local(), v8_str("c")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018502 v8::Local<v8::Function> d = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018503 env->Global()->Get(env.local(), v8_str("d")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018504 v8::Local<v8::Function> e = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018505 env->Global()->Get(env.local(), v8_str("e")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018506 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018507 env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018508 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018509 env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
18510 CHECK_EQ(false, error->BooleanValue(env.local()).FromJust());
18511 CHECK_EQ(0, strcmp("display_a", *v8::String::Utf8Value(a->GetDisplayName())));
18512 CHECK_EQ(0, strcmp("display_b", *v8::String::Utf8Value(b->GetDisplayName())));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018513 CHECK(c->GetDisplayName()->IsUndefined());
18514 CHECK(d->GetDisplayName()->IsUndefined());
18515 CHECK(e->GetDisplayName()->IsUndefined());
18516 CHECK(f->GetDisplayName()->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018517 CHECK_EQ(
18518 0, strcmp("set_in_runtime", *v8::String::Utf8Value(g->GetDisplayName())));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018519}
18520
18521
18522THREADED_TEST(ScriptLineNumber) {
18523 LocalContext env;
18524 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018525 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
18526 v8::Local<v8::String> script = v8_str("function f() {}\n\nfunction g() {}");
18527 v8::Script::Compile(env.local(), script, &origin)
18528 .ToLocalChecked()
18529 ->Run(env.local())
18530 .ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000018531 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018532 env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
Andrei Popescu402d9372010-02-26 13:31:12 +000018533 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018534 env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
Andrei Popescu402d9372010-02-26 13:31:12 +000018535 CHECK_EQ(0, f->GetScriptLineNumber());
18536 CHECK_EQ(2, g->GetScriptLineNumber());
18537}
18538
18539
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018540THREADED_TEST(ScriptColumnNumber) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018541 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018542 v8::Isolate* isolate = env->GetIsolate();
18543 v8::HandleScope scope(isolate);
18544 v8::ScriptOrigin origin =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018545 v8::ScriptOrigin(v8_str("test"), v8::Integer::New(isolate, 3),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018546 v8::Integer::New(isolate, 2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018547 v8::Local<v8::String> script =
18548 v8_str("function foo() {}\n\n function bar() {}");
18549 v8::Script::Compile(env.local(), script, &origin)
18550 .ToLocalChecked()
18551 ->Run(env.local())
18552 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018553 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018554 env->Global()->Get(env.local(), v8_str("foo")).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018555 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018556 env->Global()->Get(env.local(), v8_str("bar")).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018557 CHECK_EQ(14, foo->GetScriptColumnNumber());
18558 CHECK_EQ(17, bar->GetScriptColumnNumber());
18559}
18560
18561
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018562THREADED_TEST(FunctionIsBuiltin) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018563 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018564 v8::Isolate* isolate = env->GetIsolate();
18565 v8::HandleScope scope(isolate);
18566 v8::Local<v8::Function> f;
18567 f = v8::Local<v8::Function>::Cast(CompileRun("Math.floor"));
18568 CHECK(f->IsBuiltin());
18569 f = v8::Local<v8::Function>::Cast(CompileRun("Object"));
18570 CHECK(f->IsBuiltin());
18571 f = v8::Local<v8::Function>::Cast(CompileRun("Object.__defineSetter__"));
18572 CHECK(f->IsBuiltin());
18573 f = v8::Local<v8::Function>::Cast(CompileRun("Array.prototype.toString"));
18574 CHECK(f->IsBuiltin());
18575 f = v8::Local<v8::Function>::Cast(CompileRun("function a() {}; a;"));
18576 CHECK(!f->IsBuiltin());
18577}
18578
18579
18580THREADED_TEST(FunctionGetScriptId) {
18581 LocalContext env;
18582 v8::Isolate* isolate = env->GetIsolate();
18583 v8::HandleScope scope(isolate);
18584 v8::ScriptOrigin origin =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018585 v8::ScriptOrigin(v8_str("test"), v8::Integer::New(isolate, 3),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018586 v8::Integer::New(isolate, 2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018587 v8::Local<v8::String> scriptSource =
18588 v8_str("function foo() {}\n\n function bar() {}");
18589 v8::Local<v8::Script> script(
18590 v8::Script::Compile(env.local(), scriptSource, &origin).ToLocalChecked());
18591 script->Run(env.local()).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018592 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018593 env->Global()->Get(env.local(), v8_str("foo")).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018594 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018595 env->Global()->Get(env.local(), v8_str("bar")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018596 CHECK_EQ(script->GetUnboundScript()->GetId(), foo->ScriptId());
18597 CHECK_EQ(script->GetUnboundScript()->GetId(), bar->ScriptId());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018598}
18599
18600
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018601THREADED_TEST(FunctionGetBoundFunction) {
18602 LocalContext env;
18603 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018604 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
18605 v8::Local<v8::String> script = v8_str(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018606 "var a = new Object();\n"
18607 "a.x = 1;\n"
18608 "function f () { return this.x };\n"
18609 "var g = f.bind(a);\n"
18610 "var b = g();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018611 v8::Script::Compile(env.local(), script, &origin)
18612 .ToLocalChecked()
18613 ->Run(env.local())
18614 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018615 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018616 env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018617 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018618 env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018619 CHECK(g->GetBoundFunction()->IsFunction());
18620 Local<v8::Function> original_function = Local<v8::Function>::Cast(
18621 g->GetBoundFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018622 CHECK(f->GetName()
18623 ->Equals(env.local(), original_function->GetName())
18624 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018625 CHECK_EQ(f->GetScriptLineNumber(), original_function->GetScriptLineNumber());
18626 CHECK_EQ(f->GetScriptColumnNumber(),
18627 original_function->GetScriptColumnNumber());
Andrei Popescu402d9372010-02-26 13:31:12 +000018628}
18629
18630
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018631static void GetterWhichReturns42(
18632 Local<String> name,
18633 const v8::PropertyCallbackInfo<v8::Value>& info) {
18634 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18635 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
18636 info.GetReturnValue().Set(v8_num(42));
18637}
18638
18639
18640static void SetterWhichSetsYOnThisTo23(
18641 Local<String> name,
18642 Local<Value> value,
18643 const v8::PropertyCallbackInfo<void>& info) {
18644 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18645 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018646 Local<Object>::Cast(info.This())
18647 ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
18648 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018649}
18650
18651
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018652void FooGetInterceptor(Local<Name> name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018653 const v8::PropertyCallbackInfo<v8::Value>& info) {
18654 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18655 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018656 if (!name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
18657 .FromJust()) {
18658 return;
18659 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018660 info.GetReturnValue().Set(v8_num(42));
18661}
18662
18663
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018664void FooSetInterceptor(Local<Name> name, Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018665 const v8::PropertyCallbackInfo<v8::Value>& info) {
18666 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18667 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018668 if (!name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
18669 .FromJust()) {
18670 return;
18671 }
18672 Local<Object>::Cast(info.This())
18673 ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
18674 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018675 info.GetReturnValue().Set(v8_num(23));
Andrei Popescu402d9372010-02-26 13:31:12 +000018676}
18677
18678
Steve Block6ded16b2010-05-10 14:33:55 +010018679TEST(SetterOnConstructorPrototype) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018680 v8::Isolate* isolate = CcTest::isolate();
18681 v8::HandleScope scope(isolate);
18682 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
18683 templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
Andrei Popescu402d9372010-02-26 13:31:12 +000018684 SetterWhichSetsYOnThisTo23);
18685 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018686 CHECK(context->Global()
18687 ->Set(context.local(), v8_str("P"),
18688 templ->NewInstance(context.local()).ToLocalChecked())
18689 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018690 CompileRun("function C1() {"
18691 " this.x = 23;"
18692 "};"
18693 "C1.prototype = P;"
18694 "function C2() {"
18695 " this.x = 23"
18696 "};"
18697 "C2.prototype = { };"
18698 "C2.prototype.__proto__ = P;");
18699
18700 v8::Local<v8::Script> script;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018701 script = v8_compile("new C1();");
Andrei Popescu402d9372010-02-26 13:31:12 +000018702 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018703 v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
18704 script->Run(context.local()).ToLocalChecked());
18705 CHECK_EQ(42, c1->Get(context.local(), v8_str("x"))
18706 .ToLocalChecked()
18707 ->Int32Value(context.local())
18708 .FromJust());
18709 CHECK_EQ(23, c1->Get(context.local(), v8_str("y"))
18710 .ToLocalChecked()
18711 ->Int32Value(context.local())
18712 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018713 }
18714
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018715 script = v8_compile("new C2();");
Andrei Popescu402d9372010-02-26 13:31:12 +000018716 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018717 v8::Local<v8::Object> c2 = v8::Local<v8::Object>::Cast(
18718 script->Run(context.local()).ToLocalChecked());
18719 CHECK_EQ(42, c2->Get(context.local(), v8_str("x"))
18720 .ToLocalChecked()
18721 ->Int32Value(context.local())
18722 .FromJust());
18723 CHECK_EQ(23, c2->Get(context.local(), v8_str("y"))
18724 .ToLocalChecked()
18725 ->Int32Value(context.local())
18726 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018727 }
18728}
18729
18730
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018731static void NamedPropertyGetterWhichReturns42(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018732 Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018733 info.GetReturnValue().Set(v8_num(42));
Andrei Popescu402d9372010-02-26 13:31:12 +000018734}
18735
18736
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018737static void NamedPropertySetterWhichSetsYOnThisTo23(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018738 Local<Name> name, Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018739 const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018740 if (name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("x"))
18741 .FromJust()) {
18742 Local<Object>::Cast(info.This())
18743 ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
18744 .FromJust();
Andrei Popescu402d9372010-02-26 13:31:12 +000018745 }
Andrei Popescu402d9372010-02-26 13:31:12 +000018746}
18747
18748
18749THREADED_TEST(InterceptorOnConstructorPrototype) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018750 v8::Isolate* isolate = CcTest::isolate();
18751 v8::HandleScope scope(isolate);
18752 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018753 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
18754 NamedPropertyGetterWhichReturns42,
18755 NamedPropertySetterWhichSetsYOnThisTo23));
Andrei Popescu402d9372010-02-26 13:31:12 +000018756 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018757 CHECK(context->Global()
18758 ->Set(context.local(), v8_str("P"),
18759 templ->NewInstance(context.local()).ToLocalChecked())
18760 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018761 CompileRun("function C1() {"
18762 " this.x = 23;"
18763 "};"
18764 "C1.prototype = P;"
18765 "function C2() {"
18766 " this.x = 23"
18767 "};"
18768 "C2.prototype = { };"
18769 "C2.prototype.__proto__ = P;");
18770
18771 v8::Local<v8::Script> script;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018772 script = v8_compile("new C1();");
Andrei Popescu402d9372010-02-26 13:31:12 +000018773 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018774 v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
18775 script->Run(context.local()).ToLocalChecked());
18776 CHECK_EQ(23, c1->Get(context.local(), v8_str("x"))
18777 .ToLocalChecked()
18778 ->Int32Value(context.local())
18779 .FromJust());
18780 CHECK_EQ(42, c1->Get(context.local(), v8_str("y"))
18781 .ToLocalChecked()
18782 ->Int32Value(context.local())
18783 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018784 }
18785
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018786 script = v8_compile("new C2();");
Andrei Popescu402d9372010-02-26 13:31:12 +000018787 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018788 v8::Local<v8::Object> c2 = v8::Local<v8::Object>::Cast(
18789 script->Run(context.local()).ToLocalChecked());
18790 CHECK_EQ(23, c2->Get(context.local(), v8_str("x"))
18791 .ToLocalChecked()
18792 ->Int32Value(context.local())
18793 .FromJust());
18794 CHECK_EQ(42, c2->Get(context.local(), v8_str("y"))
18795 .ToLocalChecked()
18796 ->Int32Value(context.local())
18797 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018798 }
18799}
Steve Block6ded16b2010-05-10 14:33:55 +010018800
18801
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018802TEST(Regress618) {
Steve Block6ded16b2010-05-10 14:33:55 +010018803 const char* source = "function C1() {"
18804 " this.x = 23;"
18805 "};"
18806 "C1.prototype = P;";
18807
Steve Block6ded16b2010-05-10 14:33:55 +010018808 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018809 v8::Isolate* isolate = context->GetIsolate();
18810 v8::HandleScope scope(isolate);
Steve Block6ded16b2010-05-10 14:33:55 +010018811 v8::Local<v8::Script> script;
18812
18813 // Use a simple object as prototype.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018814 v8::Local<v8::Object> prototype = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018815 prototype->Set(context.local(), v8_str("y"), v8_num(42)).FromJust();
18816 CHECK(context->Global()
18817 ->Set(context.local(), v8_str("P"), prototype)
18818 .FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +010018819
18820 // This compile will add the code to the compilation cache.
18821 CompileRun(source);
18822
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018823 script = v8_compile("new C1();");
Kristian Monsen0d5e1162010-09-30 15:31:59 +010018824 // Allow enough iterations for the inobject slack tracking logic
18825 // to finalize instance size and install the fast construct stub.
18826 for (int i = 0; i < 256; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018827 v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
18828 script->Run(context.local()).ToLocalChecked());
18829 CHECK_EQ(23, c1->Get(context.local(), v8_str("x"))
18830 .ToLocalChecked()
18831 ->Int32Value(context.local())
18832 .FromJust());
18833 CHECK_EQ(42, c1->Get(context.local(), v8_str("y"))
18834 .ToLocalChecked()
18835 ->Int32Value(context.local())
18836 .FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +010018837 }
18838
18839 // Use an API object with accessors as prototype.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018840 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
18841 templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
Steve Block6ded16b2010-05-10 14:33:55 +010018842 SetterWhichSetsYOnThisTo23);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018843 CHECK(context->Global()
18844 ->Set(context.local(), v8_str("P"),
18845 templ->NewInstance(context.local()).ToLocalChecked())
18846 .FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +010018847
18848 // This compile will get the code from the compilation cache.
18849 CompileRun(source);
18850
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018851 script = v8_compile("new C1();");
Steve Block6ded16b2010-05-10 14:33:55 +010018852 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018853 v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
18854 script->Run(context.local()).ToLocalChecked());
18855 CHECK_EQ(42, c1->Get(context.local(), v8_str("x"))
18856 .ToLocalChecked()
18857 ->Int32Value(context.local())
18858 .FromJust());
18859 CHECK_EQ(23, c1->Get(context.local(), v8_str("y"))
18860 .ToLocalChecked()
18861 ->Int32Value(context.local())
18862 .FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +010018863 }
18864}
18865
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018866v8::Isolate* gc_callbacks_isolate = NULL;
Steve Block6ded16b2010-05-10 14:33:55 +010018867int prologue_call_count = 0;
18868int epilogue_call_count = 0;
18869int prologue_call_count_second = 0;
18870int epilogue_call_count_second = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018871int prologue_call_count_alloc = 0;
18872int epilogue_call_count_alloc = 0;
Steve Block6ded16b2010-05-10 14:33:55 +010018873
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018874void PrologueCallback(v8::Isolate* isolate,
18875 v8::GCType,
18876 v8::GCCallbackFlags flags) {
18877 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18878 CHECK_EQ(gc_callbacks_isolate, isolate);
18879 ++prologue_call_count;
18880}
18881
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018882void EpilogueCallback(v8::Isolate* isolate,
18883 v8::GCType,
18884 v8::GCCallbackFlags flags) {
18885 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18886 CHECK_EQ(gc_callbacks_isolate, isolate);
18887 ++epilogue_call_count;
18888}
18889
18890
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018891void PrologueCallbackSecond(v8::Isolate* isolate,
18892 v8::GCType,
18893 v8::GCCallbackFlags flags) {
18894 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18895 CHECK_EQ(gc_callbacks_isolate, isolate);
18896 ++prologue_call_count_second;
18897}
18898
18899
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018900void EpilogueCallbackSecond(v8::Isolate* isolate,
18901 v8::GCType,
18902 v8::GCCallbackFlags flags) {
18903 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18904 CHECK_EQ(gc_callbacks_isolate, isolate);
18905 ++epilogue_call_count_second;
18906}
18907
18908
18909void PrologueCallbackAlloc(v8::Isolate* isolate,
18910 v8::GCType,
18911 v8::GCCallbackFlags flags) {
18912 v8::HandleScope scope(isolate);
18913
18914 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18915 CHECK_EQ(gc_callbacks_isolate, isolate);
18916 ++prologue_call_count_alloc;
18917
18918 // Simulate full heap to see if we will reenter this callback
18919 SimulateFullSpace(CcTest::heap()->new_space());
18920
18921 Local<Object> obj = Object::New(isolate);
18922 CHECK(!obj.IsEmpty());
18923
18924 CcTest::heap()->CollectAllGarbage(
18925 i::Heap::kAbortIncrementalMarkingMask);
18926}
18927
18928
18929void EpilogueCallbackAlloc(v8::Isolate* isolate,
18930 v8::GCType,
18931 v8::GCCallbackFlags flags) {
18932 v8::HandleScope scope(isolate);
18933
18934 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18935 CHECK_EQ(gc_callbacks_isolate, isolate);
18936 ++epilogue_call_count_alloc;
18937
18938 // Simulate full heap to see if we will reenter this callback
18939 SimulateFullSpace(CcTest::heap()->new_space());
18940
18941 Local<Object> obj = Object::New(isolate);
18942 CHECK(!obj.IsEmpty());
18943
18944 CcTest::heap()->CollectAllGarbage(
18945 i::Heap::kAbortIncrementalMarkingMask);
18946}
18947
18948
18949TEST(GCCallbacksOld) {
Steve Block6ded16b2010-05-10 14:33:55 +010018950 LocalContext context;
18951
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018952 gc_callbacks_isolate = context->GetIsolate();
18953
18954 context->GetIsolate()->AddGCPrologueCallback(PrologueCallback);
18955 context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallback);
Steve Block6ded16b2010-05-10 14:33:55 +010018956 CHECK_EQ(0, prologue_call_count);
18957 CHECK_EQ(0, epilogue_call_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018958 CcTest::heap()->CollectAllGarbage();
Steve Block6ded16b2010-05-10 14:33:55 +010018959 CHECK_EQ(1, prologue_call_count);
18960 CHECK_EQ(1, epilogue_call_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018961 context->GetIsolate()->AddGCPrologueCallback(PrologueCallbackSecond);
18962 context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallbackSecond);
18963 CcTest::heap()->CollectAllGarbage();
Steve Block6ded16b2010-05-10 14:33:55 +010018964 CHECK_EQ(2, prologue_call_count);
18965 CHECK_EQ(2, epilogue_call_count);
18966 CHECK_EQ(1, prologue_call_count_second);
18967 CHECK_EQ(1, epilogue_call_count_second);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018968 context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallback);
18969 context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallback);
18970 CcTest::heap()->CollectAllGarbage();
Steve Block6ded16b2010-05-10 14:33:55 +010018971 CHECK_EQ(2, prologue_call_count);
18972 CHECK_EQ(2, epilogue_call_count);
18973 CHECK_EQ(2, prologue_call_count_second);
18974 CHECK_EQ(2, epilogue_call_count_second);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018975 context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallbackSecond);
18976 context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
18977 CcTest::heap()->CollectAllGarbage();
Steve Block6ded16b2010-05-10 14:33:55 +010018978 CHECK_EQ(2, prologue_call_count);
18979 CHECK_EQ(2, epilogue_call_count);
18980 CHECK_EQ(2, prologue_call_count_second);
18981 CHECK_EQ(2, epilogue_call_count_second);
18982}
Kristian Monsen25f61362010-05-21 11:50:48 +010018983
18984
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018985TEST(GCCallbacks) {
18986 LocalContext context;
18987 v8::Isolate* isolate = context->GetIsolate();
18988 gc_callbacks_isolate = isolate;
18989 isolate->AddGCPrologueCallback(PrologueCallback);
18990 isolate->AddGCEpilogueCallback(EpilogueCallback);
18991 CHECK_EQ(0, prologue_call_count);
18992 CHECK_EQ(0, epilogue_call_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018993 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018994 CHECK_EQ(1, prologue_call_count);
18995 CHECK_EQ(1, epilogue_call_count);
18996 isolate->AddGCPrologueCallback(PrologueCallbackSecond);
18997 isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018998 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018999 CHECK_EQ(2, prologue_call_count);
19000 CHECK_EQ(2, epilogue_call_count);
19001 CHECK_EQ(1, prologue_call_count_second);
19002 CHECK_EQ(1, epilogue_call_count_second);
19003 isolate->RemoveGCPrologueCallback(PrologueCallback);
19004 isolate->RemoveGCEpilogueCallback(EpilogueCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019005 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019006 CHECK_EQ(2, prologue_call_count);
19007 CHECK_EQ(2, epilogue_call_count);
19008 CHECK_EQ(2, prologue_call_count_second);
19009 CHECK_EQ(2, epilogue_call_count_second);
19010 isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
19011 isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019012 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019013 CHECK_EQ(2, prologue_call_count);
19014 CHECK_EQ(2, epilogue_call_count);
19015 CHECK_EQ(2, prologue_call_count_second);
19016 CHECK_EQ(2, epilogue_call_count_second);
19017
19018 CHECK_EQ(0, prologue_call_count_alloc);
19019 CHECK_EQ(0, epilogue_call_count_alloc);
19020 isolate->AddGCPrologueCallback(PrologueCallbackAlloc);
19021 isolate->AddGCEpilogueCallback(EpilogueCallbackAlloc);
19022 CcTest::heap()->CollectAllGarbage(
19023 i::Heap::kAbortIncrementalMarkingMask);
19024 CHECK_EQ(1, prologue_call_count_alloc);
19025 CHECK_EQ(1, epilogue_call_count_alloc);
19026 isolate->RemoveGCPrologueCallback(PrologueCallbackAlloc);
19027 isolate->RemoveGCEpilogueCallback(EpilogueCallbackAlloc);
19028}
19029
19030
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019031THREADED_TEST(TwoByteStringInOneByteCons) {
Steve Block8defd9f2010-07-08 12:39:36 +010019032 // See Chromium issue 47824.
Steve Block8defd9f2010-07-08 12:39:36 +010019033 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019034 v8::HandleScope scope(context->GetIsolate());
19035
Steve Block8defd9f2010-07-08 12:39:36 +010019036 const char* init_code =
19037 "var str1 = 'abelspendabel';"
19038 "var str2 = str1 + str1 + str1;"
19039 "str2;";
19040 Local<Value> result = CompileRun(init_code);
19041
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019042 Local<Value> indexof = CompileRun("str2.indexOf('els')");
19043 Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
19044
Steve Block8defd9f2010-07-08 12:39:36 +010019045 CHECK(result->IsString());
19046 i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
19047 int length = string->length();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019048 CHECK(string->IsOneByteRepresentation());
Steve Block8defd9f2010-07-08 12:39:36 +010019049
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019050 i::Handle<i::String> flat_string = i::String::Flatten(string);
Steve Block8defd9f2010-07-08 12:39:36 +010019051
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019052 CHECK(string->IsOneByteRepresentation());
19053 CHECK(flat_string->IsOneByteRepresentation());
Steve Block8defd9f2010-07-08 12:39:36 +010019054
19055 // Create external resource.
19056 uint16_t* uc16_buffer = new uint16_t[length + 1];
19057
19058 i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
19059 uc16_buffer[length] = 0;
19060
19061 TestResource resource(uc16_buffer);
19062
19063 flat_string->MakeExternal(&resource);
19064
19065 CHECK(flat_string->IsTwoByteRepresentation());
19066
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019067 // If the cons string has been short-circuited, skip the following checks.
19068 if (!string.is_identical_to(flat_string)) {
19069 // At this point, we should have a Cons string which is flat and one-byte,
19070 // with a first half that is a two-byte string (although it only contains
19071 // one-byte characters). This is a valid sequence of steps, and it can
19072 // happen in real pages.
19073 CHECK(string->IsOneByteRepresentation());
19074 i::ConsString* cons = i::ConsString::cast(*string);
19075 CHECK_EQ(0, cons->second()->length());
19076 CHECK(cons->first()->IsTwoByteRepresentation());
19077 }
Steve Block8defd9f2010-07-08 12:39:36 +010019078
19079 // Check that some string operations work.
19080
19081 // Atom RegExp.
19082 Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019083 CHECK_EQ(6, reresult->Int32Value(context.local()).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +010019084
19085 // Nonatom RegExp.
19086 reresult = CompileRun("str2.match(/abe./g).length;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019087 CHECK_EQ(6, reresult->Int32Value(context.local()).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +010019088
19089 reresult = CompileRun("str2.search(/bel/g);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019090 CHECK_EQ(1, reresult->Int32Value(context.local()).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +010019091
19092 reresult = CompileRun("str2.search(/be./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 ExpectTrue("/bel/g.test(str2);");
19096
19097 ExpectTrue("/be./g.test(str2);");
19098
19099 reresult = CompileRun("/bel/g.exec(str2);");
19100 CHECK(!reresult->IsNull());
19101
19102 reresult = CompileRun("/be./g.exec(str2);");
19103 CHECK(!reresult->IsNull());
19104
19105 ExpectString("str2.substring(2, 10);", "elspenda");
19106
19107 ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
19108
19109 ExpectString("str2.charAt(2);", "e");
19110
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019111 ExpectObject("str2.indexOf('els');", indexof);
19112
19113 ExpectObject("str2.lastIndexOf('dab');", lastindexof);
19114
Steve Block8defd9f2010-07-08 12:39:36 +010019115 reresult = CompileRun("str2.charCodeAt(2);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019116 CHECK_EQ(static_cast<int32_t>('e'),
19117 reresult->Int32Value(context.local()).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +010019118}
Iain Merrick75681382010-08-19 15:07:18 +010019119
19120
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019121TEST(ContainsOnlyOneByte) {
19122 v8::V8::Initialize();
19123 v8::Isolate* isolate = CcTest::isolate();
19124 v8::HandleScope scope(isolate);
19125 // Make a buffer long enough that it won't automatically be converted.
19126 const int length = 512;
19127 // Ensure word aligned assignment.
19128 const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019129 v8::base::SmartArrayPointer<uintptr_t> aligned_contents(
19130 new uintptr_t[aligned_length]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019131 uint16_t* string_contents =
19132 reinterpret_cast<uint16_t*>(aligned_contents.get());
19133 // Set to contain only one byte.
19134 for (int i = 0; i < length-1; i++) {
19135 string_contents[i] = 0x41;
19136 }
19137 string_contents[length-1] = 0;
19138 // Simple case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019139 Local<String> string =
19140 String::NewExternalTwoByte(isolate,
19141 new TestResource(string_contents, NULL, false))
19142 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019143 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
19144 // Counter example.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019145 string = String::NewFromTwoByte(isolate, string_contents,
19146 v8::NewStringType::kNormal)
19147 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019148 CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
19149 // Test left right and balanced cons strings.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019150 Local<String> base = v8_str("a");
19151 Local<String> left = base;
19152 Local<String> right = base;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019153 for (int i = 0; i < 1000; i++) {
19154 left = String::Concat(base, left);
19155 right = String::Concat(right, base);
19156 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019157 Local<String> balanced = String::Concat(left, base);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019158 balanced = String::Concat(balanced, right);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019159 Local<String> cons_strings[] = {left, balanced, right};
19160 Local<String> two_byte =
19161 String::NewExternalTwoByte(isolate,
19162 new TestResource(string_contents, NULL, false))
19163 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019164 USE(two_byte); USE(cons_strings);
19165 for (size_t i = 0; i < arraysize(cons_strings); i++) {
19166 // Base assumptions.
19167 string = cons_strings[i];
19168 CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
19169 // Test left and right concatentation.
19170 string = String::Concat(two_byte, cons_strings[i]);
19171 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
19172 string = String::Concat(cons_strings[i], two_byte);
19173 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
19174 }
19175 // Set bits in different positions
19176 // for strings of different lengths and alignments.
19177 for (int alignment = 0; alignment < 7; alignment++) {
19178 for (int size = 2; alignment + size < length; size *= 2) {
19179 int zero_offset = size + alignment;
19180 string_contents[zero_offset] = 0;
19181 for (int i = 0; i < size; i++) {
19182 int shift = 8 + (i % 7);
19183 string_contents[alignment + i] = 1 << shift;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019184 string = String::NewExternalTwoByte(
19185 isolate,
19186 new TestResource(string_contents + alignment, NULL, false))
19187 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019188 CHECK_EQ(size, string->Length());
19189 CHECK(!string->ContainsOnlyOneByte());
19190 string_contents[alignment + i] = 0x41;
19191 }
19192 string_contents[zero_offset] = 0x41;
19193 }
19194 }
19195}
19196
19197
Iain Merrick75681382010-08-19 15:07:18 +010019198// Failed access check callback that performs a GC on each invocation.
19199void FailedAccessCheckCallbackGC(Local<v8::Object> target,
19200 v8::AccessType type,
19201 Local<v8::Value> data) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019202 CcTest::heap()->CollectAllGarbage();
19203 CcTest::isolate()->ThrowException(
19204 v8::Exception::Error(v8_str("cross context")));
Iain Merrick75681382010-08-19 15:07:18 +010019205}
19206
19207
19208TEST(GCInFailedAccessCheckCallback) {
19209 // Install a failed access check callback that performs a GC on each
19210 // invocation. Then force the callback to be called from va
19211
19212 v8::V8::Initialize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019213 v8::Isolate* isolate = CcTest::isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019214
19215 isolate->SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
19216
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019217 v8::HandleScope scope(isolate);
Iain Merrick75681382010-08-19 15:07:18 +010019218
19219 // Create an ObjectTemplate for global objects and install access
19220 // check callbacks that will block access.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019221 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019222 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019223 global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Iain Merrick75681382010-08-19 15:07:18 +010019224
19225 // Create a context and set an x property on it's global object.
19226 LocalContext context0(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019227 CHECK(context0->Global()
19228 ->Set(context0.local(), v8_str("x"), v8_num(42))
19229 .FromJust());
19230 v8::Local<v8::Object> global0 = context0->Global();
Iain Merrick75681382010-08-19 15:07:18 +010019231
19232 // Create a context with a different security token so that the
19233 // failed access check callback will be called on each access.
19234 LocalContext context1(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019235 CHECK(context1->Global()
19236 ->Set(context1.local(), v8_str("other"), global0)
19237 .FromJust());
19238
19239 v8::TryCatch try_catch(isolate);
Iain Merrick75681382010-08-19 15:07:18 +010019240
19241 // Get property with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019242 CHECK(CompileRun("other.x").IsEmpty());
19243 CHECK(try_catch.HasCaught());
19244 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019245
19246 // Get element with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019247 CHECK(CompileRun("other[0]").IsEmpty());
19248 CHECK(try_catch.HasCaught());
19249 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019250
19251 // Set property with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019252 CHECK(CompileRun("other.x = new Object()").IsEmpty());
19253 CHECK(try_catch.HasCaught());
19254 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019255
19256 // Set element with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019257 CHECK(CompileRun("other[0] = new Object()").IsEmpty());
19258 CHECK(try_catch.HasCaught());
19259 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019260
19261 // Get property attribute with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019262 CHECK(CompileRun("\'x\' in other").IsEmpty());
19263 CHECK(try_catch.HasCaught());
19264 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019265
19266 // Get property attribute for element with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019267 CHECK(CompileRun("0 in other").IsEmpty());
19268 CHECK(try_catch.HasCaught());
19269 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019270
19271 // Delete property.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019272 CHECK(CompileRun("delete other.x").IsEmpty());
19273 CHECK(try_catch.HasCaught());
19274 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019275
19276 // Delete element.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019277 CHECK(global0->Delete(context1.local(), 0).IsNothing());
19278 CHECK(try_catch.HasCaught());
19279 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019280
19281 // DefineAccessor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019282 CHECK(global0->SetAccessor(context1.local(), v8_str("x"), GetXValue, NULL,
19283 v8_str("x"))
19284 .IsNothing());
19285 CHECK(try_catch.HasCaught());
19286 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019287
19288 // Define JavaScript accessor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019289 CHECK(CompileRun(
19290 "Object.prototype.__defineGetter__.call("
19291 " other, \'x\', function() { return 42; })").IsEmpty());
19292 CHECK(try_catch.HasCaught());
19293 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019294
19295 // LookupAccessor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019296 CHECK(CompileRun(
19297 "Object.prototype.__lookupGetter__.call("
19298 " other, \'x\')").IsEmpty());
19299 CHECK(try_catch.HasCaught());
19300 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019301
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019302 // HasOwnElement.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019303 CHECK(CompileRun(
19304 "Object.prototype.hasOwnProperty.call("
19305 "other, \'0\')").IsEmpty());
19306 CHECK(try_catch.HasCaught());
19307 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019308
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019309 CHECK(global0->HasRealIndexedProperty(context1.local(), 0).IsNothing());
19310 CHECK(try_catch.HasCaught());
19311 try_catch.Reset();
19312
19313 CHECK(
19314 global0->HasRealNamedProperty(context1.local(), v8_str("x")).IsNothing());
19315 CHECK(try_catch.HasCaught());
19316 try_catch.Reset();
19317
19318 CHECK(global0->HasRealNamedCallbackProperty(context1.local(), v8_str("x"))
19319 .IsNothing());
19320 CHECK(try_catch.HasCaught());
19321 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019322
19323 // Reset the failed access check callback so it does not influence
19324 // the other tests.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019325 isolate->SetFailedAccessCheckCallbackFunction(NULL);
Iain Merrick75681382010-08-19 15:07:18 +010019326}
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019327
Steve Block44f0eee2011-05-26 01:26:41 +010019328
19329TEST(IsolateNewDispose) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019330 v8::Isolate* current_isolate = CcTest::isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019331 v8::Isolate::CreateParams create_params;
19332 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19333 v8::Isolate* isolate = v8::Isolate::New(create_params);
Steve Block44f0eee2011-05-26 01:26:41 +010019334 CHECK(isolate != NULL);
Steve Block44f0eee2011-05-26 01:26:41 +010019335 CHECK(current_isolate != isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019336 CHECK(current_isolate == CcTest::isolate());
Steve Block44f0eee2011-05-26 01:26:41 +010019337
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019338 isolate->SetFatalErrorHandler(StoringErrorCallback);
Steve Block44f0eee2011-05-26 01:26:41 +010019339 last_location = last_message = NULL;
19340 isolate->Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019341 CHECK(!last_location);
19342 CHECK(!last_message);
Steve Block44f0eee2011-05-26 01:26:41 +010019343}
19344
Steve Block44f0eee2011-05-26 01:26:41 +010019345
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019346UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019347 v8::Isolate::CreateParams create_params;
19348 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19349 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019350 {
19351 v8::Isolate::Scope i_scope(isolate);
19352 v8::HandleScope scope(isolate);
19353 LocalContext context(isolate);
19354 // Run something in this isolate.
19355 ExpectTrue("true");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019356 isolate->SetFatalErrorHandler(StoringErrorCallback);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019357 last_location = last_message = NULL;
19358 // Still entered, should fail.
19359 isolate->Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019360 CHECK(last_location);
19361 CHECK(last_message);
Steve Block44f0eee2011-05-26 01:26:41 +010019362 }
Steve Block44f0eee2011-05-26 01:26:41 +010019363 isolate->Dispose();
Steve Block44f0eee2011-05-26 01:26:41 +010019364}
19365
Steve Block44f0eee2011-05-26 01:26:41 +010019366
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019367static void BreakArrayGuarantees(const char* script) {
19368 v8::Isolate::CreateParams create_params;
19369 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19370 v8::Isolate* isolate1 = v8::Isolate::New(create_params);
19371 isolate1->Enter();
19372 v8::Persistent<v8::Context> context1;
19373 {
19374 v8::HandleScope scope(isolate1);
19375 context1.Reset(isolate1, Context::New(isolate1));
19376 }
19377
19378 {
19379 v8::HandleScope scope(isolate1);
19380 v8::Local<v8::Context> context =
19381 v8::Local<v8::Context>::New(isolate1, context1);
19382 v8::Context::Scope context_scope(context);
19383 v8::internal::Isolate* i_isolate =
19384 reinterpret_cast<v8::internal::Isolate*>(isolate1);
19385 CHECK_EQ(true, i_isolate->IsFastArrayConstructorPrototypeChainIntact());
19386 // Run something in new isolate.
19387 CompileRun(script);
19388 CHECK_EQ(false, i_isolate->IsFastArrayConstructorPrototypeChainIntact());
19389 }
19390 isolate1->Exit();
19391 isolate1->Dispose();
19392}
19393
19394
19395TEST(VerifyArrayPrototypeGuarantees) {
19396 // Break fast array hole handling by element changes.
19397 BreakArrayGuarantees("[].__proto__[1] = 3;");
19398 BreakArrayGuarantees("Object.prototype[3] = 'three';");
19399 BreakArrayGuarantees("Array.prototype.push(1);");
19400 BreakArrayGuarantees("Array.prototype.unshift(1);");
19401 // Break fast array hole handling by changing length.
19402 BreakArrayGuarantees("Array.prototype.length = 30;");
19403 // Break fast array hole handling by prototype structure changes.
19404 BreakArrayGuarantees("[].__proto__.__proto__ = { funny: true };");
19405 // By sending elements to dictionary mode.
19406 BreakArrayGuarantees(
19407 "Object.defineProperty(Array.prototype, 0, {"
19408 " get: function() { return 3; }});");
19409 BreakArrayGuarantees(
19410 "Object.defineProperty(Object.prototype, 0, {"
19411 " get: function() { return 3; }});");
19412}
19413
19414
Steve Block44f0eee2011-05-26 01:26:41 +010019415TEST(RunTwoIsolatesOnSingleThread) {
19416 // Run isolate 1.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019417 v8::Isolate::CreateParams create_params;
19418 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19419 v8::Isolate* isolate1 = v8::Isolate::New(create_params);
Steve Block44f0eee2011-05-26 01:26:41 +010019420 isolate1->Enter();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019421 v8::Persistent<v8::Context> context1;
19422 {
19423 v8::HandleScope scope(isolate1);
19424 context1.Reset(isolate1, Context::New(isolate1));
19425 }
Steve Block44f0eee2011-05-26 01:26:41 +010019426
19427 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019428 v8::HandleScope scope(isolate1);
19429 v8::Local<v8::Context> context =
19430 v8::Local<v8::Context>::New(isolate1, context1);
19431 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019432 // Run something in new isolate.
19433 CompileRun("var foo = 'isolate 1';");
19434 ExpectString("function f() { return foo; }; f()", "isolate 1");
19435 }
19436
19437 // Run isolate 2.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019438 v8::Isolate* isolate2 = v8::Isolate::New(create_params);
Steve Block44f0eee2011-05-26 01:26:41 +010019439 v8::Persistent<v8::Context> context2;
19440
19441 {
19442 v8::Isolate::Scope iscope(isolate2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019443 v8::HandleScope scope(isolate2);
19444 context2.Reset(isolate2, Context::New(isolate2));
19445 v8::Local<v8::Context> context =
19446 v8::Local<v8::Context>::New(isolate2, context2);
19447 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019448
19449 // Run something in new isolate.
19450 CompileRun("var foo = 'isolate 2';");
19451 ExpectString("function f() { return foo; }; f()", "isolate 2");
19452 }
19453
19454 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019455 v8::HandleScope scope(isolate1);
19456 v8::Local<v8::Context> context =
19457 v8::Local<v8::Context>::New(isolate1, context1);
19458 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019459 // Now again in isolate 1
19460 ExpectString("function f() { return foo; }; f()", "isolate 1");
19461 }
19462
19463 isolate1->Exit();
19464
19465 // Run some stuff in default isolate.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019466 v8::Persistent<v8::Context> context_default;
19467 {
19468 v8::Isolate* isolate = CcTest::isolate();
19469 v8::Isolate::Scope iscope(isolate);
19470 v8::HandleScope scope(isolate);
19471 context_default.Reset(isolate, Context::New(isolate));
19472 }
Steve Block44f0eee2011-05-26 01:26:41 +010019473
19474 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019475 v8::HandleScope scope(CcTest::isolate());
19476 v8::Local<v8::Context> context =
19477 v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
19478 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019479 // Variables in other isolates should be not available, verify there
19480 // is an exception.
19481 ExpectTrue("function f() {"
19482 " try {"
19483 " foo;"
19484 " return false;"
19485 " } catch(e) {"
19486 " return true;"
19487 " }"
19488 "};"
19489 "var isDefaultIsolate = true;"
19490 "f()");
19491 }
19492
19493 isolate1->Enter();
19494
19495 {
19496 v8::Isolate::Scope iscope(isolate2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019497 v8::HandleScope scope(isolate2);
19498 v8::Local<v8::Context> context =
19499 v8::Local<v8::Context>::New(isolate2, context2);
19500 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019501 ExpectString("function f() { return foo; }; f()", "isolate 2");
19502 }
19503
19504 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019505 v8::HandleScope scope(v8::Isolate::GetCurrent());
19506 v8::Local<v8::Context> context =
19507 v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
19508 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019509 ExpectString("function f() { return foo; }; f()", "isolate 1");
19510 }
19511
19512 {
19513 v8::Isolate::Scope iscope(isolate2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019514 context2.Reset();
Steve Block44f0eee2011-05-26 01:26:41 +010019515 }
19516
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019517 context1.Reset();
Steve Block44f0eee2011-05-26 01:26:41 +010019518 isolate1->Exit();
19519
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019520 isolate2->SetFatalErrorHandler(StoringErrorCallback);
Steve Block44f0eee2011-05-26 01:26:41 +010019521 last_location = last_message = NULL;
19522
19523 isolate1->Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019524 CHECK(!last_location);
19525 CHECK(!last_message);
Steve Block44f0eee2011-05-26 01:26:41 +010019526
19527 isolate2->Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019528 CHECK(!last_location);
19529 CHECK(!last_message);
Steve Block44f0eee2011-05-26 01:26:41 +010019530
19531 // Check that default isolate still runs.
19532 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019533 v8::HandleScope scope(CcTest::isolate());
19534 v8::Local<v8::Context> context =
19535 v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
19536 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019537 ExpectTrue("function f() { return isDefaultIsolate; }; f()");
19538 }
19539}
19540
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019541
Steve Block44f0eee2011-05-26 01:26:41 +010019542static int CalcFibonacci(v8::Isolate* isolate, int limit) {
19543 v8::Isolate::Scope isolate_scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019544 v8::HandleScope scope(isolate);
19545 LocalContext context(isolate);
Steve Block44f0eee2011-05-26 01:26:41 +010019546 i::ScopedVector<char> code(1024);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019547 i::SNPrintF(code, "function fib(n) {"
19548 " if (n <= 2) return 1;"
19549 " return fib(n-1) + fib(n-2);"
19550 "}"
19551 "fib(%d)", limit);
Steve Block44f0eee2011-05-26 01:26:41 +010019552 Local<Value> value = CompileRun(code.start());
19553 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019554 return static_cast<int>(value->NumberValue(context.local()).FromJust());
Steve Block44f0eee2011-05-26 01:26:41 +010019555}
19556
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019557class IsolateThread : public v8::base::Thread {
Steve Block44f0eee2011-05-26 01:26:41 +010019558 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019559 explicit IsolateThread(int fib_limit)
19560 : Thread(Options("IsolateThread")), fib_limit_(fib_limit), result_(0) {}
Steve Block44f0eee2011-05-26 01:26:41 +010019561
19562 void Run() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019563 v8::Isolate::CreateParams create_params;
19564 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19565 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019566 result_ = CalcFibonacci(isolate, fib_limit_);
19567 isolate->Dispose();
Steve Block44f0eee2011-05-26 01:26:41 +010019568 }
19569
19570 int result() { return result_; }
19571
19572 private:
Steve Block44f0eee2011-05-26 01:26:41 +010019573 int fib_limit_;
19574 int result_;
19575};
19576
Steve Block44f0eee2011-05-26 01:26:41 +010019577
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019578TEST(MultipleIsolatesOnIndividualThreads) {
19579 IsolateThread thread1(21);
19580 IsolateThread thread2(12);
Steve Block44f0eee2011-05-26 01:26:41 +010019581
19582 // Compute some fibonacci numbers on 3 threads in 3 isolates.
19583 thread1.Start();
19584 thread2.Start();
19585
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019586 int result1 = CalcFibonacci(CcTest::isolate(), 21);
19587 int result2 = CalcFibonacci(CcTest::isolate(), 12);
Steve Block44f0eee2011-05-26 01:26:41 +010019588
19589 thread1.Join();
19590 thread2.Join();
19591
19592 // Compare results. The actual fibonacci numbers for 12 and 21 are taken
19593 // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
19594 CHECK_EQ(result1, 10946);
19595 CHECK_EQ(result2, 144);
19596 CHECK_EQ(result1, thread1.result());
19597 CHECK_EQ(result2, thread2.result());
Steve Block44f0eee2011-05-26 01:26:41 +010019598}
19599
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019600
Ben Murdoch257744e2011-11-30 15:57:28 +000019601TEST(IsolateDifferentContexts) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019602 v8::Isolate::CreateParams create_params;
19603 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19604 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019605 Local<v8::Context> context;
Ben Murdoch257744e2011-11-30 15:57:28 +000019606 {
19607 v8::Isolate::Scope isolate_scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019608 v8::HandleScope handle_scope(isolate);
19609 context = v8::Context::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000019610 v8::Context::Scope context_scope(context);
19611 Local<Value> v = CompileRun("2");
19612 CHECK(v->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019613 CHECK_EQ(2, static_cast<int>(v->NumberValue(context).FromJust()));
Ben Murdoch257744e2011-11-30 15:57:28 +000019614 }
19615 {
19616 v8::Isolate::Scope isolate_scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019617 v8::HandleScope handle_scope(isolate);
19618 context = v8::Context::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000019619 v8::Context::Scope context_scope(context);
19620 Local<Value> v = CompileRun("22");
19621 CHECK(v->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019622 CHECK_EQ(22, static_cast<int>(v->NumberValue(context).FromJust()));
Ben Murdoch257744e2011-11-30 15:57:28 +000019623 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019624 isolate->Dispose();
Ben Murdoch257744e2011-11-30 15:57:28 +000019625}
Steve Block44f0eee2011-05-26 01:26:41 +010019626
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019627class InitDefaultIsolateThread : public v8::base::Thread {
Steve Block44f0eee2011-05-26 01:26:41 +010019628 public:
19629 enum TestCase {
Steve Block44f0eee2011-05-26 01:26:41 +010019630 SetResourceConstraints,
19631 SetFatalHandler,
19632 SetCounterFunction,
19633 SetCreateHistogramFunction,
19634 SetAddHistogramSampleFunction
19635 };
19636
19637 explicit InitDefaultIsolateThread(TestCase testCase)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019638 : Thread(Options("InitDefaultIsolateThread")),
Steve Block44f0eee2011-05-26 01:26:41 +010019639 testCase_(testCase),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019640 result_(false) {}
Steve Block44f0eee2011-05-26 01:26:41 +010019641
19642 void Run() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019643 v8::Isolate::CreateParams create_params;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019644 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19645 const intptr_t pageSizeMult =
19646 v8::internal::Page::kPageSize / v8::internal::MB;
Steve Block44f0eee2011-05-26 01:26:41 +010019647 switch (testCase_) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019648 case SetResourceConstraints: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019649 create_params.constraints.set_max_semi_space_size(1 * pageSizeMult);
19650 create_params.constraints.set_max_old_space_size(4 * pageSizeMult);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019651 break;
19652 }
19653 default:
19654 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019655 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019656 v8::Isolate* isolate = v8::Isolate::New(create_params);
19657 isolate->Enter();
19658 switch (testCase_) {
19659 case SetResourceConstraints:
19660 // Already handled in pre-Isolate-creation block.
19661 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019662
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019663 case SetFatalHandler:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019664 isolate->SetFatalErrorHandler(NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019665 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019666
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019667 case SetCounterFunction:
19668 CcTest::isolate()->SetCounterFunction(NULL);
19669 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019670
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019671 case SetCreateHistogramFunction:
19672 CcTest::isolate()->SetCreateHistogramFunction(NULL);
19673 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019674
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019675 case SetAddHistogramSampleFunction:
19676 CcTest::isolate()->SetAddHistogramSampleFunction(NULL);
19677 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019678 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019679 isolate->Exit();
19680 isolate->Dispose();
Steve Block44f0eee2011-05-26 01:26:41 +010019681 result_ = true;
19682 }
19683
19684 bool result() { return result_; }
19685
19686 private:
19687 TestCase testCase_;
19688 bool result_;
19689};
19690
19691
19692static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
19693 InitDefaultIsolateThread thread(testCase);
19694 thread.Start();
19695 thread.Join();
19696 CHECK_EQ(thread.result(), true);
19697}
19698
Steve Block44f0eee2011-05-26 01:26:41 +010019699
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019700TEST(InitializeDefaultIsolateOnSecondaryThread1) {
Steve Block44f0eee2011-05-26 01:26:41 +010019701 InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
19702}
19703
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019704
19705TEST(InitializeDefaultIsolateOnSecondaryThread2) {
Steve Block44f0eee2011-05-26 01:26:41 +010019706 InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
19707}
19708
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019709
19710TEST(InitializeDefaultIsolateOnSecondaryThread3) {
Steve Block44f0eee2011-05-26 01:26:41 +010019711 InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
19712}
19713
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019714
19715TEST(InitializeDefaultIsolateOnSecondaryThread4) {
Steve Block44f0eee2011-05-26 01:26:41 +010019716 InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
19717}
19718
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019719
19720TEST(InitializeDefaultIsolateOnSecondaryThread5) {
Steve Block44f0eee2011-05-26 01:26:41 +010019721 InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
19722}
19723
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019724
19725TEST(StringCheckMultipleContexts) {
19726 const char* code =
19727 "(function() { return \"a\".charAt(0); })()";
19728
19729 {
19730 // Run the code twice in the first context to initialize the call IC.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019731 LocalContext context1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019732 v8::HandleScope scope(context1->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019733 ExpectString(code, "a");
19734 ExpectString(code, "a");
19735 }
19736
19737 {
19738 // Change the String.prototype in the second context and check
19739 // that the right function gets called.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019740 LocalContext context2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019741 v8::HandleScope scope(context2->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019742 CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
19743 ExpectString(code, "not a");
19744 }
19745}
19746
19747
19748TEST(NumberCheckMultipleContexts) {
19749 const char* code =
19750 "(function() { return (42).toString(); })()";
19751
19752 {
19753 // Run the code twice in the first context to initialize the call IC.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019754 LocalContext context1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019755 v8::HandleScope scope(context1->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019756 ExpectString(code, "42");
19757 ExpectString(code, "42");
19758 }
19759
19760 {
19761 // Change the Number.prototype in the second context and check
19762 // that the right function gets called.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019763 LocalContext context2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019764 v8::HandleScope scope(context2->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019765 CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
19766 ExpectString(code, "not 42");
19767 }
19768}
19769
19770
19771TEST(BooleanCheckMultipleContexts) {
19772 const char* code =
19773 "(function() { return true.toString(); })()";
19774
19775 {
19776 // Run the code twice in the first context to initialize the call IC.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019777 LocalContext context1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019778 v8::HandleScope scope(context1->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019779 ExpectString(code, "true");
19780 ExpectString(code, "true");
19781 }
19782
19783 {
19784 // Change the Boolean.prototype in the second context and check
19785 // that the right function gets called.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019786 LocalContext context2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019787 v8::HandleScope scope(context2->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019788 CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
19789 ExpectString(code, "");
19790 }
19791}
Ben Murdochf87a2032010-10-22 12:50:53 +010019792
19793
19794TEST(DontDeleteCellLoadIC) {
19795 const char* function_code =
19796 "function readCell() { while (true) { return cell; } }";
19797
19798 {
19799 // Run the code twice in the first context to initialize the load
19800 // IC for a don't delete cell.
Ben Murdochf87a2032010-10-22 12:50:53 +010019801 LocalContext context1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019802 v8::HandleScope scope(context1->GetIsolate());
Ben Murdochf87a2032010-10-22 12:50:53 +010019803 CompileRun("var cell = \"first\";");
19804 ExpectBoolean("delete cell", false);
19805 CompileRun(function_code);
19806 ExpectString("readCell()", "first");
19807 ExpectString("readCell()", "first");
19808 }
19809
19810 {
19811 // Use a deletable cell in the second context.
Ben Murdochf87a2032010-10-22 12:50:53 +010019812 LocalContext context2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019813 v8::HandleScope scope(context2->GetIsolate());
Ben Murdochf87a2032010-10-22 12:50:53 +010019814 CompileRun("cell = \"second\";");
19815 CompileRun(function_code);
19816 ExpectString("readCell()", "second");
19817 ExpectBoolean("delete cell", true);
19818 ExpectString("(function() {"
19819 " try {"
19820 " return readCell();"
19821 " } catch(e) {"
19822 " return e.toString();"
19823 " }"
19824 "})()",
19825 "ReferenceError: cell is not defined");
19826 CompileRun("cell = \"new_second\";");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019827 CcTest::heap()->CollectAllGarbage();
Ben Murdochf87a2032010-10-22 12:50:53 +010019828 ExpectString("readCell()", "new_second");
19829 ExpectString("readCell()", "new_second");
19830 }
19831}
19832
19833
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019834class Visitor42 : public v8::PersistentHandleVisitor {
19835 public:
19836 explicit Visitor42(v8::Persistent<v8::Object>* object)
19837 : counter_(0), object_(object) { }
19838
19839 virtual void VisitPersistentHandle(Persistent<Value>* value,
19840 uint16_t class_id) {
19841 if (class_id != 42) return;
19842 CHECK_EQ(42, value->WrapperClassId());
19843 v8::Isolate* isolate = CcTest::isolate();
19844 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019845 v8::Local<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
19846 v8::Local<v8::Value> object = v8::Local<v8::Object>::New(isolate, *object_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019847 CHECK(handle->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019848 CHECK(Local<Object>::Cast(handle)
19849 ->Equals(isolate->GetCurrentContext(), object)
19850 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019851 ++counter_;
19852 }
19853
19854 int counter_;
19855 v8::Persistent<v8::Object>* object_;
19856};
19857
19858
19859TEST(PersistentHandleVisitor) {
Ben Murdochf87a2032010-10-22 12:50:53 +010019860 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019861 v8::Isolate* isolate = context->GetIsolate();
19862 v8::HandleScope scope(isolate);
19863 v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
19864 CHECK_EQ(0, object.WrapperClassId());
19865 object.SetWrapperClassId(42);
19866 CHECK_EQ(42, object.WrapperClassId());
19867
19868 Visitor42 visitor(&object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019869 isolate->VisitHandlesWithClassIds(&visitor);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019870 CHECK_EQ(1, visitor.counter_);
19871
19872 object.Reset();
19873}
19874
19875
19876TEST(WrapperClassId) {
19877 LocalContext context;
19878 v8::Isolate* isolate = context->GetIsolate();
19879 v8::HandleScope scope(isolate);
19880 v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
19881 CHECK_EQ(0, object.WrapperClassId());
19882 object.SetWrapperClassId(65535);
19883 CHECK_EQ(65535, object.WrapperClassId());
19884 object.Reset();
19885}
19886
19887
19888TEST(PersistentHandleInNewSpaceVisitor) {
19889 LocalContext context;
19890 v8::Isolate* isolate = context->GetIsolate();
19891 v8::HandleScope scope(isolate);
19892 v8::Persistent<v8::Object> object1(isolate, v8::Object::New(isolate));
19893 CHECK_EQ(0, object1.WrapperClassId());
19894 object1.SetWrapperClassId(42);
19895 CHECK_EQ(42, object1.WrapperClassId());
19896
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019897 CcTest::heap()->CollectAllGarbage();
19898 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019899
19900 v8::Persistent<v8::Object> object2(isolate, v8::Object::New(isolate));
19901 CHECK_EQ(0, object2.WrapperClassId());
19902 object2.SetWrapperClassId(42);
19903 CHECK_EQ(42, object2.WrapperClassId());
19904
19905 Visitor42 visitor(&object2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019906 isolate->VisitHandlesForPartialDependence(&visitor);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019907 CHECK_EQ(1, visitor.counter_);
19908
19909 object1.Reset();
19910 object2.Reset();
19911}
19912
19913
19914TEST(RegExp) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019915 i::FLAG_harmony_unicode_regexps = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019916 LocalContext context;
19917 v8::HandleScope scope(context->GetIsolate());
Ben Murdochf87a2032010-10-22 12:50:53 +010019918
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019919 v8::Local<v8::RegExp> re =
19920 v8::RegExp::New(context.local(), v8_str("foo"), v8::RegExp::kNone)
19921 .ToLocalChecked();
Ben Murdochf87a2032010-10-22 12:50:53 +010019922 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019923 CHECK(re->GetSource()->Equals(context.local(), v8_str("foo")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019924 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
Ben Murdochf87a2032010-10-22 12:50:53 +010019925
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019926 re = v8::RegExp::New(context.local(), v8_str("bar"),
Ben Murdochf87a2032010-10-22 12:50:53 +010019927 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019928 v8::RegExp::kGlobal))
19929 .ToLocalChecked();
Ben Murdochf87a2032010-10-22 12:50:53 +010019930 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019931 CHECK(re->GetSource()->Equals(context.local(), v8_str("bar")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019932 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
19933 static_cast<int>(re->GetFlags()));
Ben Murdochf87a2032010-10-22 12:50:53 +010019934
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019935 re = v8::RegExp::New(context.local(), v8_str("baz"),
Ben Murdochf87a2032010-10-22 12:50:53 +010019936 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019937 v8::RegExp::kMultiline))
19938 .ToLocalChecked();
Ben Murdochf87a2032010-10-22 12:50:53 +010019939 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019940 CHECK(re->GetSource()->Equals(context.local(), v8_str("baz")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019941 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
19942 static_cast<int>(re->GetFlags()));
Ben Murdochf87a2032010-10-22 12:50:53 +010019943
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019944 re = v8::RegExp::New(context.local(), v8_str("baz"),
19945 static_cast<v8::RegExp::Flags>(v8::RegExp::kUnicode |
19946 v8::RegExp::kSticky))
19947 .ToLocalChecked();
19948 CHECK(re->IsRegExp());
19949 CHECK(re->GetSource()->Equals(context.local(), v8_str("baz")).FromJust());
19950 CHECK_EQ(v8::RegExp::kUnicode | v8::RegExp::kSticky,
19951 static_cast<int>(re->GetFlags()));
19952
Ben Murdochf87a2032010-10-22 12:50:53 +010019953 re = CompileRun("/quux/").As<v8::RegExp>();
19954 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019955 CHECK(re->GetSource()->Equals(context.local(), v8_str("quux")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019956 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
Ben Murdochf87a2032010-10-22 12:50:53 +010019957
19958 re = CompileRun("/quux/gm").As<v8::RegExp>();
19959 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019960 CHECK(re->GetSource()->Equals(context.local(), v8_str("quux")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019961 CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
19962 static_cast<int>(re->GetFlags()));
Ben Murdochf87a2032010-10-22 12:50:53 +010019963
19964 // Override the RegExp constructor and check the API constructor
19965 // still works.
19966 CompileRun("RegExp = function() {}");
19967
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019968 re = v8::RegExp::New(context.local(), v8_str("foobar"), v8::RegExp::kNone)
19969 .ToLocalChecked();
Ben Murdochf87a2032010-10-22 12:50:53 +010019970 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019971 CHECK(re->GetSource()->Equals(context.local(), v8_str("foobar")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019972 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
Ben Murdochf87a2032010-10-22 12:50:53 +010019973
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019974 re = v8::RegExp::New(context.local(), v8_str("foobarbaz"),
Ben Murdochf87a2032010-10-22 12:50:53 +010019975 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019976 v8::RegExp::kMultiline))
19977 .ToLocalChecked();
Ben Murdochf87a2032010-10-22 12:50:53 +010019978 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019979 CHECK(
19980 re->GetSource()->Equals(context.local(), v8_str("foobarbaz")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019981 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
19982 static_cast<int>(re->GetFlags()));
Ben Murdochf87a2032010-10-22 12:50:53 +010019983
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019984 CHECK(context->Global()->Set(context.local(), v8_str("re"), re).FromJust());
Ben Murdochf87a2032010-10-22 12:50:53 +010019985 ExpectTrue("re.test('FoobarbaZ')");
19986
Ben Murdoch257744e2011-11-30 15:57:28 +000019987 // RegExps are objects on which you can set properties.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019988 re->Set(context.local(), v8_str("property"),
19989 v8::Integer::New(context->GetIsolate(), 32))
19990 .FromJust();
19991 v8::Local<v8::Value> value(CompileRun("re.property"));
19992 CHECK_EQ(32, value->Int32Value(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000019993
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019994 v8::TryCatch try_catch(context->GetIsolate());
19995 CHECK(v8::RegExp::New(context.local(), v8_str("foo["), v8::RegExp::kNone)
19996 .IsEmpty());
Ben Murdochf87a2032010-10-22 12:50:53 +010019997 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019998 CHECK(context->Global()
19999 ->Set(context.local(), v8_str("ex"), try_catch.Exception())
20000 .FromJust());
Ben Murdochf87a2032010-10-22 12:50:53 +010020001 ExpectTrue("ex instanceof SyntaxError");
20002}
20003
20004
Steve Block1e0659c2011-05-24 12:43:12 +010020005THREADED_TEST(Equals) {
Steve Block1e0659c2011-05-24 12:43:12 +010020006 LocalContext localContext;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020007 v8::HandleScope handleScope(localContext->GetIsolate());
Steve Block1e0659c2011-05-24 12:43:12 +010020008
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020009 v8::Local<v8::Object> globalProxy = localContext->Global();
20010 v8::Local<Value> global = globalProxy->GetPrototype();
Steve Block1e0659c2011-05-24 12:43:12 +010020011
20012 CHECK(global->StrictEquals(global));
20013 CHECK(!global->StrictEquals(globalProxy));
20014 CHECK(!globalProxy->StrictEquals(global));
20015 CHECK(globalProxy->StrictEquals(globalProxy));
20016
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020017 CHECK(global->Equals(localContext.local(), global).FromJust());
20018 CHECK(!global->Equals(localContext.local(), globalProxy).FromJust());
20019 CHECK(!globalProxy->Equals(localContext.local(), global).FromJust());
20020 CHECK(globalProxy->Equals(localContext.local(), globalProxy).FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +010020021}
20022
20023
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020024static void Getter(v8::Local<v8::Name> property,
20025 const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020026 info.GetReturnValue().Set(v8_str("42!"));
Ben Murdochf87a2032010-10-22 12:50:53 +010020027}
20028
20029
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020030static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020031 v8::Local<v8::Array> result = v8::Array::New(info.GetIsolate());
20032 result->Set(info.GetIsolate()->GetCurrentContext(), 0,
20033 v8_str("universalAnswer"))
20034 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020035 info.GetReturnValue().Set(result);
Ben Murdochf87a2032010-10-22 12:50:53 +010020036}
20037
20038
20039TEST(NamedEnumeratorAndForIn) {
Ben Murdochf87a2032010-10-22 12:50:53 +010020040 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020041 v8::Isolate* isolate = context->GetIsolate();
20042 v8::HandleScope handle_scope(isolate);
Ben Murdochf87a2032010-10-22 12:50:53 +010020043 v8::Context::Scope context_scope(context.local());
20044
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020045 v8::Local<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020046 tmpl->SetHandler(v8::NamedPropertyHandlerConfiguration(Getter, NULL, NULL,
20047 NULL, Enumerator));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020048 CHECK(context->Global()
20049 ->Set(context.local(), v8_str("o"),
20050 tmpl->NewInstance(context.local()).ToLocalChecked())
20051 .FromJust());
20052 v8::Local<v8::Array> result = v8::Local<v8::Array>::Cast(
20053 CompileRun("var result = []; for (var k in o) result.push(k); result"));
20054 CHECK_EQ(1u, result->Length());
20055 CHECK(v8_str("universalAnswer")
20056 ->Equals(context.local(),
20057 result->Get(context.local(), 0).ToLocalChecked())
20058 .FromJust());
Ben Murdochf87a2032010-10-22 12:50:53 +010020059}
Steve Block1e0659c2011-05-24 12:43:12 +010020060
20061
20062TEST(DefinePropertyPostDetach) {
Steve Block1e0659c2011-05-24 12:43:12 +010020063 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020064 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020065 v8::Local<v8::Object> proxy = context->Global();
20066 v8::Local<v8::Function> define_property =
20067 CompileRun(
20068 "(function() {"
20069 " Object.defineProperty("
20070 " this,"
20071 " 1,"
20072 " { configurable: true, enumerable: true, value: 3 });"
20073 "})")
20074 .As<Function>();
Steve Block1e0659c2011-05-24 12:43:12 +010020075 context->DetachGlobal();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020076 CHECK(define_property->Call(context.local(), proxy, 0, NULL).IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +010020077}
Ben Murdoch8b112d22011-06-08 16:22:53 +010020078
20079
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020080static void InstallContextId(v8::Local<Context> context, int id) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010020081 Context::Scope scope(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020082 CHECK(CompileRun("Object.prototype")
20083 .As<Object>()
20084 ->Set(context, v8_str("context_id"),
20085 v8::Integer::New(context->GetIsolate(), id))
20086 .FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010020087}
20088
20089
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020090static void CheckContextId(v8::Local<Object> object, int expected) {
20091 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
20092 CHECK_EQ(expected, object->Get(context, v8_str("context_id"))
20093 .ToLocalChecked()
20094 ->Int32Value(context)
20095 .FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010020096}
20097
20098
20099THREADED_TEST(CreationContext) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020100 v8::Isolate* isolate = CcTest::isolate();
20101 HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020102 Local<Context> context1 = Context::New(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +010020103 InstallContextId(context1, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020104 Local<Context> context2 = Context::New(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +010020105 InstallContextId(context2, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020106 Local<Context> context3 = Context::New(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +010020107 InstallContextId(context3, 3);
20108
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020109 Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +010020110
20111 Local<Object> object1;
20112 Local<Function> func1;
20113 {
20114 Context::Scope scope(context1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020115 object1 = Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020116 func1 = tmpl->GetFunction(context1).ToLocalChecked();
Ben Murdoch8b112d22011-06-08 16:22:53 +010020117 }
20118
20119 Local<Object> object2;
20120 Local<Function> func2;
20121 {
20122 Context::Scope scope(context2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020123 object2 = Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020124 func2 = tmpl->GetFunction(context2).ToLocalChecked();
Ben Murdoch8b112d22011-06-08 16:22:53 +010020125 }
20126
20127 Local<Object> instance1;
20128 Local<Object> instance2;
20129
20130 {
20131 Context::Scope scope(context3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020132 instance1 = func1->NewInstance(context3).ToLocalChecked();
20133 instance2 = func2->NewInstance(context3).ToLocalChecked();
Ben Murdoch8b112d22011-06-08 16:22:53 +010020134 }
20135
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020136 {
20137 Local<Context> other_context = Context::New(isolate);
20138 Context::Scope scope(other_context);
20139 CHECK(object1->CreationContext() == context1);
20140 CheckContextId(object1, 1);
20141 CHECK(func1->CreationContext() == context1);
20142 CheckContextId(func1, 1);
20143 CHECK(instance1->CreationContext() == context1);
20144 CheckContextId(instance1, 1);
20145 CHECK(object2->CreationContext() == context2);
20146 CheckContextId(object2, 2);
20147 CHECK(func2->CreationContext() == context2);
20148 CheckContextId(func2, 2);
20149 CHECK(instance2->CreationContext() == context2);
20150 CheckContextId(instance2, 2);
20151 }
Ben Murdoch8b112d22011-06-08 16:22:53 +010020152
20153 {
20154 Context::Scope scope(context1);
20155 CHECK(object1->CreationContext() == context1);
20156 CheckContextId(object1, 1);
20157 CHECK(func1->CreationContext() == context1);
20158 CheckContextId(func1, 1);
20159 CHECK(instance1->CreationContext() == context1);
20160 CheckContextId(instance1, 1);
20161 CHECK(object2->CreationContext() == context2);
20162 CheckContextId(object2, 2);
20163 CHECK(func2->CreationContext() == context2);
20164 CheckContextId(func2, 2);
20165 CHECK(instance2->CreationContext() == context2);
20166 CheckContextId(instance2, 2);
20167 }
20168
20169 {
20170 Context::Scope scope(context2);
20171 CHECK(object1->CreationContext() == context1);
20172 CheckContextId(object1, 1);
20173 CHECK(func1->CreationContext() == context1);
20174 CheckContextId(func1, 1);
20175 CHECK(instance1->CreationContext() == context1);
20176 CheckContextId(instance1, 1);
20177 CHECK(object2->CreationContext() == context2);
20178 CheckContextId(object2, 2);
20179 CHECK(func2->CreationContext() == context2);
20180 CheckContextId(func2, 2);
20181 CHECK(instance2->CreationContext() == context2);
20182 CheckContextId(instance2, 2);
20183 }
Ben Murdoch8b112d22011-06-08 16:22:53 +010020184}
Ben Murdoch257744e2011-11-30 15:57:28 +000020185
20186
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020187THREADED_TEST(CreationContextOfJsFunction) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020188 HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020189 Local<Context> context = Context::New(CcTest::isolate());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020190 InstallContextId(context, 1);
20191
20192 Local<Object> function;
20193 {
20194 Context::Scope scope(context);
20195 function = CompileRun("function foo() {}; foo").As<Object>();
20196 }
20197
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020198 Local<Context> other_context = Context::New(CcTest::isolate());
20199 Context::Scope scope(other_context);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020200 CHECK(function->CreationContext() == context);
20201 CheckContextId(function, 1);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020202}
20203
20204
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020205THREADED_TEST(CreationContextOfJsBoundFunction) {
20206 HandleScope handle_scope(CcTest::isolate());
20207 Local<Context> context1 = Context::New(CcTest::isolate());
20208 InstallContextId(context1, 1);
20209 Local<Context> context2 = Context::New(CcTest::isolate());
20210 InstallContextId(context2, 2);
20211
20212 Local<Function> target_function;
20213 {
20214 Context::Scope scope(context1);
20215 target_function = CompileRun("function foo() {}; foo").As<Function>();
20216 }
20217
20218 Local<Function> bound_function1, bound_function2;
20219 {
20220 Context::Scope scope(context2);
20221 CHECK(context2->Global()
20222 ->Set(context2, v8_str("foo"), target_function)
20223 .FromJust());
20224 bound_function1 = CompileRun("foo.bind(1)").As<Function>();
20225 bound_function2 =
20226 CompileRun("Function.prototype.bind.call(foo, 2)").As<Function>();
20227 }
20228
20229 Local<Context> other_context = Context::New(CcTest::isolate());
20230 Context::Scope scope(other_context);
20231 CHECK(bound_function1->CreationContext() == context1);
20232 CheckContextId(bound_function1, 1);
Ben Murdoch097c5b22016-05-18 11:27:45 +010020233 CHECK(bound_function2->CreationContext() == context1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020234 CheckContextId(bound_function2, 1);
20235}
20236
20237
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020238void HasOwnPropertyIndexedPropertyGetter(
20239 uint32_t index,
20240 const v8::PropertyCallbackInfo<v8::Value>& info) {
20241 if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
Ben Murdoch257744e2011-11-30 15:57:28 +000020242}
20243
20244
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020245void HasOwnPropertyNamedPropertyGetter(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020246 Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020247 if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
20248 .FromJust()) {
20249 info.GetReturnValue().Set(v8_str("yes"));
20250 }
Ben Murdoch257744e2011-11-30 15:57:28 +000020251}
20252
20253
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020254void HasOwnPropertyIndexedPropertyQuery(
20255 uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
20256 if (index == 42) info.GetReturnValue().Set(1);
Ben Murdoch257744e2011-11-30 15:57:28 +000020257}
20258
20259
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020260void HasOwnPropertyNamedPropertyQuery(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020261 Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020262 if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
20263 .FromJust()) {
20264 info.GetReturnValue().Set(1);
20265 }
Ben Murdoch257744e2011-11-30 15:57:28 +000020266}
20267
20268
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020269void HasOwnPropertyNamedPropertyQuery2(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020270 Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020271 if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("bar"))
20272 .FromJust()) {
20273 info.GetReturnValue().Set(1);
20274 }
Ben Murdoch257744e2011-11-30 15:57:28 +000020275}
20276
20277
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020278void HasOwnPropertyAccessorGetter(
20279 Local<String> property,
20280 const v8::PropertyCallbackInfo<v8::Value>& info) {
20281 info.GetReturnValue().Set(v8_str("yes"));
Ben Murdoch257744e2011-11-30 15:57:28 +000020282}
20283
20284
20285TEST(HasOwnProperty) {
Ben Murdoch257744e2011-11-30 15:57:28 +000020286 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020287 v8::Isolate* isolate = env->GetIsolate();
20288 v8::HandleScope scope(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000020289 { // Check normal properties and defined getters.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020290 Local<Value> value = CompileRun(
Ben Murdoch257744e2011-11-30 15:57:28 +000020291 "function Foo() {"
20292 " this.foo = 11;"
20293 " this.__defineGetter__('baz', function() { return 1; });"
20294 "};"
20295 "function Bar() { "
20296 " this.bar = 13;"
20297 " this.__defineGetter__('bla', function() { return 2; });"
20298 "};"
20299 "Bar.prototype = new Foo();"
20300 "new Bar();");
20301 CHECK(value->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020302 Local<Object> object = value->ToObject(env.local()).ToLocalChecked();
20303 CHECK(object->Has(env.local(), v8_str("foo")).FromJust());
20304 CHECK(!object->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
20305 CHECK(object->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
20306 CHECK(object->Has(env.local(), v8_str("baz")).FromJust());
20307 CHECK(!object->HasOwnProperty(env.local(), v8_str("baz")).FromJust());
20308 CHECK(object->HasOwnProperty(env.local(), v8_str("bla")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020309 }
20310 { // Check named getter interceptors.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020311 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020312 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
20313 HasOwnPropertyNamedPropertyGetter));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020314 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
20315 CHECK(!instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
20316 CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
20317 CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020318 }
20319 { // Check indexed getter interceptors.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020320 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020321 templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
20322 HasOwnPropertyIndexedPropertyGetter));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020323 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
20324 CHECK(instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
20325 CHECK(!instance->HasOwnProperty(env.local(), v8_str("43")).FromJust());
20326 CHECK(!instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020327 }
20328 { // Check named query interceptors.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020329 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020330 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
20331 0, 0, HasOwnPropertyNamedPropertyQuery));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020332 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
20333 CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
20334 CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020335 }
20336 { // Check indexed query interceptors.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020337 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020338 templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
20339 0, 0, HasOwnPropertyIndexedPropertyQuery));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020340 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
20341 CHECK(instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
20342 CHECK(!instance->HasOwnProperty(env.local(), v8_str("41")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020343 }
20344 { // Check callbacks.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020345 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000020346 templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020347 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
20348 CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
20349 CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020350 }
20351 { // Check that query wins on disagreement.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020352 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020353 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
20354 HasOwnPropertyNamedPropertyGetter, 0,
20355 HasOwnPropertyNamedPropertyQuery2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020356 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
20357 CHECK(!instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
20358 CHECK(instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020359 }
20360}
20361
20362
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020363TEST(IndexedInterceptorWithStringProto) {
20364 v8::Isolate* isolate = CcTest::isolate();
20365 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020366 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020367 templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
20368 NULL, NULL, HasOwnPropertyIndexedPropertyQuery));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020369 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020370 CHECK(context->Global()
20371 ->Set(context.local(), v8_str("obj"),
20372 templ->NewInstance(context.local()).ToLocalChecked())
20373 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020374 CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
20375 // These should be intercepted.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020376 CHECK(CompileRun("42 in obj")->BooleanValue(context.local()).FromJust());
20377 CHECK(CompileRun("'42' in obj")->BooleanValue(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020378 // These should fall through to the String prototype.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020379 CHECK(CompileRun("0 in obj")->BooleanValue(context.local()).FromJust());
20380 CHECK(CompileRun("'0' in obj")->BooleanValue(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020381 // And these should both fail.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020382 CHECK(!CompileRun("32 in obj")->BooleanValue(context.local()).FromJust());
20383 CHECK(!CompileRun("'32' in obj")->BooleanValue(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020384}
20385
20386
Ben Murdoch257744e2011-11-30 15:57:28 +000020387void CheckCodeGenerationAllowed() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020388 Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
20389 Local<Value> result = CompileRun("eval('42')");
20390 CHECK_EQ(42, result->Int32Value(context).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020391 result = CompileRun("(function(e) { return e('42'); })(eval)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020392 CHECK_EQ(42, result->Int32Value(context).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020393 result = CompileRun("var f = new Function('return 42'); f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020394 CHECK_EQ(42, result->Int32Value(context).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020395}
20396
20397
20398void CheckCodeGenerationDisallowed() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020399 TryCatch try_catch(CcTest::isolate());
Ben Murdoch257744e2011-11-30 15:57:28 +000020400
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020401 Local<Value> result = CompileRun("eval('42')");
Ben Murdoch257744e2011-11-30 15:57:28 +000020402 CHECK(result.IsEmpty());
20403 CHECK(try_catch.HasCaught());
20404 try_catch.Reset();
20405
20406 result = CompileRun("(function(e) { return e('42'); })(eval)");
20407 CHECK(result.IsEmpty());
20408 CHECK(try_catch.HasCaught());
20409 try_catch.Reset();
20410
20411 result = CompileRun("var f = new Function('return 42'); f()");
20412 CHECK(result.IsEmpty());
20413 CHECK(try_catch.HasCaught());
20414}
20415
20416
20417bool CodeGenerationAllowed(Local<Context> context) {
20418 ApiTestFuzzer::Fuzz();
20419 return true;
20420}
20421
20422
20423bool CodeGenerationDisallowed(Local<Context> context) {
20424 ApiTestFuzzer::Fuzz();
20425 return false;
20426}
20427
20428
20429THREADED_TEST(AllowCodeGenFromStrings) {
Ben Murdoch257744e2011-11-30 15:57:28 +000020430 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020431 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch257744e2011-11-30 15:57:28 +000020432
20433 // eval and the Function constructor allowed by default.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020434 CHECK(context->IsCodeGenerationFromStringsAllowed());
Ben Murdoch257744e2011-11-30 15:57:28 +000020435 CheckCodeGenerationAllowed();
20436
20437 // Disallow eval and the Function constructor.
20438 context->AllowCodeGenerationFromStrings(false);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020439 CHECK(!context->IsCodeGenerationFromStringsAllowed());
Ben Murdoch257744e2011-11-30 15:57:28 +000020440 CheckCodeGenerationDisallowed();
20441
20442 // Allow again.
20443 context->AllowCodeGenerationFromStrings(true);
20444 CheckCodeGenerationAllowed();
20445
20446 // Disallow but setting a global callback that will allow the calls.
20447 context->AllowCodeGenerationFromStrings(false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020448 context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
20449 &CodeGenerationAllowed);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020450 CHECK(!context->IsCodeGenerationFromStringsAllowed());
Ben Murdoch257744e2011-11-30 15:57:28 +000020451 CheckCodeGenerationAllowed();
20452
20453 // Set a callback that disallows the code generation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020454 context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
20455 &CodeGenerationDisallowed);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020456 CHECK(!context->IsCodeGenerationFromStringsAllowed());
Ben Murdoch257744e2011-11-30 15:57:28 +000020457 CheckCodeGenerationDisallowed();
20458}
20459
20460
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020461TEST(SetErrorMessageForCodeGenFromStrings) {
20462 LocalContext context;
20463 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020464 TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020465
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020466 Local<String> message = v8_str("Message");
20467 Local<String> expected_message = v8_str("Uncaught EvalError: Message");
20468 context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
20469 &CodeGenerationDisallowed);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020470 context->AllowCodeGenerationFromStrings(false);
20471 context->SetErrorMessageForCodeGenerationFromStrings(message);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020472 Local<Value> result = CompileRun("eval('42')");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020473 CHECK(result.IsEmpty());
20474 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020475 Local<String> actual_message = try_catch.Message()->Get();
20476 CHECK(expected_message->Equals(context.local(), actual_message).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020477}
20478
20479
20480static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch257744e2011-11-30 15:57:28 +000020481}
20482
20483
20484THREADED_TEST(CallAPIFunctionOnNonObject) {
Ben Murdoch257744e2011-11-30 15:57:28 +000020485 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020486 v8::Isolate* isolate = context->GetIsolate();
20487 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020488 Local<FunctionTemplate> templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020489 v8::FunctionTemplate::New(isolate, NonObjectThis);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020490 Local<Function> function =
20491 templ->GetFunction(context.local()).ToLocalChecked();
20492 CHECK(context->Global()
20493 ->Set(context.local(), v8_str("f"), function)
20494 .FromJust());
20495 TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000020496 CompileRun("f.call(2)");
20497}
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020498
20499
20500// Regression test for issue 1470.
20501THREADED_TEST(ReadOnlyIndexedProperties) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020502 v8::Isolate* isolate = CcTest::isolate();
20503 v8::HandleScope scope(isolate);
20504 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020505
20506 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020507 Local<v8::Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
20508 CHECK(context->Global()->Set(context.local(), v8_str("obj"), obj).FromJust());
20509 obj->DefineOwnProperty(context.local(), v8_str("1"), v8_str("DONT_CHANGE"),
20510 v8::ReadOnly)
20511 .FromJust();
20512 obj->Set(context.local(), v8_str("1"), v8_str("foobar")).FromJust();
20513 CHECK(v8_str("DONT_CHANGE")
20514 ->Equals(context.local(),
20515 obj->Get(context.local(), v8_str("1")).ToLocalChecked())
20516 .FromJust());
20517 obj->DefineOwnProperty(context.local(), v8_str("2"), v8_str("DONT_CHANGE"),
20518 v8::ReadOnly)
20519 .FromJust();
20520 obj->Set(context.local(), v8_num(2), v8_str("foobar")).FromJust();
20521 CHECK(v8_str("DONT_CHANGE")
20522 ->Equals(context.local(),
20523 obj->Get(context.local(), v8_num(2)).ToLocalChecked())
20524 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020525
20526 // Test non-smi case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020527 obj->DefineOwnProperty(context.local(), v8_str("2000000000"),
20528 v8_str("DONT_CHANGE"), v8::ReadOnly)
20529 .FromJust();
20530 obj->Set(context.local(), v8_str("2000000000"), v8_str("foobar")).FromJust();
20531 CHECK(v8_str("DONT_CHANGE")
20532 ->Equals(context.local(),
20533 obj->Get(context.local(), v8_str("2000000000"))
20534 .ToLocalChecked())
20535 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020536}
20537
20538
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020539static int CountLiveMapsInMapCache(i::Context* context) {
20540 i::FixedArray* map_cache = i::FixedArray::cast(context->map_cache());
20541 int length = map_cache->length();
20542 int count = 0;
20543 for (int i = 0; i < length; i++) {
20544 i::Object* value = map_cache->get(i);
20545 if (value->IsWeakCell() && !i::WeakCell::cast(value)->cleared()) count++;
20546 }
20547 return count;
20548}
20549
20550
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020551THREADED_TEST(Regress1516) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020552 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020553 v8::HandleScope scope(context->GetIsolate());
20554
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020555 // Object with 20 properties is not a common case, so it should be removed
20556 // from the cache after GC.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020557 { v8::HandleScope temp_scope(context->GetIsolate());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020558 CompileRun(
20559 "({"
20560 "'a00': 0, 'a01': 0, 'a02': 0, 'a03': 0, 'a04': 0, "
20561 "'a05': 0, 'a06': 0, 'a07': 0, 'a08': 0, 'a09': 0, "
20562 "'a10': 0, 'a11': 0, 'a12': 0, 'a13': 0, 'a14': 0, "
20563 "'a15': 0, 'a16': 0, 'a17': 0, 'a18': 0, 'a19': 0, "
20564 "})");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020565 }
20566
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020567 int elements = CountLiveMapsInMapCache(CcTest::i_isolate()->context());
20568 CHECK_LE(1, elements);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020569
Ben Murdochda12d292016-06-02 14:46:10 +010020570 // We have to abort incremental marking here to abandon black pages.
20571 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020572
20573 CHECK_GT(elements, CountLiveMapsInMapCache(CcTest::i_isolate()->context()));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020574}
20575
20576
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020577THREADED_TEST(Regress93759) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020578 v8::Isolate* isolate = CcTest::isolate();
20579 HandleScope scope(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020580
20581 // Template for object with security check.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020582 Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020583 no_proto_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020584
20585 // Templates for objects with hidden prototypes and possibly security check.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020586 Local<FunctionTemplate> hidden_proto_template =
20587 v8::FunctionTemplate::New(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020588 hidden_proto_template->SetHiddenPrototype(true);
20589
20590 Local<FunctionTemplate> protected_hidden_proto_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020591 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020592 protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallback(
20593 AccessAlwaysBlocked);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020594 protected_hidden_proto_template->SetHiddenPrototype(true);
20595
20596 // Context for "foreign" objects used in test.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020597 Local<Context> context = v8::Context::New(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020598 context->Enter();
20599
20600 // Plain object, no security check.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020601 Local<Object> simple_object = Object::New(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020602
20603 // Object with explicit security check.
20604 Local<Object> protected_object =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020605 no_proto_template->NewInstance(context).ToLocalChecked();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020606
20607 // JSGlobalProxy object, always have security check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020608 Local<Object> proxy_object = context->Global();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020609
20610 // Global object, the prototype of proxy_object. No security checks.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020611 Local<Object> global_object =
20612 proxy_object->GetPrototype()->ToObject(context).ToLocalChecked();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020613
20614 // Hidden prototype without security check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020615 Local<Object> hidden_prototype = hidden_proto_template->GetFunction(context)
20616 .ToLocalChecked()
20617 ->NewInstance(context)
20618 .ToLocalChecked();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020619 Local<Object> object_with_hidden =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020620 Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020621 object_with_hidden->SetPrototype(context, hidden_prototype).FromJust();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020622
20623 context->Exit();
20624
Ben Murdoch097c5b22016-05-18 11:27:45 +010020625 LocalContext context2;
20626 v8::Local<v8::Object> global = context2->Global();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020627
Ben Murdoch097c5b22016-05-18 11:27:45 +010020628 // Setup global variables.
20629 CHECK(global->Set(context2.local(), v8_str("simple"), simple_object)
20630 .FromJust());
20631 CHECK(global->Set(context2.local(), v8_str("protected"), protected_object)
20632 .FromJust());
20633 CHECK(global->Set(context2.local(), v8_str("global"), global_object)
20634 .FromJust());
20635 CHECK(
20636 global->Set(context2.local(), v8_str("proxy"), proxy_object).FromJust());
20637 CHECK(global->Set(context2.local(), v8_str("hidden"), object_with_hidden)
20638 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020639
20640 Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020641 CHECK(result1->Equals(context2.local(), simple_object->GetPrototype())
20642 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020643
20644 Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020645 CHECK(result2->IsNull());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020646
20647 Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020648 CHECK(result3->Equals(context2.local(), global_object->GetPrototype())
20649 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020650
20651 Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020652 CHECK(result4->IsNull());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020653
20654 Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020655 CHECK(result5->Equals(context2.local(), object_with_hidden->GetPrototype()
20656 ->ToObject(context2.local())
20657 .ToLocalChecked()
20658 ->GetPrototype())
20659 .FromJust());
Ben Murdoch5710cea2012-05-21 14:52:42 +010020660}
20661
20662
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020663static void TestReceiver(Local<Value> expected_result,
20664 Local<Value> expected_receiver,
20665 const char* code) {
20666 Local<Value> result = CompileRun(code);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020667 Local<Context> context = CcTest::isolate()->GetCurrentContext();
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020668 CHECK(result->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020669 CHECK(expected_receiver
20670 ->Equals(context,
20671 result.As<v8::Object>()->Get(context, 1).ToLocalChecked())
20672 .FromJust());
20673 CHECK(expected_result
20674 ->Equals(context,
20675 result.As<v8::Object>()->Get(context, 0).ToLocalChecked())
20676 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020677}
20678
20679
20680THREADED_TEST(ForeignFunctionReceiver) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020681 v8::Isolate* isolate = CcTest::isolate();
20682 HandleScope scope(isolate);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020683
20684 // Create two contexts with different "id" properties ('i' and 'o').
20685 // Call a function both from its own context and from a the foreign
20686 // context, and see what "this" is bound to (returning both "this"
20687 // and "this.id" for comparison).
20688
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020689 Local<Context> foreign_context = v8::Context::New(isolate);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020690 foreign_context->Enter();
20691 Local<Value> foreign_function =
20692 CompileRun("function func() { return { 0: this.id, "
20693 " 1: this, "
20694 " toString: function() { "
20695 " return this[0];"
20696 " }"
20697 " };"
20698 "}"
20699 "var id = 'i';"
20700 "func;");
20701 CHECK(foreign_function->IsFunction());
20702 foreign_context->Exit();
20703
20704 LocalContext context;
20705
20706 Local<String> password = v8_str("Password");
20707 // Don't get hit by security checks when accessing foreign_context's
20708 // global receiver (aka. global proxy).
20709 context->SetSecurityToken(password);
20710 foreign_context->SetSecurityToken(password);
20711
20712 Local<String> i = v8_str("i");
20713 Local<String> o = v8_str("o");
20714 Local<String> id = v8_str("id");
20715
20716 CompileRun("function ownfunc() { return { 0: this.id, "
20717 " 1: this, "
20718 " toString: function() { "
20719 " return this[0];"
20720 " }"
20721 " };"
20722 "}"
20723 "var id = 'o';"
20724 "ownfunc");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020725 CHECK(context->Global()
20726 ->Set(context.local(), v8_str("func"), foreign_function)
20727 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020728
20729 // Sanity check the contexts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020730 CHECK(
20731 i->Equals(
20732 context.local(),
20733 foreign_context->Global()->Get(context.local(), id).ToLocalChecked())
20734 .FromJust());
20735 CHECK(o->Equals(context.local(),
20736 context->Global()->Get(context.local(), id).ToLocalChecked())
20737 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020738
20739 // Checking local function's receiver.
20740 // Calling function using its call/apply methods.
20741 TestReceiver(o, context->Global(), "ownfunc.call()");
20742 TestReceiver(o, context->Global(), "ownfunc.apply()");
20743 // Making calls through built-in functions.
20744 TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020745 CHECK(
20746 o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/,ownfunc)[1]"))
20747 .FromJust());
20748 CHECK(
20749 o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]"))
20750 .FromJust());
20751 CHECK(
20752 o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]"))
20753 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020754 // Calling with environment record as base.
20755 TestReceiver(o, context->Global(), "ownfunc()");
20756 // Calling with no base.
20757 TestReceiver(o, context->Global(), "(1,ownfunc)()");
20758
20759 // Checking foreign function return value.
20760 // Calling function using its call/apply methods.
20761 TestReceiver(i, foreign_context->Global(), "func.call()");
20762 TestReceiver(i, foreign_context->Global(), "func.apply()");
20763 // Calling function using another context's call/apply methods.
20764 TestReceiver(i, foreign_context->Global(),
20765 "Function.prototype.call.call(func)");
20766 TestReceiver(i, foreign_context->Global(),
20767 "Function.prototype.call.apply(func)");
20768 TestReceiver(i, foreign_context->Global(),
20769 "Function.prototype.apply.call(func)");
20770 TestReceiver(i, foreign_context->Global(),
20771 "Function.prototype.apply.apply(func)");
20772 // Making calls through built-in functions.
20773 TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
20774 // ToString(func()) is func()[0], i.e., the returned this.id.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020775 CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/,func)[1]"))
20776 .FromJust());
20777 CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,func)[1]"))
20778 .FromJust());
20779 CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,func)[3]"))
20780 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020781
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020782 // Calling with environment record as base.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020783 TestReceiver(i, foreign_context->Global(), "func()");
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020784 // Calling with no base.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020785 TestReceiver(i, foreign_context->Global(), "(1,func)()");
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020786}
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020787
20788
20789uint8_t callback_fired = 0;
Ben Murdoch097c5b22016-05-18 11:27:45 +010020790uint8_t before_call_entered_callback_count1 = 0;
20791uint8_t before_call_entered_callback_count2 = 0;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020792
20793
Ben Murdoch097c5b22016-05-18 11:27:45 +010020794void CallCompletedCallback1(v8::Isolate*) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020795 v8::base::OS::Print("Firing callback 1.\n");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020796 callback_fired ^= 1; // Toggle first bit.
20797}
20798
20799
Ben Murdoch097c5b22016-05-18 11:27:45 +010020800void CallCompletedCallback2(v8::Isolate*) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020801 v8::base::OS::Print("Firing callback 2.\n");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020802 callback_fired ^= 2; // Toggle second bit.
20803}
20804
20805
Ben Murdoch097c5b22016-05-18 11:27:45 +010020806void BeforeCallEnteredCallback1(v8::Isolate*) {
20807 v8::base::OS::Print("Firing before call entered callback 1.\n");
20808 before_call_entered_callback_count1++;
20809}
20810
20811
20812void BeforeCallEnteredCallback2(v8::Isolate*) {
20813 v8::base::OS::Print("Firing before call entered callback 2.\n");
20814 before_call_entered_callback_count2++;
20815}
20816
20817
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020818void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020819 int32_t level =
20820 args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020821 if (level < 3) {
20822 level++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020823 v8::base::OS::Print("Entering recursion level %d.\n", level);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020824 char script[64];
20825 i::Vector<char> script_vector(script, sizeof(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020826 i::SNPrintF(script_vector, "recursion(%d)", level);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020827 CompileRun(script_vector.start());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020828 v8::base::OS::Print("Leaving recursion level %d.\n", level);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020829 CHECK_EQ(0, callback_fired);
20830 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020831 v8::base::OS::Print("Recursion ends.\n");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020832 CHECK_EQ(0, callback_fired);
20833 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020834}
20835
20836
20837TEST(CallCompletedCallback) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020838 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020839 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020840 v8::Local<v8::FunctionTemplate> recursive_runtime =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020841 v8::FunctionTemplate::New(env->GetIsolate(), RecursiveCall);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020842 env->Global()
20843 ->Set(env.local(), v8_str("recursion"),
20844 recursive_runtime->GetFunction(env.local()).ToLocalChecked())
20845 .FromJust();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020846 // Adding the same callback a second time has no effect.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020847 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
20848 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
20849 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback2);
Ben Murdoch097c5b22016-05-18 11:27:45 +010020850 env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback1);
20851 env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback2);
20852 env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020853 v8::base::OS::Print("--- Script (1) ---\n");
Ben Murdoch097c5b22016-05-18 11:27:45 +010020854 callback_fired = 0;
20855 before_call_entered_callback_count1 = 0;
20856 before_call_entered_callback_count2 = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020857 Local<Script> script =
20858 v8::Script::Compile(env.local(), v8_str("recursion(0)")).ToLocalChecked();
20859 script->Run(env.local()).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020860 CHECK_EQ(3, callback_fired);
Ben Murdoch097c5b22016-05-18 11:27:45 +010020861 CHECK_EQ(4, before_call_entered_callback_count1);
20862 CHECK_EQ(4, before_call_entered_callback_count2);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020863
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020864 v8::base::OS::Print("\n--- Script (2) ---\n");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020865 callback_fired = 0;
Ben Murdoch097c5b22016-05-18 11:27:45 +010020866 before_call_entered_callback_count1 = 0;
20867 before_call_entered_callback_count2 = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020868 env->GetIsolate()->RemoveCallCompletedCallback(CallCompletedCallback1);
Ben Murdoch097c5b22016-05-18 11:27:45 +010020869 env->GetIsolate()->RemoveBeforeCallEnteredCallback(
20870 BeforeCallEnteredCallback1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020871 script->Run(env.local()).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020872 CHECK_EQ(2, callback_fired);
Ben Murdoch097c5b22016-05-18 11:27:45 +010020873 CHECK_EQ(0, before_call_entered_callback_count1);
20874 CHECK_EQ(4, before_call_entered_callback_count2);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020875
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020876 v8::base::OS::Print("\n--- Function ---\n");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020877 callback_fired = 0;
Ben Murdoch097c5b22016-05-18 11:27:45 +010020878 before_call_entered_callback_count1 = 0;
20879 before_call_entered_callback_count2 = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020880 Local<Function> recursive_function = Local<Function>::Cast(
20881 env->Global()->Get(env.local(), v8_str("recursion")).ToLocalChecked());
20882 v8::Local<Value> args[] = {v8_num(0)};
20883 recursive_function->Call(env.local(), env->Global(), 1, args)
20884 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020885 CHECK_EQ(2, callback_fired);
Ben Murdoch097c5b22016-05-18 11:27:45 +010020886 CHECK_EQ(0, before_call_entered_callback_count1);
20887 CHECK_EQ(4, before_call_entered_callback_count2);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020888}
20889
20890
Ben Murdoch097c5b22016-05-18 11:27:45 +010020891void CallCompletedCallbackNoException(v8::Isolate*) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020892 v8::HandleScope scope(CcTest::isolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020893 CompileRun("1+1;");
20894}
20895
20896
Ben Murdoch097c5b22016-05-18 11:27:45 +010020897void CallCompletedCallbackException(v8::Isolate*) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020898 v8::HandleScope scope(CcTest::isolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020899 CompileRun("throw 'second exception';");
20900}
20901
20902
20903TEST(CallCompletedCallbackOneException) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020904 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020905 v8::HandleScope scope(env->GetIsolate());
20906 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackNoException);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020907 CompileRun("throw 'exception';");
20908}
20909
20910
20911TEST(CallCompletedCallbackTwoExceptions) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020912 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020913 v8::HandleScope scope(env->GetIsolate());
20914 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackException);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020915 CompileRun("throw 'first exception';");
20916}
20917
20918
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020919static void MicrotaskOne(const v8::FunctionCallbackInfo<Value>& info) {
20920 v8::HandleScope scope(info.GetIsolate());
Ben Murdochda12d292016-06-02 14:46:10 +010020921 v8::MicrotasksScope microtasks(info.GetIsolate(),
20922 v8::MicrotasksScope::kDoNotRunMicrotasks);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020923 CompileRun("ext1Calls++;");
20924}
20925
20926
20927static void MicrotaskTwo(const v8::FunctionCallbackInfo<Value>& info) {
20928 v8::HandleScope scope(info.GetIsolate());
Ben Murdochda12d292016-06-02 14:46:10 +010020929 v8::MicrotasksScope microtasks(info.GetIsolate(),
20930 v8::MicrotasksScope::kDoNotRunMicrotasks);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020931 CompileRun("ext2Calls++;");
20932}
20933
20934
20935void* g_passed_to_three = NULL;
20936
20937
20938static void MicrotaskThree(void* data) {
20939 g_passed_to_three = data;
20940}
20941
20942
20943TEST(EnqueueMicrotask) {
20944 LocalContext env;
20945 v8::HandleScope scope(env->GetIsolate());
20946 CompileRun(
20947 "var ext1Calls = 0;"
20948 "var ext2Calls = 0;");
20949 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020950 CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20951 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020952
20953 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020954 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020955 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020956 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20957 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020958
20959 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020960 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020961 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020962 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020963 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020964 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20965 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020966
20967 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020968 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020969 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020970 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20971 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020972
20973 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020974 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20975 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020976
20977 g_passed_to_three = NULL;
20978 env->GetIsolate()->EnqueueMicrotask(MicrotaskThree);
20979 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020980 CHECK(!g_passed_to_three);
20981 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20982 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020983
20984 int dummy;
20985 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020986 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020987 env->GetIsolate()->EnqueueMicrotask(MicrotaskThree, &dummy);
20988 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020989 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020990 CompileRun("1+1;");
20991 CHECK_EQ(&dummy, g_passed_to_three);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020992 CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20993 CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020994 g_passed_to_three = NULL;
20995}
20996
20997
20998static void MicrotaskExceptionOne(
20999 const v8::FunctionCallbackInfo<Value>& info) {
21000 v8::HandleScope scope(info.GetIsolate());
21001 CompileRun("exception1Calls++;");
21002 info.GetIsolate()->ThrowException(
21003 v8::Exception::Error(v8_str("first")));
21004}
21005
21006
21007static void MicrotaskExceptionTwo(
21008 const v8::FunctionCallbackInfo<Value>& info) {
21009 v8::HandleScope scope(info.GetIsolate());
21010 CompileRun("exception2Calls++;");
21011 info.GetIsolate()->ThrowException(
21012 v8::Exception::Error(v8_str("second")));
21013}
21014
21015
21016TEST(RunMicrotasksIgnoresThrownExceptions) {
21017 LocalContext env;
21018 v8::Isolate* isolate = env->GetIsolate();
21019 v8::HandleScope scope(isolate);
21020 CompileRun(
21021 "var exception1Calls = 0;"
21022 "var exception2Calls = 0;");
21023 isolate->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021024 Function::New(env.local(), MicrotaskExceptionOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021025 isolate->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021026 Function::New(env.local(), MicrotaskExceptionTwo).ToLocalChecked());
21027 TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021028 CompileRun("1+1;");
21029 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021030 CHECK_EQ(1,
21031 CompileRun("exception1Calls")->Int32Value(env.local()).FromJust());
21032 CHECK_EQ(1,
21033 CompileRun("exception2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021034}
21035
21036
Ben Murdochda12d292016-06-02 14:46:10 +010021037uint8_t microtasks_completed_callback_count = 0;
21038
21039
21040static void MicrotasksCompletedCallback(v8::Isolate* isolate) {
21041 ++microtasks_completed_callback_count;
21042}
21043
21044
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021045TEST(SetAutorunMicrotasks) {
21046 LocalContext env;
21047 v8::HandleScope scope(env->GetIsolate());
Ben Murdochda12d292016-06-02 14:46:10 +010021048 env->GetIsolate()->AddMicrotasksCompletedCallback(
21049 &MicrotasksCompletedCallback);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021050 CompileRun(
21051 "var ext1Calls = 0;"
21052 "var ext2Calls = 0;");
21053 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021054 CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21055 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochda12d292016-06-02 14:46:10 +010021056 CHECK_EQ(0u, microtasks_completed_callback_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021057
21058 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021059 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021060 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021061 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21062 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochda12d292016-06-02 14:46:10 +010021063 CHECK_EQ(1u, microtasks_completed_callback_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021064
Ben Murdochda12d292016-06-02 14:46:10 +010021065 env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021066 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021067 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021068 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021069 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021070 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021071 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21072 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochda12d292016-06-02 14:46:10 +010021073 CHECK_EQ(1u, microtasks_completed_callback_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021074
21075 env->GetIsolate()->RunMicrotasks();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021076 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21077 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochda12d292016-06-02 14:46:10 +010021078 CHECK_EQ(2u, microtasks_completed_callback_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021079
21080 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021081 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021082 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021083 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21084 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochda12d292016-06-02 14:46:10 +010021085 CHECK_EQ(2u, microtasks_completed_callback_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021086
21087 env->GetIsolate()->RunMicrotasks();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021088 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21089 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochda12d292016-06-02 14:46:10 +010021090 CHECK_EQ(3u, microtasks_completed_callback_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021091
Ben Murdochda12d292016-06-02 14:46:10 +010021092 env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021093 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021094 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021095 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021096 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21097 CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochda12d292016-06-02 14:46:10 +010021098 CHECK_EQ(4u, microtasks_completed_callback_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021099
21100 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021101 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021102 {
21103 v8::Isolate::SuppressMicrotaskExecutionScope scope(env->GetIsolate());
21104 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021105 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21106 CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochda12d292016-06-02 14:46:10 +010021107 CHECK_EQ(4u, microtasks_completed_callback_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021108 }
21109
21110 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021111 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21112 CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochda12d292016-06-02 14:46:10 +010021113 CHECK_EQ(5u, microtasks_completed_callback_count);
21114
21115 env->GetIsolate()->RemoveMicrotasksCompletedCallback(
21116 &MicrotasksCompletedCallback);
21117 env->GetIsolate()->EnqueueMicrotask(
21118 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
21119 CompileRun("1+1;");
21120 CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21121 CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21122 CHECK_EQ(5u, microtasks_completed_callback_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021123}
21124
21125
21126TEST(RunMicrotasksWithoutEnteringContext) {
21127 v8::Isolate* isolate = CcTest::isolate();
21128 HandleScope handle_scope(isolate);
Ben Murdochda12d292016-06-02 14:46:10 +010021129 isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021130 Local<Context> context = Context::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021131 {
21132 Context::Scope context_scope(context);
21133 CompileRun("var ext1Calls = 0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021134 isolate->EnqueueMicrotask(
21135 Function::New(context, MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021136 }
21137 isolate->RunMicrotasks();
21138 {
21139 Context::Scope context_scope(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021140 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021141 }
Ben Murdochda12d292016-06-02 14:46:10 +010021142 isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto);
21143}
21144
21145
21146TEST(ScopedMicrotasks) {
21147 LocalContext env;
21148 v8::HandleScope handles(env->GetIsolate());
21149 env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kScoped);
21150 {
21151 v8::MicrotasksScope scope1(env->GetIsolate(),
21152 v8::MicrotasksScope::kDoNotRunMicrotasks);
21153 env->GetIsolate()->EnqueueMicrotask(
21154 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
21155 CompileRun(
21156 "var ext1Calls = 0;"
21157 "var ext2Calls = 0;");
21158 CompileRun("1+1;");
21159 CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21160 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21161 {
21162 v8::MicrotasksScope scope2(env->GetIsolate(),
21163 v8::MicrotasksScope::kRunMicrotasks);
21164 CompileRun("1+1;");
21165 CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21166 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21167 {
21168 v8::MicrotasksScope scope3(env->GetIsolate(),
21169 v8::MicrotasksScope::kRunMicrotasks);
21170 CompileRun("1+1;");
21171 CHECK_EQ(0,
21172 CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21173 CHECK_EQ(0,
21174 CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21175 }
21176 CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21177 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21178 }
21179 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21180 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21181 env->GetIsolate()->EnqueueMicrotask(
21182 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
21183 }
21184
21185 {
21186 v8::MicrotasksScope scope(env->GetIsolate(),
21187 v8::MicrotasksScope::kDoNotRunMicrotasks);
21188 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21189 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21190 }
21191
21192 {
21193 v8::MicrotasksScope scope1(env->GetIsolate(),
21194 v8::MicrotasksScope::kRunMicrotasks);
21195 CompileRun("1+1;");
21196 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21197 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21198 {
21199 v8::MicrotasksScope scope2(env->GetIsolate(),
21200 v8::MicrotasksScope::kDoNotRunMicrotasks);
21201 }
21202 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21203 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21204 }
21205
21206 {
21207 v8::MicrotasksScope scope(env->GetIsolate(),
21208 v8::MicrotasksScope::kDoNotRunMicrotasks);
21209 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21210 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21211 env->GetIsolate()->EnqueueMicrotask(
21212 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
21213 }
21214
21215 {
21216 v8::Isolate::SuppressMicrotaskExecutionScope scope1(env->GetIsolate());
21217 {
21218 v8::MicrotasksScope scope2(env->GetIsolate(),
21219 v8::MicrotasksScope::kRunMicrotasks);
21220 }
21221 v8::MicrotasksScope scope3(env->GetIsolate(),
21222 v8::MicrotasksScope::kDoNotRunMicrotasks);
21223 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21224 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21225 }
21226
21227 {
21228 v8::MicrotasksScope scope1(env->GetIsolate(),
21229 v8::MicrotasksScope::kRunMicrotasks);
21230 v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
21231 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21232 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21233 }
21234
21235 {
21236 v8::MicrotasksScope scope(env->GetIsolate(),
21237 v8::MicrotasksScope::kDoNotRunMicrotasks);
21238 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21239 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21240 }
21241
21242 v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
21243
21244 {
21245 v8::MicrotasksScope scope(env->GetIsolate(),
21246 v8::MicrotasksScope::kDoNotRunMicrotasks);
21247 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21248 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21249 env->GetIsolate()->EnqueueMicrotask(
21250 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
21251 }
21252
21253 v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
21254
21255 {
21256 v8::MicrotasksScope scope(env->GetIsolate(),
21257 v8::MicrotasksScope::kDoNotRunMicrotasks);
21258 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21259 CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21260 }
21261
21262 env->GetIsolate()->EnqueueMicrotask(
21263 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
21264 {
21265 v8::Isolate::SuppressMicrotaskExecutionScope scope1(env->GetIsolate());
21266 v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
21267 v8::MicrotasksScope scope2(env->GetIsolate(),
21268 v8::MicrotasksScope::kDoNotRunMicrotasks);
21269 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21270 CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21271 }
21272
21273 v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
21274
21275 {
21276 v8::MicrotasksScope scope(env->GetIsolate(),
21277 v8::MicrotasksScope::kDoNotRunMicrotasks);
21278 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21279 CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21280 }
21281
21282 env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021283}
21284
21285
21286static void DebugEventInObserver(const v8::Debug::EventDetails& event_details) {
21287 v8::DebugEvent event = event_details.GetEvent();
21288 if (event != v8::Break) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021289 Local<Object> exec_state = event_details.GetExecutionState();
21290 Local<Context> context = CcTest::isolate()->GetCurrentContext();
21291 Local<Value> break_id =
21292 exec_state->Get(context, v8_str("break_id")).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021293 CompileRun("function f(id) { new FrameDetails(id, 0); }");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021294 Local<Function> fun = Local<Function>::Cast(
21295 CcTest::global()->Get(context, v8_str("f")).ToLocalChecked());
21296 fun->Call(context, CcTest::global(), 1, &break_id).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021297}
21298
21299
21300TEST(Regress385349) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021301 i::FLAG_harmony_object_observe = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021302 i::FLAG_allow_natives_syntax = true;
21303 v8::Isolate* isolate = CcTest::isolate();
21304 HandleScope handle_scope(isolate);
Ben Murdochda12d292016-06-02 14:46:10 +010021305 isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021306 Local<Context> context = Context::New(isolate);
21307 v8::Debug::SetDebugEventListener(isolate, DebugEventInObserver);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021308 {
21309 Context::Scope context_scope(context);
21310 CompileRun("var obj = {};"
21311 "Object.observe(obj, function(changes) { debugger; });"
21312 "obj.a = 0;");
21313 }
21314 isolate->RunMicrotasks();
Ben Murdochda12d292016-06-02 14:46:10 +010021315 isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021316 v8::Debug::SetDebugEventListener(isolate, nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021317}
21318
21319
Emily Bernierd0a1eb72015-03-24 16:35:39 -040021320#ifdef ENABLE_DISASSEMBLER
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021321static int probes_counter = 0;
21322static int misses_counter = 0;
21323static int updates_counter = 0;
21324
21325
21326static int* LookupCounter(const char* name) {
21327 if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
21328 return &probes_counter;
21329 } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
21330 return &misses_counter;
21331 } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
21332 return &updates_counter;
21333 }
21334 return NULL;
21335}
21336
21337
21338static const char* kMegamorphicTestProgram =
21339 "function ClassA() { };"
21340 "function ClassB() { };"
21341 "ClassA.prototype.foo = function() { };"
21342 "ClassB.prototype.foo = function() { };"
21343 "function fooify(obj) { obj.foo(); };"
21344 "var a = new ClassA();"
21345 "var b = new ClassB();"
21346 "for (var i = 0; i < 10000; i++) {"
21347 " fooify(a);"
21348 " fooify(b);"
21349 "}";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021350#endif
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021351
21352
21353static void StubCacheHelper(bool primary) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040021354#ifdef ENABLE_DISASSEMBLER
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021355 i::FLAG_native_code_counters = true;
21356 if (primary) {
21357 i::FLAG_test_primary_stub_cache = true;
21358 } else {
21359 i::FLAG_test_secondary_stub_cache = true;
21360 }
21361 i::FLAG_crankshaft = false;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021362 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021363 env->GetIsolate()->SetCounterFunction(LookupCounter);
21364 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021365 int initial_probes = probes_counter;
21366 int initial_misses = misses_counter;
21367 int initial_updates = updates_counter;
21368 CompileRun(kMegamorphicTestProgram);
21369 int probes = probes_counter - initial_probes;
21370 int misses = misses_counter - initial_misses;
21371 int updates = updates_counter - initial_updates;
21372 CHECK_LT(updates, 10);
21373 CHECK_LT(misses, 10);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021374 // TODO(verwaest): Update this test to overflow the degree of polymorphism
21375 // before megamorphism. The number of probes will only work once we teach the
21376 // serializer to embed references to counters in the stubs, given that the
21377 // megamorphic_stub_cache_probes is updated in a snapshot-generated stub.
21378 CHECK_GE(probes, 0);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021379#endif
21380}
21381
21382
21383TEST(SecondaryStubCache) {
21384 StubCacheHelper(true);
21385}
21386
21387
21388TEST(PrimaryStubCache) {
21389 StubCacheHelper(false);
21390}
21391
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021392
21393#ifdef DEBUG
21394static int cow_arrays_created_runtime = 0;
21395
21396
21397static int* LookupCounterCOWArrays(const char* name) {
21398 if (strcmp(name, "c:V8.COWArraysCreatedRuntime") == 0) {
21399 return &cow_arrays_created_runtime;
21400 }
21401 return NULL;
21402}
21403#endif
21404
21405
21406TEST(CheckCOWArraysCreatedRuntimeCounter) {
21407#ifdef DEBUG
21408 i::FLAG_native_code_counters = true;
21409 LocalContext env;
21410 env->GetIsolate()->SetCounterFunction(LookupCounterCOWArrays);
21411 v8::HandleScope scope(env->GetIsolate());
21412 int initial_cow_arrays = cow_arrays_created_runtime;
21413 CompileRun("var o = [1, 2, 3];");
21414 CHECK_EQ(1, cow_arrays_created_runtime - initial_cow_arrays);
21415 CompileRun("var o = {foo: [4, 5, 6], bar: [3, 0]};");
21416 CHECK_EQ(3, cow_arrays_created_runtime - initial_cow_arrays);
21417 CompileRun("var o = {foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'};");
21418 CHECK_EQ(4, cow_arrays_created_runtime - initial_cow_arrays);
21419#endif
21420}
21421
21422
21423TEST(StaticGetters) {
21424 LocalContext context;
21425 i::Factory* factory = CcTest::i_isolate()->factory();
21426 v8::Isolate* isolate = CcTest::isolate();
21427 v8::HandleScope scope(isolate);
21428 i::Handle<i::Object> undefined_value = factory->undefined_value();
21429 CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
21430 i::Handle<i::Object> null_value = factory->null_value();
21431 CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
21432 i::Handle<i::Object> true_value = factory->true_value();
21433 CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
21434 i::Handle<i::Object> false_value = factory->false_value();
21435 CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
21436}
21437
21438
21439UNINITIALIZED_TEST(IsolateEmbedderData) {
21440 CcTest::DisableAutomaticDispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021441 v8::Isolate::CreateParams create_params;
21442 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
21443 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021444 isolate->Enter();
21445 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
21446 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021447 CHECK(!isolate->GetData(slot));
21448 CHECK(!i_isolate->GetData(slot));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021449 }
21450 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
21451 void* data = reinterpret_cast<void*>(0xacce55ed + slot);
21452 isolate->SetData(slot, data);
21453 }
21454 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
21455 void* data = reinterpret_cast<void*>(0xacce55ed + slot);
21456 CHECK_EQ(data, isolate->GetData(slot));
21457 CHECK_EQ(data, i_isolate->GetData(slot));
21458 }
21459 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
21460 void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
21461 isolate->SetData(slot, data);
21462 }
21463 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
21464 void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
21465 CHECK_EQ(data, isolate->GetData(slot));
21466 CHECK_EQ(data, i_isolate->GetData(slot));
21467 }
21468 isolate->Exit();
21469 isolate->Dispose();
21470}
21471
21472
21473TEST(StringEmpty) {
21474 LocalContext context;
21475 i::Factory* factory = CcTest::i_isolate()->factory();
21476 v8::Isolate* isolate = CcTest::isolate();
21477 v8::HandleScope scope(isolate);
21478 i::Handle<i::Object> empty_string = factory->empty_string();
21479 CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
21480}
21481
21482
21483static int instance_checked_getter_count = 0;
21484static void InstanceCheckedGetter(
21485 Local<String> name,
21486 const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021487 CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
21488 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021489 instance_checked_getter_count++;
21490 info.GetReturnValue().Set(v8_num(11));
21491}
21492
21493
21494static int instance_checked_setter_count = 0;
21495static void InstanceCheckedSetter(Local<String> name,
21496 Local<Value> value,
21497 const v8::PropertyCallbackInfo<void>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021498 CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
21499 .FromJust());
21500 CHECK(value->Equals(info.GetIsolate()->GetCurrentContext(), v8_num(23))
21501 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021502 instance_checked_setter_count++;
21503}
21504
21505
21506static void CheckInstanceCheckedResult(int getters, int setters,
21507 bool expects_callbacks,
21508 TryCatch* try_catch) {
21509 if (expects_callbacks) {
21510 CHECK(!try_catch->HasCaught());
21511 CHECK_EQ(getters, instance_checked_getter_count);
21512 CHECK_EQ(setters, instance_checked_setter_count);
21513 } else {
21514 CHECK(try_catch->HasCaught());
21515 CHECK_EQ(0, instance_checked_getter_count);
21516 CHECK_EQ(0, instance_checked_setter_count);
21517 }
21518 try_catch->Reset();
21519}
21520
21521
21522static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
21523 instance_checked_getter_count = 0;
21524 instance_checked_setter_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021525 TryCatch try_catch(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021526
21527 // Test path through generic runtime code.
21528 CompileRun("obj.foo");
21529 CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
21530 CompileRun("obj.foo = 23");
21531 CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
21532
21533 // Test path through generated LoadIC and StoredIC.
21534 CompileRun("function test_get(o) { o.foo; }"
21535 "test_get(obj);");
21536 CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
21537 CompileRun("test_get(obj);");
21538 CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
21539 CompileRun("test_get(obj);");
21540 CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
21541 CompileRun("function test_set(o) { o.foo = 23; }"
21542 "test_set(obj);");
21543 CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
21544 CompileRun("test_set(obj);");
21545 CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
21546 CompileRun("test_set(obj);");
21547 CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
21548
21549 // Test path through optimized code.
21550 CompileRun("%OptimizeFunctionOnNextCall(test_get);"
21551 "test_get(obj);");
21552 CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
21553 CompileRun("%OptimizeFunctionOnNextCall(test_set);"
21554 "test_set(obj);");
21555 CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
21556
21557 // Cleanup so that closures start out fresh in next check.
21558 CompileRun("%DeoptimizeFunction(test_get);"
21559 "%ClearFunctionTypeFeedback(test_get);"
21560 "%DeoptimizeFunction(test_set);"
21561 "%ClearFunctionTypeFeedback(test_set);");
21562}
21563
21564
21565THREADED_TEST(InstanceCheckOnInstanceAccessor) {
21566 v8::internal::FLAG_allow_natives_syntax = true;
21567 LocalContext context;
21568 v8::HandleScope scope(context->GetIsolate());
21569
21570 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
21571 Local<ObjectTemplate> inst = templ->InstanceTemplate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021572 inst->SetAccessor(v8_str("foo"), InstanceCheckedGetter, InstanceCheckedSetter,
21573 Local<Value>(), v8::DEFAULT, v8::None,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021574 v8::AccessorSignature::New(context->GetIsolate(), templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021575 CHECK(context->Global()
21576 ->Set(context.local(), v8_str("f"),
21577 templ->GetFunction(context.local()).ToLocalChecked())
21578 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021579
21580 printf("Testing positive ...\n");
21581 CompileRun("var obj = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021582 CHECK(templ->HasInstance(
21583 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021584 CheckInstanceCheckedAccessors(true);
21585
21586 printf("Testing negative ...\n");
21587 CompileRun("var obj = {};"
21588 "obj.__proto__ = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021589 CHECK(!templ->HasInstance(
21590 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021591 CheckInstanceCheckedAccessors(false);
21592}
21593
21594
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021595static void EmptyInterceptorGetter(
21596 Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {}
21597
21598
21599static void EmptyInterceptorSetter(
21600 Local<String> name, Local<Value> value,
21601 const v8::PropertyCallbackInfo<v8::Value>& info) {}
21602
21603
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021604THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
21605 v8::internal::FLAG_allow_natives_syntax = true;
21606 LocalContext context;
21607 v8::HandleScope scope(context->GetIsolate());
21608
21609 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
21610 Local<ObjectTemplate> inst = templ->InstanceTemplate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021611 templ->InstanceTemplate()->SetNamedPropertyHandler(EmptyInterceptorGetter,
21612 EmptyInterceptorSetter);
21613 inst->SetAccessor(v8_str("foo"), InstanceCheckedGetter, InstanceCheckedSetter,
21614 Local<Value>(), v8::DEFAULT, v8::None,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021615 v8::AccessorSignature::New(context->GetIsolate(), templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021616 CHECK(context->Global()
21617 ->Set(context.local(), v8_str("f"),
21618 templ->GetFunction(context.local()).ToLocalChecked())
21619 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021620
21621 printf("Testing positive ...\n");
21622 CompileRun("var obj = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021623 CHECK(templ->HasInstance(
21624 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021625 CheckInstanceCheckedAccessors(true);
21626
21627 printf("Testing negative ...\n");
21628 CompileRun("var obj = {};"
21629 "obj.__proto__ = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021630 CHECK(!templ->HasInstance(
21631 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021632 CheckInstanceCheckedAccessors(false);
21633}
21634
21635
21636THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
21637 v8::internal::FLAG_allow_natives_syntax = true;
21638 LocalContext context;
21639 v8::HandleScope scope(context->GetIsolate());
21640
21641 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
21642 Local<ObjectTemplate> proto = templ->PrototypeTemplate();
21643 proto->SetAccessor(v8_str("foo"), InstanceCheckedGetter,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021644 InstanceCheckedSetter, Local<Value>(), v8::DEFAULT,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021645 v8::None,
21646 v8::AccessorSignature::New(context->GetIsolate(), templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021647 CHECK(context->Global()
21648 ->Set(context.local(), v8_str("f"),
21649 templ->GetFunction(context.local()).ToLocalChecked())
21650 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021651
21652 printf("Testing positive ...\n");
21653 CompileRun("var obj = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021654 CHECK(templ->HasInstance(
21655 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021656 CheckInstanceCheckedAccessors(true);
21657
21658 printf("Testing negative ...\n");
21659 CompileRun("var obj = {};"
21660 "obj.__proto__ = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021661 CHECK(!templ->HasInstance(
21662 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021663 CheckInstanceCheckedAccessors(false);
21664
21665 printf("Testing positive with modified prototype chain ...\n");
21666 CompileRun("var obj = new f();"
21667 "var pro = {};"
21668 "pro.__proto__ = obj.__proto__;"
21669 "obj.__proto__ = pro;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021670 CHECK(templ->HasInstance(
21671 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021672 CheckInstanceCheckedAccessors(true);
21673}
21674
21675
21676TEST(TryFinallyMessage) {
21677 LocalContext context;
21678 v8::HandleScope scope(context->GetIsolate());
21679 {
21680 // Test that the original error message is not lost if there is a
21681 // recursive call into Javascript is done in the finally block, e.g. to
21682 // initialize an IC. (crbug.com/129171)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021683 TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021684 const char* trigger_ic =
21685 "try { \n"
21686 " throw new Error('test'); \n"
21687 "} finally { \n"
21688 " var x = 0; \n"
21689 " x++; \n" // Trigger an IC initialization here.
21690 "} \n";
21691 CompileRun(trigger_ic);
21692 CHECK(try_catch.HasCaught());
21693 Local<Message> message = try_catch.Message();
21694 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021695 CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021696 }
21697
21698 {
21699 // Test that the original exception message is indeed overwritten if
21700 // a new error is thrown in the finally block.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021701 TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021702 const char* throw_again =
21703 "try { \n"
21704 " throw new Error('test'); \n"
21705 "} finally { \n"
21706 " var x = 0; \n"
21707 " x++; \n"
21708 " throw new Error('again'); \n" // This is the new uncaught error.
21709 "} \n";
21710 CompileRun(throw_again);
21711 CHECK(try_catch.HasCaught());
21712 Local<Message> message = try_catch.Message();
21713 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021714 CHECK_EQ(6, message->GetLineNumber(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021715 }
21716}
21717
21718
21719static void Helper137002(bool do_store,
21720 bool polymorphic,
21721 bool remove_accessor,
21722 bool interceptor) {
21723 LocalContext context;
21724 Local<ObjectTemplate> templ = ObjectTemplate::New(context->GetIsolate());
21725 if (interceptor) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040021726 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(FooGetInterceptor,
21727 FooSetInterceptor));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021728 } else {
21729 templ->SetAccessor(v8_str("foo"),
21730 GetterWhichReturns42,
21731 SetterWhichSetsYOnThisTo23);
21732 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021733 CHECK(context->Global()
21734 ->Set(context.local(), v8_str("obj"),
21735 templ->NewInstance(context.local()).ToLocalChecked())
21736 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021737
21738 // Turn monomorphic on slow object with native accessor, then turn
21739 // polymorphic, finally optimize to create negative lookup and fail.
21740 CompileRun(do_store ?
21741 "function f(x) { x.foo = void 0; }" :
21742 "function f(x) { return x.foo; }");
21743 CompileRun("obj.y = void 0;");
21744 if (!interceptor) {
21745 CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
21746 }
21747 CompileRun("obj.__proto__ = null;"
21748 "f(obj); f(obj); f(obj);");
21749 if (polymorphic) {
21750 CompileRun("f({});");
21751 }
21752 CompileRun("obj.y = void 0;"
21753 "%OptimizeFunctionOnNextCall(f);");
21754 if (remove_accessor) {
21755 CompileRun("delete obj.foo;");
21756 }
21757 CompileRun("var result = f(obj);");
21758 if (do_store) {
21759 CompileRun("result = obj.y;");
21760 }
21761 if (remove_accessor && !interceptor) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021762 CHECK(context->Global()
21763 ->Get(context.local(), v8_str("result"))
21764 .ToLocalChecked()
21765 ->IsUndefined());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021766 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021767 CHECK_EQ(do_store ? 23 : 42, context->Global()
21768 ->Get(context.local(), v8_str("result"))
21769 .ToLocalChecked()
21770 ->Int32Value(context.local())
21771 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021772 }
21773}
21774
21775
21776THREADED_TEST(Regress137002a) {
21777 i::FLAG_allow_natives_syntax = true;
21778 i::FLAG_compilation_cache = false;
21779 v8::HandleScope scope(CcTest::isolate());
21780 for (int i = 0; i < 16; i++) {
21781 Helper137002(i & 8, i & 4, i & 2, i & 1);
21782 }
21783}
21784
21785
21786THREADED_TEST(Regress137002b) {
21787 i::FLAG_allow_natives_syntax = true;
21788 LocalContext context;
21789 v8::Isolate* isolate = context->GetIsolate();
21790 v8::HandleScope scope(isolate);
21791 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
21792 templ->SetAccessor(v8_str("foo"),
21793 GetterWhichReturns42,
21794 SetterWhichSetsYOnThisTo23);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021795 CHECK(context->Global()
21796 ->Set(context.local(), v8_str("obj"),
21797 templ->NewInstance(context.local()).ToLocalChecked())
21798 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021799
21800 // Turn monomorphic on slow object with native accessor, then just
21801 // delete the property and fail.
21802 CompileRun("function load(x) { return x.foo; }"
21803 "function store(x) { x.foo = void 0; }"
21804 "function keyed_load(x, key) { return x[key]; }"
21805 // Second version of function has a different source (add void 0)
21806 // so that it does not share code with the first version. This
21807 // ensures that the ICs are monomorphic.
21808 "function load2(x) { void 0; return x.foo; }"
21809 "function store2(x) { void 0; x.foo = void 0; }"
21810 "function keyed_load2(x, key) { void 0; return x[key]; }"
21811
21812 "obj.y = void 0;"
21813 "obj.__proto__ = null;"
21814 "var subobj = {};"
21815 "subobj.y = void 0;"
21816 "subobj.__proto__ = obj;"
21817 "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
21818
21819 // Make the ICs monomorphic.
21820 "load(obj); load(obj);"
21821 "load2(subobj); load2(subobj);"
21822 "store(obj); store(obj);"
21823 "store2(subobj); store2(subobj);"
21824 "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
21825 "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
21826
21827 // Actually test the shiny new ICs and better not crash. This
21828 // serves as a regression test for issue 142088 as well.
21829 "load(obj);"
21830 "load2(subobj);"
21831 "store(obj);"
21832 "store2(subobj);"
21833 "keyed_load(obj, 'foo');"
21834 "keyed_load2(subobj, 'foo');"
21835
21836 // Delete the accessor. It better not be called any more now.
21837 "delete obj.foo;"
21838 "obj.y = void 0;"
21839 "subobj.y = void 0;"
21840
21841 "var load_result = load(obj);"
21842 "var load_result2 = load2(subobj);"
21843 "var keyed_load_result = keyed_load(obj, 'foo');"
21844 "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
21845 "store(obj);"
21846 "store2(subobj);"
21847 "var y_from_obj = obj.y;"
21848 "var y_from_subobj = subobj.y;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021849 CHECK(context->Global()
21850 ->Get(context.local(), v8_str("load_result"))
21851 .ToLocalChecked()
21852 ->IsUndefined());
21853 CHECK(context->Global()
21854 ->Get(context.local(), v8_str("load_result2"))
21855 .ToLocalChecked()
21856 ->IsUndefined());
21857 CHECK(context->Global()
21858 ->Get(context.local(), v8_str("keyed_load_result"))
21859 .ToLocalChecked()
21860 ->IsUndefined());
21861 CHECK(context->Global()
21862 ->Get(context.local(), v8_str("keyed_load_result2"))
21863 .ToLocalChecked()
21864 ->IsUndefined());
21865 CHECK(context->Global()
21866 ->Get(context.local(), v8_str("y_from_obj"))
21867 .ToLocalChecked()
21868 ->IsUndefined());
21869 CHECK(context->Global()
21870 ->Get(context.local(), v8_str("y_from_subobj"))
21871 .ToLocalChecked()
21872 ->IsUndefined());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021873}
21874
21875
21876THREADED_TEST(Regress142088) {
21877 i::FLAG_allow_natives_syntax = true;
21878 LocalContext context;
21879 v8::Isolate* isolate = context->GetIsolate();
21880 v8::HandleScope scope(isolate);
21881 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
21882 templ->SetAccessor(v8_str("foo"),
21883 GetterWhichReturns42,
21884 SetterWhichSetsYOnThisTo23);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021885 CHECK(context->Global()
21886 ->Set(context.local(), v8_str("obj"),
21887 templ->NewInstance(context.local()).ToLocalChecked())
21888 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021889
21890 CompileRun("function load(x) { return x.foo; }"
21891 "var o = Object.create(obj);"
21892 "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
21893 "load(o); load(o); load(o); load(o);");
21894}
21895
21896
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021897THREADED_TEST(Regress137496) {
21898 i::FLAG_expose_gc = true;
21899 LocalContext context;
21900 v8::HandleScope scope(context->GetIsolate());
21901
21902 // Compile a try-finally clause where the finally block causes a GC
21903 // while there still is a message pending for external reporting.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021904 TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021905 try_catch.SetVerbose(true);
21906 CompileRun("try { throw new Error(); } finally { gc(); }");
21907 CHECK(try_catch.HasCaught());
21908}
21909
21910
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021911THREADED_TEST(Regress157124) {
21912 LocalContext context;
21913 v8::Isolate* isolate = context->GetIsolate();
21914 v8::HandleScope scope(isolate);
21915 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021916 Local<Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021917 obj->GetIdentityHash();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021918 obj->DeletePrivate(context.local(),
21919 v8::Private::ForApi(isolate, v8_str("Bug")))
21920 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021921}
21922
21923
21924THREADED_TEST(Regress2535) {
21925 LocalContext context;
21926 v8::HandleScope scope(context->GetIsolate());
21927 Local<Value> set_value = CompileRun("new Set();");
21928 Local<Object> set_object(Local<Object>::Cast(set_value));
21929 CHECK_EQ(0, set_object->InternalFieldCount());
21930 Local<Value> map_value = CompileRun("new Map();");
21931 Local<Object> map_object(Local<Object>::Cast(map_value));
21932 CHECK_EQ(0, map_object->InternalFieldCount());
21933}
21934
21935
21936THREADED_TEST(Regress2746) {
21937 LocalContext context;
21938 v8::Isolate* isolate = context->GetIsolate();
21939 v8::HandleScope scope(isolate);
21940 Local<Object> obj = Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021941 Local<v8::Private> key = v8::Private::New(isolate, v8_str("key"));
21942 CHECK(
21943 obj->SetPrivate(context.local(), key, v8::Undefined(isolate)).FromJust());
21944 Local<Value> value = obj->GetPrivate(context.local(), key).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021945 CHECK(!value.IsEmpty());
21946 CHECK(value->IsUndefined());
21947}
21948
21949
21950THREADED_TEST(Regress260106) {
21951 LocalContext context;
21952 v8::Isolate* isolate = context->GetIsolate();
21953 v8::HandleScope scope(isolate);
21954 Local<FunctionTemplate> templ = FunctionTemplate::New(isolate,
21955 DummyCallHandler);
21956 CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021957 Local<Function> function =
21958 templ->GetFunction(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021959 CHECK(!function.IsEmpty());
21960 CHECK(function->IsFunction());
21961}
21962
21963
21964THREADED_TEST(JSONParseObject) {
21965 LocalContext context;
21966 HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021967 Local<Value> obj =
21968 v8::JSON::Parse(context->GetIsolate(), v8_str("{\"x\":42}"))
21969 .ToLocalChecked();
21970 Local<Object> global = context->Global();
21971 global->Set(context.local(), v8_str("obj"), obj).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021972 ExpectString("JSON.stringify(obj)", "{\"x\":42}");
21973}
21974
21975
21976THREADED_TEST(JSONParseNumber) {
21977 LocalContext context;
21978 HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021979 Local<Value> obj =
21980 v8::JSON::Parse(context->GetIsolate(), v8_str("42")).ToLocalChecked();
21981 Local<Object> global = context->Global();
21982 global->Set(context.local(), v8_str("obj"), obj).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021983 ExpectString("JSON.stringify(obj)", "42");
21984}
21985
21986
21987#if V8_OS_POSIX && !V8_OS_NACL
21988class ThreadInterruptTest {
21989 public:
21990 ThreadInterruptTest() : sem_(0), sem_value_(0) { }
21991 ~ThreadInterruptTest() {}
21992
21993 void RunTest() {
21994 InterruptThread i_thread(this);
21995 i_thread.Start();
21996
21997 sem_.Wait();
21998 CHECK_EQ(kExpectedValue, sem_value_);
21999 }
22000
22001 private:
22002 static const int kExpectedValue = 1;
22003
22004 class InterruptThread : public v8::base::Thread {
22005 public:
22006 explicit InterruptThread(ThreadInterruptTest* test)
22007 : Thread(Options("InterruptThread")), test_(test) {}
22008
22009 virtual void Run() {
22010 struct sigaction action;
22011
22012 // Ensure that we'll enter waiting condition
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022013 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022014
22015 // Setup signal handler
22016 memset(&action, 0, sizeof(action));
22017 action.sa_handler = SignalHandler;
22018 sigaction(SIGCHLD, &action, NULL);
22019
22020 // Send signal
22021 kill(getpid(), SIGCHLD);
22022
22023 // Ensure that if wait has returned because of error
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022024 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022025
22026 // Set value and signal semaphore
22027 test_->sem_value_ = 1;
22028 test_->sem_.Signal();
22029 }
22030
22031 static void SignalHandler(int signal) {
22032 }
22033
22034 private:
22035 ThreadInterruptTest* test_;
22036 };
22037
22038 v8::base::Semaphore sem_;
22039 volatile int sem_value_;
22040};
22041
22042
22043THREADED_TEST(SemaphoreInterruption) {
22044 ThreadInterruptTest().RunTest();
22045}
22046
22047
22048#endif // V8_OS_POSIX
22049
22050
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022051void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
22052 CHECK(false);
22053}
22054
22055
22056TEST(JSONStringifyAccessCheck) {
22057 v8::V8::Initialize();
22058 v8::Isolate* isolate = CcTest::isolate();
22059 v8::HandleScope scope(isolate);
22060
22061 // Create an ObjectTemplate for global objects and install access
22062 // check callbacks that will block access.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022063 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022064 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022065 global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022066
22067 // Create a context and set an x property on it's global object.
22068 LocalContext context0(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022069 v8::Local<v8::Object> global0 = context0->Global();
22070 global0->Set(context0.local(), v8_str("x"), v8_num(42)).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022071 ExpectString("JSON.stringify(this)", "{\"x\":42}");
22072
22073 for (int i = 0; i < 2; i++) {
22074 if (i == 1) {
22075 // Install a toJSON function on the second run.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022076 v8::Local<v8::FunctionTemplate> toJSON =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022077 v8::FunctionTemplate::New(isolate, UnreachableCallback);
22078
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022079 global0->Set(context0.local(), v8_str("toJSON"),
22080 toJSON->GetFunction(context0.local()).ToLocalChecked())
22081 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022082 }
22083 // Create a context with a different security token so that the
22084 // failed access check callback will be called on each access.
22085 LocalContext context1(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022086 CHECK(context1->Global()
22087 ->Set(context1.local(), v8_str("other"), global0)
22088 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022089
22090 CHECK(CompileRun("JSON.stringify(other)").IsEmpty());
22091 CHECK(CompileRun("JSON.stringify({ 'a' : other, 'b' : ['c'] })").IsEmpty());
22092 CHECK(CompileRun("JSON.stringify([other, 'b', 'c'])").IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022093 }
22094}
22095
22096
22097bool access_check_fail_thrown = false;
22098bool catch_callback_called = false;
22099
22100
22101// Failed access check callback that performs a GC on each invocation.
22102void FailedAccessCheckThrows(Local<v8::Object> target,
22103 v8::AccessType type,
22104 Local<v8::Value> data) {
22105 access_check_fail_thrown = true;
22106 i::PrintF("Access check failed. Error thrown.\n");
22107 CcTest::isolate()->ThrowException(
22108 v8::Exception::Error(v8_str("cross context")));
22109}
22110
22111
22112void CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
22113 for (int i = 0; i < args.Length(); i++) {
22114 i::PrintF("%s\n", *String::Utf8Value(args[i]));
22115 }
22116 catch_callback_called = true;
22117}
22118
22119
22120void HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022121 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
22122 CHECK(
22123 args[0]
22124 ->ToObject(context)
22125 .ToLocalChecked()
22126 ->HasOwnProperty(context, args[1]->ToString(context).ToLocalChecked())
22127 .IsNothing());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022128}
22129
22130
22131void CheckCorrectThrow(const char* script) {
22132 // Test that the script, when wrapped into a try-catch, triggers the catch
22133 // clause due to failed access check throwing an exception.
22134 // The subsequent try-catch should run without any exception.
22135 access_check_fail_thrown = false;
22136 catch_callback_called = false;
22137 i::ScopedVector<char> source(1024);
22138 i::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
22139 CompileRun(source.start());
22140 CHECK(access_check_fail_thrown);
22141 CHECK(catch_callback_called);
22142
22143 access_check_fail_thrown = false;
22144 catch_callback_called = false;
22145 CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
22146 CHECK(!access_check_fail_thrown);
22147 CHECK(!catch_callback_called);
22148}
22149
22150
22151TEST(AccessCheckThrows) {
22152 i::FLAG_allow_natives_syntax = true;
22153 v8::V8::Initialize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022154 v8::Isolate* isolate = CcTest::isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022155 isolate->SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022156 v8::HandleScope scope(isolate);
22157
22158 // Create an ObjectTemplate for global objects and install access
22159 // check callbacks that will block access.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022160 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022161 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022162 global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022163
22164 // Create a context and set an x property on it's global object.
22165 LocalContext context0(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022166 v8::Local<v8::Object> global0 = context0->Global();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022167
22168 // Create a context with a different security token so that the
22169 // failed access check callback will be called on each access.
22170 LocalContext context1(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022171 CHECK(context1->Global()
22172 ->Set(context1.local(), v8_str("other"), global0)
22173 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022174
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022175 v8::Local<v8::FunctionTemplate> catcher_fun =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022176 v8::FunctionTemplate::New(isolate, CatcherCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022177 CHECK(context1->Global()
22178 ->Set(context1.local(), v8_str("catcher"),
22179 catcher_fun->GetFunction(context1.local()).ToLocalChecked())
22180 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022181
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022182 v8::Local<v8::FunctionTemplate> has_own_property_fun =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022183 v8::FunctionTemplate::New(isolate, HasOwnPropertyCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022184 CHECK(context1->Global()
22185 ->Set(context1.local(), v8_str("has_own_property"),
22186 has_own_property_fun->GetFunction(context1.local())
22187 .ToLocalChecked())
22188 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022189
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022190 {
22191 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022192 access_check_fail_thrown = false;
22193 CompileRun("other.x;");
22194 CHECK(access_check_fail_thrown);
22195 CHECK(try_catch.HasCaught());
22196 }
22197
22198 CheckCorrectThrow("other.x");
22199 CheckCorrectThrow("other[1]");
22200 CheckCorrectThrow("JSON.stringify(other)");
22201 CheckCorrectThrow("has_own_property(other, 'x')");
22202 CheckCorrectThrow("%GetProperty(other, 'x')");
22203 CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 0)");
22204 CheckCorrectThrow("%AddNamedProperty(other, 'x', 'foo', 1)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022205 CheckCorrectThrow("%DeleteProperty_Sloppy(other, 'x')");
22206 CheckCorrectThrow("%DeleteProperty_Strict(other, 'x')");
22207 CheckCorrectThrow("%DeleteProperty_Sloppy(other, '1')");
22208 CheckCorrectThrow("%DeleteProperty_Strict(other, '1')");
Ben Murdochda12d292016-06-02 14:46:10 +010022209 CheckCorrectThrow("Object.prototype.hasOwnProperty.call(other, 'x')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022210 CheckCorrectThrow("%HasProperty('x', other)");
22211 CheckCorrectThrow("%PropertyIsEnumerable(other, 'x')");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022212 // PROPERTY_ATTRIBUTES_NONE = 0
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022213 CheckCorrectThrow("%DefineAccessorPropertyUnchecked("
22214 "other, 'x', null, null, 1)");
22215
22216 // Reset the failed access check callback so it does not influence
22217 // the other tests.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022218 isolate->SetFailedAccessCheckCallbackFunction(NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022219}
22220
22221
22222class RequestInterruptTestBase {
22223 public:
22224 RequestInterruptTestBase()
22225 : env_(),
22226 isolate_(env_->GetIsolate()),
22227 sem_(0),
22228 warmup_(20000),
22229 should_continue_(true) {
22230 }
22231
22232 virtual ~RequestInterruptTestBase() { }
22233
22234 virtual void StartInterruptThread() = 0;
22235
22236 virtual void TestBody() = 0;
22237
22238 void RunTest() {
22239 StartInterruptThread();
22240
22241 v8::HandleScope handle_scope(isolate_);
22242
22243 TestBody();
22244
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022245 // Verify we arrived here because interruptor was called
22246 // not due to a bug causing us to exit the loop too early.
22247 CHECK(!should_continue());
22248 }
22249
22250 void WakeUpInterruptor() {
22251 sem_.Signal();
22252 }
22253
22254 bool should_continue() const { return should_continue_; }
22255
22256 bool ShouldContinue() {
22257 if (warmup_ > 0) {
22258 if (--warmup_ == 0) {
22259 WakeUpInterruptor();
22260 }
22261 }
22262
22263 return should_continue_;
22264 }
22265
22266 static void ShouldContinueCallback(
22267 const v8::FunctionCallbackInfo<Value>& info) {
22268 RequestInterruptTestBase* test =
22269 reinterpret_cast<RequestInterruptTestBase*>(
22270 info.Data().As<v8::External>()->Value());
22271 info.GetReturnValue().Set(test->ShouldContinue());
22272 }
22273
22274 LocalContext env_;
22275 v8::Isolate* isolate_;
22276 v8::base::Semaphore sem_;
22277 int warmup_;
22278 bool should_continue_;
22279};
22280
22281
22282class RequestInterruptTestBaseWithSimpleInterrupt
22283 : public RequestInterruptTestBase {
22284 public:
22285 RequestInterruptTestBaseWithSimpleInterrupt() : i_thread(this) { }
22286
22287 virtual void StartInterruptThread() {
22288 i_thread.Start();
22289 }
22290
22291 private:
22292 class InterruptThread : public v8::base::Thread {
22293 public:
22294 explicit InterruptThread(RequestInterruptTestBase* test)
22295 : Thread(Options("RequestInterruptTest")), test_(test) {}
22296
22297 virtual void Run() {
22298 test_->sem_.Wait();
22299 test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
22300 }
22301
22302 static void OnInterrupt(v8::Isolate* isolate, void* data) {
22303 reinterpret_cast<RequestInterruptTestBase*>(data)->
22304 should_continue_ = false;
22305 }
22306
22307 private:
22308 RequestInterruptTestBase* test_;
22309 };
22310
22311 InterruptThread i_thread;
22312};
22313
22314
22315class RequestInterruptTestWithFunctionCall
22316 : public RequestInterruptTestBaseWithSimpleInterrupt {
22317 public:
22318 virtual void TestBody() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022319 Local<Function> func = Function::New(env_.local(), ShouldContinueCallback,
22320 v8::External::New(isolate_, this))
22321 .ToLocalChecked();
22322 CHECK(env_->Global()
22323 ->Set(env_.local(), v8_str("ShouldContinue"), func)
22324 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022325
22326 CompileRun("while (ShouldContinue()) { }");
22327 }
22328};
22329
22330
22331class RequestInterruptTestWithMethodCall
22332 : public RequestInterruptTestBaseWithSimpleInterrupt {
22333 public:
22334 virtual void TestBody() {
22335 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
22336 v8::Local<v8::Template> proto = t->PrototypeTemplate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022337 proto->Set(v8_str("shouldContinue"),
Ben Murdoch097c5b22016-05-18 11:27:45 +010022338 FunctionTemplate::New(isolate_, ShouldContinueCallback,
22339 v8::External::New(isolate_, this)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022340 CHECK(env_->Global()
22341 ->Set(env_.local(), v8_str("Klass"),
22342 t->GetFunction(env_.local()).ToLocalChecked())
22343 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022344
22345 CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
22346 }
22347};
22348
22349
22350class RequestInterruptTestWithAccessor
22351 : public RequestInterruptTestBaseWithSimpleInterrupt {
22352 public:
22353 virtual void TestBody() {
22354 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
22355 v8::Local<v8::Template> proto = t->PrototypeTemplate();
22356 proto->SetAccessorProperty(v8_str("shouldContinue"), FunctionTemplate::New(
22357 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022358 CHECK(env_->Global()
22359 ->Set(env_.local(), v8_str("Klass"),
22360 t->GetFunction(env_.local()).ToLocalChecked())
22361 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022362
22363 CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
22364 }
22365};
22366
22367
22368class RequestInterruptTestWithNativeAccessor
22369 : public RequestInterruptTestBaseWithSimpleInterrupt {
22370 public:
22371 virtual void TestBody() {
22372 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
22373 t->InstanceTemplate()->SetNativeDataProperty(
22374 v8_str("shouldContinue"),
22375 &ShouldContinueNativeGetter,
22376 NULL,
22377 v8::External::New(isolate_, this));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022378 CHECK(env_->Global()
22379 ->Set(env_.local(), v8_str("Klass"),
22380 t->GetFunction(env_.local()).ToLocalChecked())
22381 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022382
22383 CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
22384 }
22385
22386 private:
22387 static void ShouldContinueNativeGetter(
22388 Local<String> property,
22389 const v8::PropertyCallbackInfo<v8::Value>& info) {
22390 RequestInterruptTestBase* test =
22391 reinterpret_cast<RequestInterruptTestBase*>(
22392 info.Data().As<v8::External>()->Value());
22393 info.GetReturnValue().Set(test->ShouldContinue());
22394 }
22395};
22396
22397
22398class RequestInterruptTestWithMethodCallAndInterceptor
22399 : public RequestInterruptTestBaseWithSimpleInterrupt {
22400 public:
22401 virtual void TestBody() {
22402 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
22403 v8::Local<v8::Template> proto = t->PrototypeTemplate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022404 proto->Set(v8_str("shouldContinue"),
Ben Murdoch097c5b22016-05-18 11:27:45 +010022405 FunctionTemplate::New(isolate_, ShouldContinueCallback,
22406 v8::External::New(isolate_, this)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022407 v8::Local<v8::ObjectTemplate> instance_template = t->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022408 instance_template->SetHandler(
22409 v8::NamedPropertyHandlerConfiguration(EmptyInterceptor));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022410
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022411 CHECK(env_->Global()
22412 ->Set(env_.local(), v8_str("Klass"),
22413 t->GetFunction(env_.local()).ToLocalChecked())
22414 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022415
22416 CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
22417 }
22418
22419 private:
22420 static void EmptyInterceptor(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022421 Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022422};
22423
22424
22425class RequestInterruptTestWithMathAbs
22426 : public RequestInterruptTestBaseWithSimpleInterrupt {
22427 public:
22428 virtual void TestBody() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022429 env_->Global()
22430 ->Set(env_.local(), v8_str("WakeUpInterruptor"),
22431 Function::New(env_.local(), WakeUpInterruptorCallback,
22432 v8::External::New(isolate_, this))
22433 .ToLocalChecked())
22434 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022435
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022436 env_->Global()
22437 ->Set(env_.local(), v8_str("ShouldContinue"),
22438 Function::New(env_.local(), ShouldContinueCallback,
22439 v8::External::New(isolate_, this))
22440 .ToLocalChecked())
22441 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022442
22443 i::FLAG_allow_natives_syntax = true;
22444 CompileRun("function loopish(o) {"
22445 " var pre = 10;"
22446 " while (o.abs(1) > 0) {"
22447 " if (o.abs(1) >= 0 && !ShouldContinue()) break;"
22448 " if (pre > 0) {"
22449 " if (--pre === 0) WakeUpInterruptor(o === Math);"
22450 " }"
22451 " }"
22452 "}"
22453 "var i = 50;"
22454 "var obj = {abs: function () { return i-- }, x: null};"
22455 "delete obj.x;"
22456 "loopish(obj);"
22457 "%OptimizeFunctionOnNextCall(loopish);"
22458 "loopish(Math);");
22459
22460 i::FLAG_allow_natives_syntax = false;
22461 }
22462
22463 private:
22464 static void WakeUpInterruptorCallback(
22465 const v8::FunctionCallbackInfo<Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022466 if (!info[0]
22467 ->BooleanValue(info.GetIsolate()->GetCurrentContext())
22468 .FromJust()) {
22469 return;
22470 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022471
22472 RequestInterruptTestBase* test =
22473 reinterpret_cast<RequestInterruptTestBase*>(
22474 info.Data().As<v8::External>()->Value());
22475 test->WakeUpInterruptor();
22476 }
22477
22478 static void ShouldContinueCallback(
22479 const v8::FunctionCallbackInfo<Value>& info) {
22480 RequestInterruptTestBase* test =
22481 reinterpret_cast<RequestInterruptTestBase*>(
22482 info.Data().As<v8::External>()->Value());
22483 info.GetReturnValue().Set(test->should_continue());
22484 }
22485};
22486
22487
22488TEST(RequestInterruptTestWithFunctionCall) {
22489 RequestInterruptTestWithFunctionCall().RunTest();
22490}
22491
22492
22493TEST(RequestInterruptTestWithMethodCall) {
22494 RequestInterruptTestWithMethodCall().RunTest();
22495}
22496
22497
22498TEST(RequestInterruptTestWithAccessor) {
22499 RequestInterruptTestWithAccessor().RunTest();
22500}
22501
22502
22503TEST(RequestInterruptTestWithNativeAccessor) {
22504 RequestInterruptTestWithNativeAccessor().RunTest();
22505}
22506
22507
22508TEST(RequestInterruptTestWithMethodCallAndInterceptor) {
22509 RequestInterruptTestWithMethodCallAndInterceptor().RunTest();
22510}
22511
22512
22513TEST(RequestInterruptTestWithMathAbs) {
22514 RequestInterruptTestWithMathAbs().RunTest();
22515}
22516
22517
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022518class RequestMultipleInterrupts : public RequestInterruptTestBase {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022519 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022520 RequestMultipleInterrupts() : i_thread(this), counter_(0) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022521
22522 virtual void StartInterruptThread() {
22523 i_thread.Start();
22524 }
22525
22526 virtual void TestBody() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022527 Local<Function> func = Function::New(env_.local(), ShouldContinueCallback,
22528 v8::External::New(isolate_, this))
22529 .ToLocalChecked();
22530 CHECK(env_->Global()
22531 ->Set(env_.local(), v8_str("ShouldContinue"), func)
22532 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022533
22534 CompileRun("while (ShouldContinue()) { }");
22535 }
22536
22537 private:
22538 class InterruptThread : public v8::base::Thread {
22539 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022540 enum { NUM_INTERRUPTS = 10 };
22541 explicit InterruptThread(RequestMultipleInterrupts* test)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022542 : Thread(Options("RequestInterruptTest")), test_(test) {}
22543
22544 virtual void Run() {
22545 test_->sem_.Wait();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022546 for (int i = 0; i < NUM_INTERRUPTS; i++) {
22547 test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
22548 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022549 }
22550
22551 static void OnInterrupt(v8::Isolate* isolate, void* data) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022552 RequestMultipleInterrupts* test =
22553 reinterpret_cast<RequestMultipleInterrupts*>(data);
22554 test->should_continue_ = ++test->counter_ < NUM_INTERRUPTS;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022555 }
22556
22557 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022558 RequestMultipleInterrupts* test_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022559 };
22560
22561 InterruptThread i_thread;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022562 int counter_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022563};
22564
22565
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022566TEST(RequestMultipleInterrupts) { RequestMultipleInterrupts().RunTest(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022567
22568
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022569static bool interrupt_was_called = false;
22570
22571
22572void SmallScriptsInterruptCallback(v8::Isolate* isolate, void* data) {
22573 interrupt_was_called = true;
22574}
22575
22576
22577TEST(RequestInterruptSmallScripts) {
22578 LocalContext env;
22579 v8::Isolate* isolate = CcTest::isolate();
22580 v8::HandleScope scope(isolate);
22581
22582 interrupt_was_called = false;
22583 isolate->RequestInterrupt(&SmallScriptsInterruptCallback, NULL);
22584 CompileRun("(function(x){return x;})(1);");
22585 CHECK(interrupt_was_called);
22586}
22587
22588
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022589static Local<Value> function_new_expected_env;
22590static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022591 CHECK(
22592 function_new_expected_env->Equals(info.GetIsolate()->GetCurrentContext(),
22593 info.Data())
22594 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022595 info.GetReturnValue().Set(17);
22596}
22597
22598
22599THREADED_TEST(FunctionNew) {
22600 LocalContext env;
22601 v8::Isolate* isolate = env->GetIsolate();
22602 v8::HandleScope scope(isolate);
22603 Local<Object> data = v8::Object::New(isolate);
22604 function_new_expected_env = data;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022605 Local<Function> func =
22606 Function::New(env.local(), FunctionNewCallback, data).ToLocalChecked();
22607 CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022608 Local<Value> result = CompileRun("func();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022609 CHECK(v8::Integer::New(isolate, 17)->Equals(env.local(), result).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022610 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022611 // Verify function not cached
22612 auto serial_number = handle(
22613 i::Smi::cast(i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*func))
22614 ->shared()
22615 ->get_api_func_data()
22616 ->serial_number()),
22617 i_isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +010022618 auto cache = i_isolate->template_instantiations_cache();
Ben Murdochda12d292016-06-02 14:46:10 +010022619 CHECK(cache->FindEntry(static_cast<uint32_t>(serial_number->value())) ==
22620 i::UnseededNumberDictionary::kNotFound);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022621 // Verify that each Function::New creates a new function instance
22622 Local<Object> data2 = v8::Object::New(isolate);
22623 function_new_expected_env = data2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022624 Local<Function> func2 =
22625 Function::New(env.local(), FunctionNewCallback, data2).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022626 CHECK(!func2->IsNull());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022627 CHECK(!func->Equals(env.local(), func2).FromJust());
22628 CHECK(env->Global()->Set(env.local(), v8_str("func2"), func2).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022629 Local<Value> result2 = CompileRun("func2();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022630 CHECK(v8::Integer::New(isolate, 17)->Equals(env.local(), result2).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022631}
22632
22633
22634TEST(EscapeableHandleScope) {
22635 HandleScope outer_scope(CcTest::isolate());
22636 LocalContext context;
22637 const int runs = 10;
22638 Local<String> values[runs];
22639 for (int i = 0; i < runs; i++) {
22640 v8::EscapableHandleScope inner_scope(CcTest::isolate());
22641 Local<String> value;
22642 if (i != 0) value = v8_str("escape value");
22643 values[i] = inner_scope.Escape(value);
22644 }
22645 for (int i = 0; i < runs; i++) {
22646 Local<String> expected;
22647 if (i != 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022648 CHECK(v8_str("escape value")
22649 ->Equals(context.local(), values[i])
22650 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022651 } else {
22652 CHECK(values[i].IsEmpty());
22653 }
22654 }
22655}
22656
22657
22658static void SetterWhichExpectsThisAndHolderToDiffer(
22659 Local<String>, Local<Value>, const v8::PropertyCallbackInfo<void>& info) {
22660 CHECK(info.Holder() != info.This());
22661}
22662
22663
22664TEST(Regress239669) {
22665 LocalContext context;
22666 v8::Isolate* isolate = context->GetIsolate();
22667 v8::HandleScope scope(isolate);
22668 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
22669 templ->SetAccessor(v8_str("x"), 0, SetterWhichExpectsThisAndHolderToDiffer);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022670 CHECK(context->Global()
22671 ->Set(context.local(), v8_str("P"),
22672 templ->NewInstance(context.local()).ToLocalChecked())
22673 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022674 CompileRun(
22675 "function C1() {"
22676 " this.x = 23;"
22677 "};"
22678 "C1.prototype = P;"
22679 "for (var i = 0; i < 4; i++ ) {"
22680 " new C1();"
22681 "}");
22682}
22683
22684
22685class ApiCallOptimizationChecker {
22686 private:
22687 static Local<Object> data;
22688 static Local<Object> receiver;
22689 static Local<Object> holder;
22690 static Local<Object> callee;
22691 static int count;
22692
22693 static void OptimizationCallback(
22694 const v8::FunctionCallbackInfo<v8::Value>& info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022695 CHECK(data == info.Data());
22696 CHECK(receiver == info.This());
22697 if (info.Length() == 1) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022698 CHECK(v8_num(1)
22699 ->Equals(info.GetIsolate()->GetCurrentContext(), info[0])
22700 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022701 }
22702 CHECK(holder == info.Holder());
22703 count++;
22704 info.GetReturnValue().Set(v8_str("returned"));
22705 }
22706
22707 public:
22708 enum SignatureType {
22709 kNoSignature,
22710 kSignatureOnReceiver,
22711 kSignatureOnPrototype
22712 };
22713
22714 void RunAll() {
22715 SignatureType signature_types[] =
22716 {kNoSignature, kSignatureOnReceiver, kSignatureOnPrototype};
22717 for (unsigned i = 0; i < arraysize(signature_types); i++) {
22718 SignatureType signature_type = signature_types[i];
22719 for (int j = 0; j < 2; j++) {
22720 bool global = j == 0;
22721 int key = signature_type +
22722 arraysize(signature_types) * (global ? 1 : 0);
22723 Run(signature_type, global, key);
22724 }
22725 }
22726 }
22727
22728 void Run(SignatureType signature_type, bool global, int key) {
22729 v8::Isolate* isolate = CcTest::isolate();
22730 v8::HandleScope scope(isolate);
22731 // Build a template for signature checks.
22732 Local<v8::ObjectTemplate> signature_template;
22733 Local<v8::Signature> signature;
22734 {
22735 Local<v8::FunctionTemplate> parent_template =
22736 FunctionTemplate::New(isolate);
22737 parent_template->SetHiddenPrototype(true);
22738 Local<v8::FunctionTemplate> function_template
22739 = FunctionTemplate::New(isolate);
22740 function_template->Inherit(parent_template);
22741 switch (signature_type) {
22742 case kNoSignature:
22743 break;
22744 case kSignatureOnReceiver:
22745 signature = v8::Signature::New(isolate, function_template);
22746 break;
22747 case kSignatureOnPrototype:
22748 signature = v8::Signature::New(isolate, parent_template);
22749 break;
22750 }
22751 signature_template = function_template->InstanceTemplate();
22752 }
22753 // Global object must pass checks.
22754 Local<v8::Context> context =
22755 v8::Context::New(isolate, NULL, signature_template);
22756 v8::Context::Scope context_scope(context);
22757 // Install regular object that can pass signature checks.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022758 Local<Object> function_receiver =
22759 signature_template->NewInstance(context).ToLocalChecked();
22760 CHECK(context->Global()
22761 ->Set(context, v8_str("function_receiver"), function_receiver)
22762 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022763 // Get the holder objects.
22764 Local<Object> inner_global =
22765 Local<Object>::Cast(context->Global()->GetPrototype());
22766 // Install functions on hidden prototype object if there is one.
22767 data = Object::New(isolate);
22768 Local<FunctionTemplate> function_template = FunctionTemplate::New(
22769 isolate, OptimizationCallback, data, signature);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022770 Local<Function> function =
22771 function_template->GetFunction(context).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022772 Local<Object> global_holder = inner_global;
22773 Local<Object> function_holder = function_receiver;
22774 if (signature_type == kSignatureOnPrototype) {
22775 function_holder = Local<Object>::Cast(function_holder->GetPrototype());
22776 global_holder = Local<Object>::Cast(global_holder->GetPrototype());
22777 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022778 global_holder->Set(context, v8_str("g_f"), function).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022779 global_holder->SetAccessorProperty(v8_str("g_acc"), function, function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022780 function_holder->Set(context, v8_str("f"), function).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022781 function_holder->SetAccessorProperty(v8_str("acc"), function, function);
22782 // Initialize expected values.
22783 callee = function;
22784 count = 0;
22785 if (global) {
22786 receiver = context->Global();
22787 holder = inner_global;
22788 } else {
22789 holder = function_receiver;
22790 // If not using a signature, add something else to the prototype chain
22791 // to test the case that holder != receiver
22792 if (signature_type == kNoSignature) {
22793 receiver = Local<Object>::Cast(CompileRun(
22794 "var receiver_subclass = {};\n"
22795 "receiver_subclass.__proto__ = function_receiver;\n"
22796 "receiver_subclass"));
22797 } else {
22798 receiver = Local<Object>::Cast(CompileRun(
22799 "var receiver_subclass = function_receiver;\n"
22800 "receiver_subclass"));
22801 }
22802 }
22803 // With no signature, the holder is not set.
22804 if (signature_type == kNoSignature) holder = receiver;
22805 // build wrap_function
22806 i::ScopedVector<char> wrap_function(200);
22807 if (global) {
22808 i::SNPrintF(
22809 wrap_function,
22810 "function wrap_f_%d() { var f = g_f; return f(); }\n"
22811 "function wrap_get_%d() { return this.g_acc; }\n"
22812 "function wrap_set_%d() { return this.g_acc = 1; }\n",
22813 key, key, key);
22814 } else {
22815 i::SNPrintF(
22816 wrap_function,
22817 "function wrap_f_%d() { return receiver_subclass.f(); }\n"
22818 "function wrap_get_%d() { return receiver_subclass.acc; }\n"
22819 "function wrap_set_%d() { return receiver_subclass.acc = 1; }\n",
22820 key, key, key);
22821 }
22822 // build source string
22823 i::ScopedVector<char> source(1000);
22824 i::SNPrintF(
22825 source,
22826 "%s\n" // wrap functions
22827 "function wrap_f() { return wrap_f_%d(); }\n"
22828 "function wrap_get() { return wrap_get_%d(); }\n"
22829 "function wrap_set() { return wrap_set_%d(); }\n"
22830 "check = function(returned) {\n"
22831 " if (returned !== 'returned') { throw returned; }\n"
22832 "}\n"
22833 "\n"
22834 "check(wrap_f());\n"
22835 "check(wrap_f());\n"
22836 "%%OptimizeFunctionOnNextCall(wrap_f_%d);\n"
22837 "check(wrap_f());\n"
22838 "\n"
22839 "check(wrap_get());\n"
22840 "check(wrap_get());\n"
22841 "%%OptimizeFunctionOnNextCall(wrap_get_%d);\n"
22842 "check(wrap_get());\n"
22843 "\n"
22844 "check = function(returned) {\n"
22845 " if (returned !== 1) { throw returned; }\n"
22846 "}\n"
22847 "check(wrap_set());\n"
22848 "check(wrap_set());\n"
22849 "%%OptimizeFunctionOnNextCall(wrap_set_%d);\n"
22850 "check(wrap_set());\n",
22851 wrap_function.start(), key, key, key, key, key, key);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022852 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022853 CompileRun(source.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022854 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022855 CHECK_EQ(9, count);
22856 }
22857};
22858
22859
22860Local<Object> ApiCallOptimizationChecker::data;
22861Local<Object> ApiCallOptimizationChecker::receiver;
22862Local<Object> ApiCallOptimizationChecker::holder;
22863Local<Object> ApiCallOptimizationChecker::callee;
22864int ApiCallOptimizationChecker::count = 0;
22865
22866
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022867TEST(FunctionCallOptimization) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022868 i::FLAG_allow_natives_syntax = true;
22869 ApiCallOptimizationChecker checker;
22870 checker.RunAll();
22871}
22872
22873
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022874TEST(FunctionCallOptimizationMultipleArgs) {
22875 i::FLAG_allow_natives_syntax = true;
22876 LocalContext context;
22877 v8::Isolate* isolate = context->GetIsolate();
22878 v8::HandleScope scope(isolate);
22879 Local<Object> global = context->Global();
22880 Local<v8::Function> function =
22881 Function::New(context.local(), Returns42).ToLocalChecked();
22882 global->Set(context.local(), v8_str("x"), function).FromJust();
22883 CompileRun(
22884 "function x_wrap() {\n"
22885 " for (var i = 0; i < 5; i++) {\n"
22886 " x(1,2,3);\n"
22887 " }\n"
22888 "}\n"
22889 "x_wrap();\n"
22890 "%OptimizeFunctionOnNextCall(x_wrap);"
22891 "x_wrap();\n");
22892}
22893
22894
22895static void ReturnsSymbolCallback(
22896 const v8::FunctionCallbackInfo<v8::Value>& info) {
22897 info.GetReturnValue().Set(v8::Symbol::New(info.GetIsolate()));
22898}
22899
22900
22901TEST(ApiCallbackCanReturnSymbols) {
22902 i::FLAG_allow_natives_syntax = true;
22903 LocalContext context;
22904 v8::Isolate* isolate = context->GetIsolate();
22905 v8::HandleScope scope(isolate);
22906 Local<Object> global = context->Global();
22907 Local<v8::Function> function =
22908 Function::New(context.local(), ReturnsSymbolCallback).ToLocalChecked();
22909 global->Set(context.local(), v8_str("x"), function).FromJust();
22910 CompileRun(
22911 "function x_wrap() {\n"
22912 " for (var i = 0; i < 5; i++) {\n"
22913 " x();\n"
22914 " }\n"
22915 "}\n"
22916 "x_wrap();\n"
22917 "%OptimizeFunctionOnNextCall(x_wrap);"
22918 "x_wrap();\n");
22919}
22920
22921
22922TEST(EmptyApiCallback) {
22923 LocalContext context;
22924 auto isolate = context->GetIsolate();
22925 v8::HandleScope scope(isolate);
22926 auto global = context->Global();
22927 auto function = FunctionTemplate::New(isolate)
22928 ->GetFunction(context.local())
22929 .ToLocalChecked();
22930 global->Set(context.local(), v8_str("x"), function).FromJust();
22931
22932 auto result = CompileRun("x()");
22933 CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
22934
22935 result = CompileRun("x(1,2,3)");
22936 CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
22937
22938 result = CompileRun("x.call(undefined)");
22939 CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
22940
22941 result = CompileRun("x.call(null)");
22942 CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
22943
22944 result = CompileRun("7 + x.call(3) + 11");
22945 CHECK(result->IsInt32());
22946 CHECK_EQ(21, result->Int32Value(context.local()).FromJust());
22947
22948 result = CompileRun("7 + x.call(3, 101, 102, 103, 104) + 11");
22949 CHECK(result->IsInt32());
22950 CHECK_EQ(21, result->Int32Value(context.local()).FromJust());
22951
22952 result = CompileRun("var y = []; x.call(y)");
22953 CHECK(result->IsArray());
22954
22955 result = CompileRun("x.call(y, 1, 2, 3, 4)");
22956 CHECK(result->IsArray());
22957}
22958
22959
22960TEST(SimpleSignatureCheck) {
22961 LocalContext context;
22962 auto isolate = context->GetIsolate();
22963 v8::HandleScope scope(isolate);
22964 auto global = context->Global();
22965 auto sig_obj = FunctionTemplate::New(isolate);
22966 auto sig = v8::Signature::New(isolate, sig_obj);
22967 auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
22968 global->Set(context.local(), v8_str("sig_obj"),
22969 sig_obj->GetFunction(context.local()).ToLocalChecked())
22970 .FromJust();
22971 global->Set(context.local(), v8_str("x"),
22972 x->GetFunction(context.local()).ToLocalChecked())
22973 .FromJust();
22974 CompileRun("var s = new sig_obj();");
22975 {
22976 TryCatch try_catch(isolate);
22977 CompileRun("x()");
22978 CHECK(try_catch.HasCaught());
22979 }
22980 {
22981 TryCatch try_catch(isolate);
22982 CompileRun("x.call(1)");
22983 CHECK(try_catch.HasCaught());
22984 }
22985 {
22986 TryCatch try_catch(isolate);
22987 auto result = CompileRun("s.x = x; s.x()");
22988 CHECK(!try_catch.HasCaught());
22989 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
22990 }
22991 {
22992 TryCatch try_catch(isolate);
22993 auto result = CompileRun("x.call(s)");
22994 CHECK(!try_catch.HasCaught());
22995 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
22996 }
22997}
22998
22999
23000TEST(ChainSignatureCheck) {
23001 LocalContext context;
23002 auto isolate = context->GetIsolate();
23003 v8::HandleScope scope(isolate);
23004 auto global = context->Global();
23005 auto sig_obj = FunctionTemplate::New(isolate);
23006 auto sig = v8::Signature::New(isolate, sig_obj);
23007 for (int i = 0; i < 4; ++i) {
23008 auto temp = FunctionTemplate::New(isolate);
23009 temp->Inherit(sig_obj);
23010 sig_obj = temp;
23011 }
23012 auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
23013 global->Set(context.local(), v8_str("sig_obj"),
23014 sig_obj->GetFunction(context.local()).ToLocalChecked())
23015 .FromJust();
23016 global->Set(context.local(), v8_str("x"),
23017 x->GetFunction(context.local()).ToLocalChecked())
23018 .FromJust();
23019 CompileRun("var s = new sig_obj();");
23020 {
23021 TryCatch try_catch(isolate);
23022 CompileRun("x()");
23023 CHECK(try_catch.HasCaught());
23024 }
23025 {
23026 TryCatch try_catch(isolate);
23027 CompileRun("x.call(1)");
23028 CHECK(try_catch.HasCaught());
23029 }
23030 {
23031 TryCatch try_catch(isolate);
23032 auto result = CompileRun("s.x = x; s.x()");
23033 CHECK(!try_catch.HasCaught());
23034 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
23035 }
23036 {
23037 TryCatch try_catch(isolate);
23038 auto result = CompileRun("x.call(s)");
23039 CHECK(!try_catch.HasCaught());
23040 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
23041 }
23042}
23043
23044
23045TEST(PrototypeSignatureCheck) {
23046 LocalContext context;
23047 auto isolate = context->GetIsolate();
23048 v8::HandleScope scope(isolate);
23049 auto global = context->Global();
23050 auto sig_obj = FunctionTemplate::New(isolate);
23051 sig_obj->SetHiddenPrototype(true);
23052 auto sig = v8::Signature::New(isolate, sig_obj);
23053 auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
23054 global->Set(context.local(), v8_str("sig_obj"),
23055 sig_obj->GetFunction(context.local()).ToLocalChecked())
23056 .FromJust();
23057 global->Set(context.local(), v8_str("x"),
23058 x->GetFunction(context.local()).ToLocalChecked())
23059 .FromJust();
23060 CompileRun("s = {}; s.__proto__ = new sig_obj();");
23061 {
23062 TryCatch try_catch(isolate);
23063 CompileRun("x()");
23064 CHECK(try_catch.HasCaught());
23065 }
23066 {
23067 TryCatch try_catch(isolate);
23068 CompileRun("x.call(1)");
23069 CHECK(try_catch.HasCaught());
23070 }
23071 {
23072 TryCatch try_catch(isolate);
23073 auto result = CompileRun("s.x = x; s.x()");
23074 CHECK(!try_catch.HasCaught());
23075 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
23076 }
23077 {
23078 TryCatch try_catch(isolate);
23079 auto result = CompileRun("x.call(s)");
23080 CHECK(!try_catch.HasCaught());
23081 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
23082 }
23083}
23084
23085
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023086static const char* last_event_message;
23087static int last_event_status;
23088void StoringEventLoggerCallback(const char* message, int status) {
23089 last_event_message = message;
23090 last_event_status = status;
23091}
23092
23093
23094TEST(EventLogging) {
23095 v8::Isolate* isolate = CcTest::isolate();
23096 isolate->SetEventLogger(StoringEventLoggerCallback);
23097 v8::internal::HistogramTimer histogramTimer(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023098 "V8.Test", 0, 10000, v8::internal::HistogramTimer::MILLISECOND, 50,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023099 reinterpret_cast<v8::internal::Isolate*>(isolate));
23100 histogramTimer.Start();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023101 CHECK_EQ(0, strcmp("V8.Test", last_event_message));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023102 CHECK_EQ(0, last_event_status);
23103 histogramTimer.Stop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023104 CHECK_EQ(0, strcmp("V8.Test", last_event_message));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023105 CHECK_EQ(1, last_event_status);
23106}
23107
23108
23109TEST(Promises) {
23110 LocalContext context;
23111 v8::Isolate* isolate = context->GetIsolate();
23112 v8::HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023113
23114 // Creation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023115 Local<v8::Promise::Resolver> pr =
23116 v8::Promise::Resolver::New(context.local()).ToLocalChecked();
23117 Local<v8::Promise::Resolver> rr =
23118 v8::Promise::Resolver::New(context.local()).ToLocalChecked();
23119 Local<v8::Promise> p = pr->GetPromise();
23120 Local<v8::Promise> r = rr->GetPromise();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023121
23122 // IsPromise predicate.
23123 CHECK(p->IsPromise());
23124 CHECK(r->IsPromise());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023125 Local<Value> o = v8::Object::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023126 CHECK(!o->IsPromise());
23127
23128 // Resolution and rejection.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023129 pr->Resolve(context.local(), v8::Integer::New(isolate, 1)).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023130 CHECK(p->IsPromise());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023131 rr->Reject(context.local(), v8::Integer::New(isolate, 2)).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023132 CHECK(r->IsPromise());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023133}
23134
23135
23136TEST(PromiseThen) {
23137 LocalContext context;
23138 v8::Isolate* isolate = context->GetIsolate();
23139 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023140 Local<Object> global = context->Global();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023141
23142 // Creation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023143 Local<v8::Promise::Resolver> pr =
23144 v8::Promise::Resolver::New(context.local()).ToLocalChecked();
23145 Local<v8::Promise::Resolver> qr =
23146 v8::Promise::Resolver::New(context.local()).ToLocalChecked();
23147 Local<v8::Promise> p = pr->GetPromise();
23148 Local<v8::Promise> q = qr->GetPromise();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023149
23150 CHECK(p->IsPromise());
23151 CHECK(q->IsPromise());
23152
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023153 pr->Resolve(context.local(), v8::Integer::New(isolate, 1)).FromJust();
23154 qr->Resolve(context.local(), p).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023155
23156 // Chaining non-pending promises.
23157 CompileRun(
23158 "var x1 = 0;\n"
23159 "var x2 = 0;\n"
23160 "function f1(x) { x1 = x; return x+1 };\n"
23161 "function f2(x) { x2 = x; return x+1 };\n");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023162 Local<Function> f1 = Local<Function>::Cast(
23163 global->Get(context.local(), v8_str("f1")).ToLocalChecked());
23164 Local<Function> f2 = Local<Function>::Cast(
23165 global->Get(context.local(), v8_str("f2")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023166
23167 // Then
23168 CompileRun("x1 = x2 = 0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023169 q->Then(context.local(), f1).ToLocalChecked();
23170 CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
23171 .ToLocalChecked()
23172 ->Int32Value(context.local())
23173 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023174 isolate->RunMicrotasks();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023175 CHECK_EQ(1, global->Get(context.local(), v8_str("x1"))
23176 .ToLocalChecked()
23177 ->Int32Value(context.local())
23178 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023179
23180 // Then
23181 CompileRun("x1 = x2 = 0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023182 pr = v8::Promise::Resolver::New(context.local()).ToLocalChecked();
23183 qr = v8::Promise::Resolver::New(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023184
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023185 qr->Resolve(context.local(), pr).FromJust();
23186 qr->GetPromise()
23187 ->Then(context.local(), f1)
23188 .ToLocalChecked()
23189 ->Then(context.local(), f2)
23190 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023191
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023192 CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
23193 .ToLocalChecked()
23194 ->Int32Value(context.local())
23195 .FromJust());
23196 CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
23197 .ToLocalChecked()
23198 ->Int32Value(context.local())
23199 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023200 isolate->RunMicrotasks();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023201 CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
23202 .ToLocalChecked()
23203 ->Int32Value(context.local())
23204 .FromJust());
23205 CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
23206 .ToLocalChecked()
23207 ->Int32Value(context.local())
23208 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023209
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023210 pr->Resolve(context.local(), v8::Integer::New(isolate, 3)).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023211
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023212 CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
23213 .ToLocalChecked()
23214 ->Int32Value(context.local())
23215 .FromJust());
23216 CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
23217 .ToLocalChecked()
23218 ->Int32Value(context.local())
23219 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023220 isolate->RunMicrotasks();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023221 CHECK_EQ(3, global->Get(context.local(), v8_str("x1"))
23222 .ToLocalChecked()
23223 ->Int32Value(context.local())
23224 .FromJust());
23225 CHECK_EQ(4, global->Get(context.local(), v8_str("x2"))
23226 .ToLocalChecked()
23227 ->Int32Value(context.local())
23228 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023229}
23230
23231
23232TEST(DisallowJavascriptExecutionScope) {
23233 LocalContext context;
23234 v8::Isolate* isolate = context->GetIsolate();
23235 v8::HandleScope scope(isolate);
23236 v8::Isolate::DisallowJavascriptExecutionScope no_js(
23237 isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
23238 CompileRun("2+2");
23239}
23240
23241
23242TEST(AllowJavascriptExecutionScope) {
23243 LocalContext context;
23244 v8::Isolate* isolate = context->GetIsolate();
23245 v8::HandleScope scope(isolate);
23246 v8::Isolate::DisallowJavascriptExecutionScope no_js(
23247 isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
23248 v8::Isolate::DisallowJavascriptExecutionScope throw_js(
23249 isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
23250 { v8::Isolate::AllowJavascriptExecutionScope yes_js(isolate);
23251 CompileRun("1+1");
23252 }
23253}
23254
23255
23256TEST(ThrowOnJavascriptExecution) {
23257 LocalContext context;
23258 v8::Isolate* isolate = context->GetIsolate();
23259 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023260 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023261 v8::Isolate::DisallowJavascriptExecutionScope throw_js(
23262 isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
23263 CompileRun("1+1");
23264 CHECK(try_catch.HasCaught());
23265}
23266
23267
23268TEST(Regress354123) {
23269 LocalContext current;
23270 v8::Isolate* isolate = current->GetIsolate();
23271 v8::HandleScope scope(isolate);
23272
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023273 v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
23274 templ->SetAccessCheckCallback(AccessCounter);
23275 CHECK(current->Global()
23276 ->Set(current.local(), v8_str("friend"),
23277 templ->NewInstance(current.local()).ToLocalChecked())
23278 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023279
23280 // Test access using __proto__ from the prototype chain.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023281 access_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023282 CompileRun("friend.__proto__ = {};");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023283 CHECK_EQ(2, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023284 CompileRun("friend.__proto__;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023285 CHECK_EQ(4, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023286
23287 // Test access using __proto__ as a hijacked function (A).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023288 access_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023289 CompileRun("var p = Object.prototype;"
23290 "var f = Object.getOwnPropertyDescriptor(p, '__proto__').set;"
23291 "f.call(friend, {});");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023292 CHECK_EQ(1, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023293 CompileRun("var p = Object.prototype;"
23294 "var f = Object.getOwnPropertyDescriptor(p, '__proto__').get;"
23295 "f.call(friend);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023296 CHECK_EQ(2, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023297
23298 // Test access using __proto__ as a hijacked function (B).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023299 access_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023300 CompileRun("var f = Object.prototype.__lookupSetter__('__proto__');"
23301 "f.call(friend, {});");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023302 CHECK_EQ(1, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023303 CompileRun("var f = Object.prototype.__lookupGetter__('__proto__');"
23304 "f.call(friend);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023305 CHECK_EQ(2, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023306
23307 // Test access using Object.setPrototypeOf reflective method.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023308 access_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023309 CompileRun("Object.setPrototypeOf(friend, {});");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023310 CHECK_EQ(1, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023311 CompileRun("Object.getPrototypeOf(friend);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023312 CHECK_EQ(2, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023313}
23314
23315
23316TEST(CaptureStackTraceForStackOverflow) {
23317 v8::internal::FLAG_stack_size = 150;
23318 LocalContext current;
23319 v8::Isolate* isolate = current->GetIsolate();
23320 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023321 isolate->SetCaptureStackTraceForUncaughtExceptions(true, 10,
23322 v8::StackTrace::kDetailed);
23323 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023324 CompileRun("(function f(x) { f(x+1); })(0)");
23325 CHECK(try_catch.HasCaught());
23326}
23327
23328
23329TEST(ScriptNameAndLineNumber) {
23330 LocalContext env;
23331 v8::Isolate* isolate = env->GetIsolate();
23332 v8::HandleScope scope(isolate);
23333 const char* url = "http://www.foo.com/foo.js";
23334 v8::ScriptOrigin origin(v8_str(url), v8::Integer::New(isolate, 13));
23335 v8::ScriptCompiler::Source script_source(v8_str("var foo;"), origin);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023336 Local<Script> script =
23337 v8::ScriptCompiler::Compile(env.local(), &script_source).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023338 Local<Value> script_name = script->GetUnboundScript()->GetScriptName();
23339 CHECK(!script_name.IsEmpty());
23340 CHECK(script_name->IsString());
23341 String::Utf8Value utf8_name(script_name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023342 CHECK_EQ(0, strcmp(url, *utf8_name));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023343 int line_number = script->GetUnboundScript()->GetLineNumber(0);
23344 CHECK_EQ(13, line_number);
23345}
23346
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023347void CheckMagicComments(Local<Script> script, const char* expected_source_url,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023348 const char* expected_source_mapping_url) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023349 if (expected_source_url != NULL) {
23350 v8::String::Utf8Value url(script->GetUnboundScript()->GetSourceURL());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023351 CHECK_EQ(0, strcmp(expected_source_url, *url));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023352 } else {
23353 CHECK(script->GetUnboundScript()->GetSourceURL()->IsUndefined());
23354 }
23355 if (expected_source_mapping_url != NULL) {
23356 v8::String::Utf8Value url(
23357 script->GetUnboundScript()->GetSourceMappingURL());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023358 CHECK_EQ(0, strcmp(expected_source_mapping_url, *url));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023359 } else {
23360 CHECK(script->GetUnboundScript()->GetSourceMappingURL()->IsUndefined());
23361 }
23362}
23363
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023364void SourceURLHelper(const char* source, const char* expected_source_url,
23365 const char* expected_source_mapping_url) {
23366 Local<Script> script = v8_compile(source);
23367 CheckMagicComments(script, expected_source_url, expected_source_mapping_url);
23368}
23369
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023370
23371TEST(ScriptSourceURLAndSourceMappingURL) {
23372 LocalContext env;
23373 v8::Isolate* isolate = env->GetIsolate();
23374 v8::HandleScope scope(isolate);
23375 SourceURLHelper("function foo() {}\n"
23376 "//# sourceURL=bar1.js\n", "bar1.js", NULL);
23377 SourceURLHelper("function foo() {}\n"
23378 "//# sourceMappingURL=bar2.js\n", NULL, "bar2.js");
23379
23380 // Both sourceURL and sourceMappingURL.
23381 SourceURLHelper("function foo() {}\n"
23382 "//# sourceURL=bar3.js\n"
23383 "//# sourceMappingURL=bar4.js\n", "bar3.js", "bar4.js");
23384
23385 // Two source URLs; the first one is ignored.
23386 SourceURLHelper("function foo() {}\n"
23387 "//# sourceURL=ignoreme.js\n"
23388 "//# sourceURL=bar5.js\n", "bar5.js", NULL);
23389 SourceURLHelper("function foo() {}\n"
23390 "//# sourceMappingURL=ignoreme.js\n"
23391 "//# sourceMappingURL=bar6.js\n", NULL, "bar6.js");
23392
23393 // SourceURL or sourceMappingURL in the middle of the script.
23394 SourceURLHelper("function foo() {}\n"
23395 "//# sourceURL=bar7.js\n"
23396 "function baz() {}\n", "bar7.js", NULL);
23397 SourceURLHelper("function foo() {}\n"
23398 "//# sourceMappingURL=bar8.js\n"
23399 "function baz() {}\n", NULL, "bar8.js");
23400
23401 // Too much whitespace.
23402 SourceURLHelper("function foo() {}\n"
23403 "//# sourceURL=bar9.js\n"
23404 "//# sourceMappingURL=bar10.js\n", NULL, NULL);
23405 SourceURLHelper("function foo() {}\n"
23406 "//# sourceURL =bar11.js\n"
23407 "//# sourceMappingURL =bar12.js\n", NULL, NULL);
23408
23409 // Disallowed characters in value.
23410 SourceURLHelper("function foo() {}\n"
23411 "//# sourceURL=bar13 .js \n"
23412 "//# sourceMappingURL=bar14 .js \n",
23413 NULL, NULL);
23414 SourceURLHelper("function foo() {}\n"
23415 "//# sourceURL=bar15\t.js \n"
23416 "//# sourceMappingURL=bar16\t.js \n",
23417 NULL, NULL);
23418 SourceURLHelper("function foo() {}\n"
23419 "//# sourceURL=bar17'.js \n"
23420 "//# sourceMappingURL=bar18'.js \n",
23421 NULL, NULL);
23422 SourceURLHelper("function foo() {}\n"
23423 "//# sourceURL=bar19\".js \n"
23424 "//# sourceMappingURL=bar20\".js \n",
23425 NULL, NULL);
23426
23427 // Not too much whitespace.
23428 SourceURLHelper("function foo() {}\n"
23429 "//# sourceURL= bar21.js \n"
23430 "//# sourceMappingURL= bar22.js \n", "bar21.js", "bar22.js");
23431}
23432
23433
23434TEST(GetOwnPropertyDescriptor) {
23435 LocalContext env;
23436 v8::Isolate* isolate = env->GetIsolate();
23437 v8::HandleScope scope(isolate);
23438 CompileRun(
23439 "var x = { value : 13};"
23440 "Object.defineProperty(x, 'p0', {value : 12});"
23441 "Object.defineProperty(x, 'p1', {"
23442 " set : function(value) { this.value = value; },"
23443 " get : function() { return this.value; },"
23444 "});");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023445 Local<Object> x = Local<Object>::Cast(
23446 env->Global()->Get(env.local(), v8_str("x")).ToLocalChecked());
23447 Local<Value> desc =
23448 x->GetOwnPropertyDescriptor(env.local(), v8_str("no_prop"))
23449 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023450 CHECK(desc->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023451 desc =
23452 x->GetOwnPropertyDescriptor(env.local(), v8_str("p0")).ToLocalChecked();
23453 CHECK(v8_num(12)
23454 ->Equals(env.local(), Local<Object>::Cast(desc)
23455 ->Get(env.local(), v8_str("value"))
23456 .ToLocalChecked())
23457 .FromJust());
23458 desc =
23459 x->GetOwnPropertyDescriptor(env.local(), v8_str("p1")).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023460 Local<Function> set =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023461 Local<Function>::Cast(Local<Object>::Cast(desc)
23462 ->Get(env.local(), v8_str("set"))
23463 .ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023464 Local<Function> get =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023465 Local<Function>::Cast(Local<Object>::Cast(desc)
23466 ->Get(env.local(), v8_str("get"))
23467 .ToLocalChecked());
23468 CHECK(v8_num(13)
23469 ->Equals(env.local(),
23470 get->Call(env.local(), x, 0, NULL).ToLocalChecked())
23471 .FromJust());
23472 Local<Value> args[] = {v8_num(14)};
23473 set->Call(env.local(), x, 1, args).ToLocalChecked();
23474 CHECK(v8_num(14)
23475 ->Equals(env.local(),
23476 get->Call(env.local(), x, 0, NULL).ToLocalChecked())
23477 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023478}
23479
23480
23481TEST(Regress411877) {
23482 v8::Isolate* isolate = CcTest::isolate();
23483 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023484 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023485 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023486 object_template->SetAccessCheckCallback(AccessCounter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023487
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023488 v8::Local<Context> context = Context::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023489 v8::Context::Scope context_scope(context);
23490
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023491 CHECK(context->Global()
23492 ->Set(context, v8_str("o"),
23493 object_template->NewInstance(context).ToLocalChecked())
23494 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023495 CompileRun("Object.getOwnPropertyNames(o)");
23496}
23497
23498
23499TEST(GetHiddenPropertyTableAfterAccessCheck) {
23500 v8::Isolate* isolate = CcTest::isolate();
23501 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023502 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023503 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023504 object_template->SetAccessCheckCallback(AccessCounter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023505
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023506 v8::Local<Context> context = Context::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023507 v8::Context::Scope context_scope(context);
23508
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023509 v8::Local<v8::Object> obj =
23510 object_template->NewInstance(context).ToLocalChecked();
23511 obj->Set(context, v8_str("key"), v8_str("value")).FromJust();
23512 obj->Delete(context, v8_str("key")).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023513
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023514 obj->SetPrivate(context, v8::Private::New(isolate, v8_str("hidden key 2")),
23515 v8_str("hidden value 2"))
23516 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023517}
23518
23519
23520TEST(Regress411793) {
23521 v8::Isolate* isolate = CcTest::isolate();
23522 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023523 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023524 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023525 object_template->SetAccessCheckCallback(AccessCounter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023526
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023527 v8::Local<Context> context = Context::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023528 v8::Context::Scope context_scope(context);
23529
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023530 CHECK(context->Global()
23531 ->Set(context, v8_str("o"),
23532 object_template->NewInstance(context).ToLocalChecked())
23533 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023534 CompileRun(
23535 "Object.defineProperty(o, 'key', "
23536 " { get: function() {}, set: function() {} });");
23537}
23538
23539class TestSourceStream : public v8::ScriptCompiler::ExternalSourceStream {
23540 public:
23541 explicit TestSourceStream(const char** chunks) : chunks_(chunks), index_(0) {}
23542
23543 virtual size_t GetMoreData(const uint8_t** src) {
23544 // Unlike in real use cases, this function will never block.
23545 if (chunks_[index_] == NULL) {
23546 return 0;
23547 }
23548 // Copy the data, since the caller takes ownership of it.
23549 size_t len = strlen(chunks_[index_]);
23550 // We don't need to zero-terminate since we return the length.
23551 uint8_t* copy = new uint8_t[len];
23552 memcpy(copy, chunks_[index_], len);
23553 *src = copy;
23554 ++index_;
23555 return len;
23556 }
23557
23558 // Helper for constructing a string from chunks (the compilation needs it
23559 // too).
23560 static char* FullSourceString(const char** chunks) {
23561 size_t total_len = 0;
23562 for (size_t i = 0; chunks[i] != NULL; ++i) {
23563 total_len += strlen(chunks[i]);
23564 }
23565 char* full_string = new char[total_len + 1];
23566 size_t offset = 0;
23567 for (size_t i = 0; chunks[i] != NULL; ++i) {
23568 size_t len = strlen(chunks[i]);
23569 memcpy(full_string + offset, chunks[i], len);
23570 offset += len;
23571 }
23572 full_string[total_len] = 0;
23573 return full_string;
23574 }
23575
23576 private:
23577 const char** chunks_;
23578 unsigned index_;
23579};
23580
23581
23582// Helper function for running streaming tests.
23583void RunStreamingTest(const char** chunks,
23584 v8::ScriptCompiler::StreamedSource::Encoding encoding =
23585 v8::ScriptCompiler::StreamedSource::ONE_BYTE,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023586 bool expected_success = true,
23587 const char* expected_source_url = NULL,
23588 const char* expected_source_mapping_url = NULL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023589 LocalContext env;
23590 v8::Isolate* isolate = env->GetIsolate();
23591 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023592 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023593
23594 v8::ScriptCompiler::StreamedSource source(new TestSourceStream(chunks),
23595 encoding);
23596 v8::ScriptCompiler::ScriptStreamingTask* task =
23597 v8::ScriptCompiler::StartStreamingScript(isolate, &source);
23598
23599 // TestSourceStream::GetMoreData won't block, so it's OK to just run the
23600 // task here in the main thread.
23601 task->Run();
23602 delete task;
23603
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023604 // Possible errors are only produced while compiling.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023605 CHECK_EQ(false, try_catch.HasCaught());
23606
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023607 v8::ScriptOrigin origin(v8_str("http://foo.com"));
23608 char* full_source = TestSourceStream::FullSourceString(chunks);
23609 v8::MaybeLocal<Script> script = v8::ScriptCompiler::Compile(
23610 env.local(), &source, v8_str(full_source), origin);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023611 if (expected_success) {
23612 CHECK(!script.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023613 v8::Local<Value> result(
23614 script.ToLocalChecked()->Run(env.local()).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023615 // All scripts are supposed to return the fixed value 13 when ran.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023616 CHECK_EQ(13, result->Int32Value(env.local()).FromJust());
23617 CheckMagicComments(script.ToLocalChecked(), expected_source_url,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023618 expected_source_mapping_url);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023619 } else {
23620 CHECK(script.IsEmpty());
23621 CHECK(try_catch.HasCaught());
23622 }
23623 delete[] full_source;
23624}
23625
23626
23627TEST(StreamingSimpleScript) {
23628 // This script is unrealistically small, since no one chunk is enough to fill
23629 // the backing buffer of Scanner, let alone overflow it.
23630 const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
23631 NULL};
23632 RunStreamingTest(chunks);
23633}
23634
23635
23636TEST(StreamingBiggerScript) {
23637 const char* chunk1 =
23638 "function foo() {\n"
23639 " // Make this chunk sufficiently long so that it will overflow the\n"
23640 " // backing buffer of the Scanner.\n"
23641 " var i = 0;\n"
23642 " var result = 0;\n"
23643 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
23644 " result = 0;\n"
23645 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
23646 " result = 0;\n"
23647 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
23648 " result = 0;\n"
23649 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
23650 " return result;\n"
23651 "}\n";
23652 const char* chunks[] = {chunk1, "foo(); ", NULL};
23653 RunStreamingTest(chunks);
23654}
23655
23656
23657TEST(StreamingScriptWithParseError) {
23658 // Test that parse errors from streamed scripts are propagated correctly.
23659 {
23660 char chunk1[] =
23661 " // This will result in a parse error.\n"
23662 " var if else then foo";
23663 char chunk2[] = " 13\n";
23664 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23665
23666 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::ONE_BYTE,
23667 false);
23668 }
23669 // Test that the next script succeeds normally.
23670 {
23671 char chunk1[] =
23672 " // This will be parsed successfully.\n"
23673 " function foo() { return ";
23674 char chunk2[] = " 13; }\n";
23675 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23676
23677 RunStreamingTest(chunks);
23678 }
23679}
23680
23681
23682TEST(StreamingUtf8Script) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023683 // We'd want to write \uc481 instead of \xec\x92\x81, but Windows compilers
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023684 // don't like it.
23685 const char* chunk1 =
23686 "function foo() {\n"
23687 " // This function will contain an UTF-8 character which is not in\n"
23688 " // ASCII.\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023689 " var foob\xec\x92\x81r = 13;\n"
23690 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023691 "}\n";
23692 const char* chunks[] = {chunk1, "foo(); ", NULL};
23693 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23694}
23695
23696
23697TEST(StreamingUtf8ScriptWithSplitCharactersSanityCheck) {
23698 // A sanity check to prove that the approach of splitting UTF-8
23699 // characters is correct. Here is an UTF-8 character which will take three
23700 // bytes.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023701 const char* reference = "\xec\x92\x81";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023702 CHECK(3u == strlen(reference)); // NOLINT - no CHECK_EQ for unsigned.
23703
23704 char chunk1[] =
23705 "function foo() {\n"
23706 " // This function will contain an UTF-8 character which is not in\n"
23707 " // ASCII.\n"
23708 " var foob";
23709 char chunk2[] =
23710 "XXXr = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023711 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023712 "}\n";
23713 for (int i = 0; i < 3; ++i) {
23714 chunk2[i] = reference[i];
23715 }
23716 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23717 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23718}
23719
23720
23721TEST(StreamingUtf8ScriptWithSplitCharacters) {
23722 // Stream data where a multi-byte UTF-8 character is split between two data
23723 // chunks.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023724 const char* reference = "\xec\x92\x81";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023725 char chunk1[] =
23726 "function foo() {\n"
23727 " // This function will contain an UTF-8 character which is not in\n"
23728 " // ASCII.\n"
23729 " var foobX";
23730 char chunk2[] =
23731 "XXr = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023732 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023733 "}\n";
23734 chunk1[strlen(chunk1) - 1] = reference[0];
23735 chunk2[0] = reference[1];
23736 chunk2[1] = reference[2];
23737 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23738 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23739}
23740
23741
23742TEST(StreamingUtf8ScriptWithSplitCharactersValidEdgeCases) {
23743 // Tests edge cases which should still be decoded correctly.
23744
23745 // Case 1: a chunk contains only bytes for a split character (and no other
23746 // data). This kind of a chunk would be exceptionally small, but we should
23747 // still decode it correctly.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023748 const char* reference = "\xec\x92\x81";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023749 // The small chunk is at the beginning of the split character
23750 {
23751 char chunk1[] =
23752 "function foo() {\n"
23753 " // This function will contain an UTF-8 character which is not in\n"
23754 " // ASCII.\n"
23755 " var foob";
23756 char chunk2[] = "XX";
23757 char chunk3[] =
23758 "Xr = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023759 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023760 "}\n";
23761 chunk2[0] = reference[0];
23762 chunk2[1] = reference[1];
23763 chunk3[0] = reference[2];
23764 const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
23765 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23766 }
23767 // The small chunk is at the end of a character
23768 {
23769 char chunk1[] =
23770 "function foo() {\n"
23771 " // This function will contain an UTF-8 character which is not in\n"
23772 " // ASCII.\n"
23773 " var foobX";
23774 char chunk2[] = "XX";
23775 char chunk3[] =
23776 "r = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023777 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023778 "}\n";
23779 chunk1[strlen(chunk1) - 1] = reference[0];
23780 chunk2[0] = reference[1];
23781 chunk2[1] = reference[2];
23782 const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
23783 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23784 }
23785 // Case 2: the script ends with a multi-byte character. Make sure that it's
23786 // decoded correctly and not just ignored.
23787 {
23788 char chunk1[] =
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023789 "var foob\xec\x92\x81 = 13;\n"
23790 "foob\xec\x92\x81";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023791 const char* chunks[] = {chunk1, NULL};
23792 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23793 }
23794}
23795
23796
23797TEST(StreamingUtf8ScriptWithSplitCharactersInvalidEdgeCases) {
23798 // Test cases where a UTF-8 character is split over several chunks. Those
23799 // cases are not supported (the embedder should give the data in big enough
23800 // chunks), but we shouldn't crash, just produce a parse error.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023801 const char* reference = "\xec\x92\x81";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023802 char chunk1[] =
23803 "function foo() {\n"
23804 " // This function will contain an UTF-8 character which is not in\n"
23805 " // ASCII.\n"
23806 " var foobX";
23807 char chunk2[] = "X";
23808 char chunk3[] =
23809 "Xr = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023810 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023811 "}\n";
23812 chunk1[strlen(chunk1) - 1] = reference[0];
23813 chunk2[0] = reference[1];
23814 chunk3[0] = reference[2];
23815 const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
23816
23817 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
23818}
23819
23820
23821TEST(StreamingProducesParserCache) {
23822 i::FLAG_min_preparse_length = 0;
23823 const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
23824 NULL};
23825
23826 LocalContext env;
23827 v8::Isolate* isolate = env->GetIsolate();
23828 v8::HandleScope scope(isolate);
23829
23830 v8::ScriptCompiler::StreamedSource source(
23831 new TestSourceStream(chunks),
23832 v8::ScriptCompiler::StreamedSource::ONE_BYTE);
23833 v8::ScriptCompiler::ScriptStreamingTask* task =
23834 v8::ScriptCompiler::StartStreamingScript(
23835 isolate, &source, v8::ScriptCompiler::kProduceParserCache);
23836
23837 // TestSourceStream::GetMoreData won't block, so it's OK to just run the
23838 // task here in the main thread.
23839 task->Run();
23840 delete task;
23841
23842 const v8::ScriptCompiler::CachedData* cached_data = source.GetCachedData();
23843 CHECK(cached_data != NULL);
23844 CHECK(cached_data->data != NULL);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023845 CHECK(!cached_data->rejected);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023846 CHECK_GT(cached_data->length, 0);
23847}
23848
23849
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023850TEST(StreamingWithDebuggingEnabledLate) {
23851 // The streaming parser can only parse lazily, i.e. inner functions are not
23852 // fully parsed. However, we may compile inner functions eagerly when
23853 // debugging. Make sure that we can deal with this when turning on debugging
23854 // after streaming parser has already finished parsing.
23855 i::FLAG_min_preparse_length = 0;
23856 const char* chunks[] = {"with({x:1}) {",
23857 " var foo = function foo(y) {",
23858 " return x + y;",
23859 " };",
23860 " foo(2);",
23861 "}",
23862 NULL};
23863
23864 LocalContext env;
23865 v8::Isolate* isolate = env->GetIsolate();
23866 v8::HandleScope scope(isolate);
23867 v8::TryCatch try_catch(isolate);
23868
23869 v8::ScriptCompiler::StreamedSource source(
23870 new TestSourceStream(chunks),
23871 v8::ScriptCompiler::StreamedSource::ONE_BYTE);
23872 v8::ScriptCompiler::ScriptStreamingTask* task =
23873 v8::ScriptCompiler::StartStreamingScript(isolate, &source);
23874
23875 task->Run();
23876 delete task;
23877
23878 CHECK(!try_catch.HasCaught());
23879
23880 v8::ScriptOrigin origin(v8_str("http://foo.com"));
23881 char* full_source = TestSourceStream::FullSourceString(chunks);
23882
23883 EnableDebugger(isolate);
23884
23885 v8::Local<Script> script =
23886 v8::ScriptCompiler::Compile(env.local(), &source, v8_str(full_source),
23887 origin)
23888 .ToLocalChecked();
23889
23890 Maybe<uint32_t> result =
23891 script->Run(env.local()).ToLocalChecked()->Uint32Value(env.local());
23892 CHECK_EQ(3U, result.FromMaybe(0));
23893
23894 delete[] full_source;
23895
23896 DisableDebugger(isolate);
23897}
23898
23899
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023900TEST(StreamingScriptWithInvalidUtf8) {
23901 // Regression test for a crash: test that invalid UTF-8 bytes in the end of a
23902 // chunk don't produce a crash.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023903 const char* reference = "\xec\x92\x81\x80\x80";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023904 char chunk1[] =
23905 "function foo() {\n"
23906 " // This function will contain an UTF-8 character which is not in\n"
23907 " // ASCII.\n"
23908 " var foobXXXXX"; // Too many bytes which look like incomplete chars!
23909 char chunk2[] =
23910 "r = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023911 " return foob\xec\x92\x81\x80\x80r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023912 "}\n";
23913 for (int i = 0; i < 5; ++i) chunk1[strlen(chunk1) - 5 + i] = reference[i];
23914
23915 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23916 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
23917}
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023918
23919
23920TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit) {
23921 // Regression test: Stream data where there are several multi-byte UTF-8
23922 // characters in a sequence and one of them is split between two data chunks.
23923 const char* reference = "\xec\x92\x81";
23924 char chunk1[] =
23925 "function foo() {\n"
23926 " // This function will contain an UTF-8 character which is not in\n"
23927 " // ASCII.\n"
23928 " var foob\xec\x92\x81X";
23929 char chunk2[] =
23930 "XXr = 13;\n"
23931 " return foob\xec\x92\x81\xec\x92\x81r;\n"
23932 "}\n";
23933 chunk1[strlen(chunk1) - 1] = reference[0];
23934 chunk2[0] = reference[1];
23935 chunk2[1] = reference[2];
23936 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23937 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23938}
23939
23940
23941TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit2) {
23942 // Another regression test, similar to the previous one. The difference is
23943 // that the split character is not the last one in the sequence.
23944 const char* reference = "\xec\x92\x81";
23945 char chunk1[] =
23946 "function foo() {\n"
23947 " // This function will contain an UTF-8 character which is not in\n"
23948 " // ASCII.\n"
23949 " var foobX";
23950 char chunk2[] =
23951 "XX\xec\x92\x81r = 13;\n"
23952 " return foob\xec\x92\x81\xec\x92\x81r;\n"
23953 "}\n";
23954 chunk1[strlen(chunk1) - 1] = reference[0];
23955 chunk2[0] = reference[1];
23956 chunk2[1] = reference[2];
23957 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23958 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23959}
23960
23961
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023962TEST(StreamingWithHarmonyScopes) {
23963 // Don't use RunStreamingTest here so that both scripts get to use the same
23964 // LocalContext and HandleScope.
23965 LocalContext env;
23966 v8::Isolate* isolate = env->GetIsolate();
23967 v8::HandleScope scope(isolate);
23968
23969 // First, run a script with a let variable.
23970 CompileRun("\"use strict\"; let x = 1;");
23971
23972 // Then stream a script which (erroneously) tries to introduce the same
23973 // variable again.
23974 const char* chunks[] = {"\"use strict\"; let x = 2;", NULL};
23975
23976 v8::TryCatch try_catch(isolate);
23977 v8::ScriptCompiler::StreamedSource source(
23978 new TestSourceStream(chunks),
23979 v8::ScriptCompiler::StreamedSource::ONE_BYTE);
23980 v8::ScriptCompiler::ScriptStreamingTask* task =
23981 v8::ScriptCompiler::StartStreamingScript(isolate, &source);
23982 task->Run();
23983 delete task;
23984
23985 // Parsing should succeed (the script will be parsed and compiled in a context
23986 // independent way, so the error is not detected).
23987 CHECK_EQ(false, try_catch.HasCaught());
23988
23989 v8::ScriptOrigin origin(v8_str("http://foo.com"));
23990 char* full_source = TestSourceStream::FullSourceString(chunks);
23991 v8::Local<Script> script =
23992 v8::ScriptCompiler::Compile(env.local(), &source, v8_str(full_source),
23993 origin)
23994 .ToLocalChecked();
23995 CHECK(!script.IsEmpty());
23996 CHECK_EQ(false, try_catch.HasCaught());
23997
23998 // Running the script exposes the error.
23999 CHECK(script->Run(env.local()).IsEmpty());
24000 CHECK(try_catch.HasCaught());
24001 delete[] full_source;
24002}
24003
24004
24005TEST(CodeCache) {
24006 v8::Isolate::CreateParams create_params;
24007 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
24008
24009 const char* source = "Math.sqrt(4)";
24010 const char* origin = "code cache test";
24011 v8::ScriptCompiler::CachedData* cache;
24012
24013 v8::Isolate* isolate1 = v8::Isolate::New(create_params);
24014 {
24015 v8::Isolate::Scope iscope(isolate1);
24016 v8::HandleScope scope(isolate1);
24017 v8::Local<v8::Context> context = v8::Context::New(isolate1);
24018 v8::Context::Scope cscope(context);
24019 v8::Local<v8::String> source_string = v8_str(source);
24020 v8::ScriptOrigin script_origin(v8_str(origin));
24021 v8::ScriptCompiler::Source source(source_string, script_origin);
24022 v8::ScriptCompiler::CompileOptions option =
24023 v8::ScriptCompiler::kProduceCodeCache;
24024 v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked();
24025 int length = source.GetCachedData()->length;
24026 uint8_t* cache_data = new uint8_t[length];
24027 memcpy(cache_data, source.GetCachedData()->data, length);
24028 cache = new v8::ScriptCompiler::CachedData(
24029 cache_data, length, v8::ScriptCompiler::CachedData::BufferOwned);
24030 }
24031 isolate1->Dispose();
24032
24033 v8::Isolate* isolate2 = v8::Isolate::New(create_params);
24034 {
24035 v8::Isolate::Scope iscope(isolate2);
24036 v8::HandleScope scope(isolate2);
24037 v8::Local<v8::Context> context = v8::Context::New(isolate2);
24038 v8::Context::Scope cscope(context);
24039 v8::Local<v8::String> source_string = v8_str(source);
24040 v8::ScriptOrigin script_origin(v8_str(origin));
24041 v8::ScriptCompiler::Source source(source_string, script_origin, cache);
24042 v8::ScriptCompiler::CompileOptions option =
24043 v8::ScriptCompiler::kConsumeCodeCache;
24044 v8::Local<v8::Script> script;
24045 {
24046 i::DisallowCompilation no_compile(
24047 reinterpret_cast<i::Isolate*>(isolate2));
24048 script = v8::ScriptCompiler::Compile(context, &source, option)
24049 .ToLocalChecked();
24050 }
24051 CHECK_EQ(2, script->Run(context)
24052 .ToLocalChecked()
24053 ->ToInt32(context)
24054 .ToLocalChecked()
24055 ->Int32Value(context)
24056 .FromJust());
24057 }
24058 isolate2->Dispose();
24059}
24060
24061
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024062void TestInvalidCacheData(v8::ScriptCompiler::CompileOptions option) {
24063 const char* garbage = "garbage garbage garbage garbage garbage garbage";
24064 const uint8_t* data = reinterpret_cast<const uint8_t*>(garbage);
24065 int length = 16;
24066 v8::ScriptCompiler::CachedData* cached_data =
24067 new v8::ScriptCompiler::CachedData(data, length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024068 CHECK(!cached_data->rejected);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024069 v8::ScriptOrigin origin(v8_str("origin"));
24070 v8::ScriptCompiler::Source source(v8_str("42"), origin, cached_data);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024071 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
24072 v8::Local<v8::Script> script =
24073 v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024074 CHECK(cached_data->rejected);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024075 CHECK_EQ(
24076 42,
24077 script->Run(context).ToLocalChecked()->Int32Value(context).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024078}
24079
24080
24081TEST(InvalidCacheData) {
24082 v8::V8::Initialize();
24083 v8::HandleScope scope(CcTest::isolate());
24084 LocalContext context;
Ben Murdochda12d292016-06-02 14:46:10 +010024085 if (i::FLAG_lazy && !(i::FLAG_ignition && i::FLAG_ignition_eager)) {
24086 // Cached parser data is not consumed while parsing eagerly.
24087 TestInvalidCacheData(v8::ScriptCompiler::kConsumeParserCache);
24088 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024089 TestInvalidCacheData(v8::ScriptCompiler::kConsumeCodeCache);
24090}
24091
24092
24093TEST(ParserCacheRejectedGracefully) {
Ben Murdochda12d292016-06-02 14:46:10 +010024094 // Producing cached parser data while parsing eagerly is not supported.
24095 if (!i::FLAG_lazy || (i::FLAG_ignition && i::FLAG_ignition_eager)) return;
24096
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024097 i::FLAG_min_preparse_length = 0;
24098 v8::V8::Initialize();
24099 v8::HandleScope scope(CcTest::isolate());
24100 LocalContext context;
24101 // Produce valid cached data.
24102 v8::ScriptOrigin origin(v8_str("origin"));
24103 v8::Local<v8::String> source_str = v8_str("function foo() {}");
24104 v8::ScriptCompiler::Source source(source_str, origin);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024105 v8::Local<v8::Script> script =
24106 v8::ScriptCompiler::Compile(context.local(), &source,
24107 v8::ScriptCompiler::kProduceParserCache)
24108 .ToLocalChecked();
24109 USE(script);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024110 const v8::ScriptCompiler::CachedData* original_cached_data =
24111 source.GetCachedData();
24112 CHECK(original_cached_data != NULL);
24113 CHECK(original_cached_data->data != NULL);
24114 CHECK(!original_cached_data->rejected);
24115 CHECK_GT(original_cached_data->length, 0);
24116 // Recompiling the same script with it won't reject the data.
24117 {
24118 v8::ScriptCompiler::Source source_with_cached_data(
24119 source_str, origin,
24120 new v8::ScriptCompiler::CachedData(original_cached_data->data,
24121 original_cached_data->length));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024122 v8::Local<v8::Script> script =
24123 v8::ScriptCompiler::Compile(context.local(), &source_with_cached_data,
24124 v8::ScriptCompiler::kConsumeParserCache)
24125 .ToLocalChecked();
24126 USE(script);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024127 const v8::ScriptCompiler::CachedData* new_cached_data =
24128 source_with_cached_data.GetCachedData();
24129 CHECK(new_cached_data != NULL);
24130 CHECK(!new_cached_data->rejected);
24131 }
24132 // Compile an incompatible script with the cached data. The new script doesn't
24133 // have the same starting position for the function as the old one, so the old
24134 // cached data will be incompatible with it and will be rejected.
24135 {
24136 v8::Local<v8::String> incompatible_source_str =
24137 v8_str(" function foo() {}");
24138 v8::ScriptCompiler::Source source_with_cached_data(
24139 incompatible_source_str, origin,
24140 new v8::ScriptCompiler::CachedData(original_cached_data->data,
24141 original_cached_data->length));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024142 v8::Local<v8::Script> script =
24143 v8::ScriptCompiler::Compile(context.local(), &source_with_cached_data,
24144 v8::ScriptCompiler::kConsumeParserCache)
24145 .ToLocalChecked();
24146 USE(script);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024147 const v8::ScriptCompiler::CachedData* new_cached_data =
24148 source_with_cached_data.GetCachedData();
24149 CHECK(new_cached_data != NULL);
24150 CHECK(new_cached_data->rejected);
24151 }
24152}
24153
24154
24155TEST(StringConcatOverflow) {
24156 v8::V8::Initialize();
24157 v8::HandleScope scope(CcTest::isolate());
24158 RandomLengthOneByteResource* r =
24159 new RandomLengthOneByteResource(i::String::kMaxLength);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024160 v8::Local<v8::String> str =
24161 v8::String::NewExternalOneByte(CcTest::isolate(), r).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024162 CHECK(!str.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024163 v8::TryCatch try_catch(CcTest::isolate());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024164 v8::Local<v8::String> result = v8::String::Concat(str, str);
24165 CHECK(result.IsEmpty());
24166 CHECK(!try_catch.HasCaught());
24167}
24168
24169
24170TEST(TurboAsmDisablesNeuter) {
24171 v8::V8::Initialize();
24172 v8::HandleScope scope(CcTest::isolate());
24173 LocalContext context;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024174 bool should_be_neuterable = !i::FLAG_turbo_asm;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024175 const char* load =
24176 "function Module(stdlib, foreign, heap) {"
24177 " 'use asm';"
24178 " var MEM32 = new stdlib.Int32Array(heap);"
24179 " function load() { return MEM32[0]; }"
24180 " return { load: load };"
24181 "}"
24182 "var buffer = new ArrayBuffer(4);"
24183 "Module(this, {}, buffer).load();"
24184 "buffer";
24185
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024186 i::FLAG_turbo_osr = false; // TODO(titzer): test requires eager TF.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024187 v8::Local<v8::ArrayBuffer> result = CompileRun(load).As<v8::ArrayBuffer>();
24188 CHECK_EQ(should_be_neuterable, result->IsNeuterable());
24189
24190 const char* store =
24191 "function Module(stdlib, foreign, heap) {"
24192 " 'use asm';"
24193 " var MEM32 = new stdlib.Int32Array(heap);"
24194 " function store() { MEM32[0] = 0; }"
24195 " return { store: store };"
24196 "}"
24197 "var buffer = new ArrayBuffer(4);"
24198 "Module(this, {}, buffer).store();"
24199 "buffer";
24200
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024201 i::FLAG_turbo_osr = false; // TODO(titzer): test requires eager TF.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024202 result = CompileRun(store).As<v8::ArrayBuffer>();
24203 CHECK_EQ(should_be_neuterable, result->IsNeuterable());
24204}
24205
24206
24207TEST(GetPrototypeAccessControl) {
24208 i::FLAG_allow_natives_syntax = true;
24209 v8::Isolate* isolate = CcTest::isolate();
24210 v8::HandleScope handle_scope(isolate);
24211 LocalContext env;
24212
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024213 v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
24214 obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024215
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024216 CHECK(env->Global()
24217 ->Set(env.local(), v8_str("prohibited"),
24218 obj_template->NewInstance(env.local()).ToLocalChecked())
24219 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024220
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024221 CHECK(CompileRun(
24222 "function f() { return %_GetPrototype(prohibited); }"
24223 "%OptimizeFunctionOnNextCall(f);"
24224 "f();")->IsNull());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024225}
24226
24227
24228TEST(GetPrototypeHidden) {
24229 i::FLAG_allow_natives_syntax = true;
24230 v8::Isolate* isolate = CcTest::isolate();
24231 v8::HandleScope handle_scope(isolate);
24232 LocalContext env;
24233
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024234 Local<FunctionTemplate> t = FunctionTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024235 t->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024236 Local<Object> proto = t->GetFunction(env.local())
24237 .ToLocalChecked()
24238 ->NewInstance(env.local())
24239 .ToLocalChecked();
24240 Local<Object> object = Object::New(isolate);
24241 Local<Object> proto2 = Object::New(isolate);
24242 object->SetPrototype(env.local(), proto).FromJust();
24243 proto->SetPrototype(env.local(), proto2).FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024244
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024245 CHECK(env->Global()->Set(env.local(), v8_str("object"), object).FromJust());
24246 CHECK(env->Global()->Set(env.local(), v8_str("proto"), proto).FromJust());
24247 CHECK(env->Global()->Set(env.local(), v8_str("proto2"), proto2).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024248
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024249 v8::Local<v8::Value> result = CompileRun("%_GetPrototype(object)");
24250 CHECK(result->Equals(env.local(), proto2).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024251
24252 result = CompileRun(
24253 "function f() { return %_GetPrototype(object); }"
24254 "%OptimizeFunctionOnNextCall(f);"
24255 "f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024256 CHECK(result->Equals(env.local(), proto2).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024257}
24258
24259
24260TEST(ClassPrototypeCreationContext) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024261 v8::Isolate* isolate = CcTest::isolate();
24262 v8::HandleScope handle_scope(isolate);
24263 LocalContext env;
24264
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024265 Local<Object> result = Local<Object>::Cast(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024266 CompileRun("'use strict'; class Example { }; Example.prototype"));
24267 CHECK(env.local() == result->CreationContext());
24268}
24269
24270
24271TEST(SimpleStreamingScriptWithSourceURL) {
24272 const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo();\n",
24273 "//# sourceURL=bar2.js\n", NULL};
24274 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
24275 "bar2.js");
24276}
24277
24278
24279TEST(StreamingScriptWithSplitSourceURL) {
24280 const char* chunks[] = {"function foo() { ret", "urn 13; } f",
24281 "oo();\n//# sourceURL=b", "ar2.js\n", NULL};
24282 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
24283 "bar2.js");
24284}
24285
24286
24287TEST(StreamingScriptWithSourceMappingURLInTheMiddle) {
24288 const char* chunks[] = {"function foo() { ret", "urn 13; }\n//#",
24289 " sourceMappingURL=bar2.js\n", "foo();", NULL};
24290 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true, NULL,
24291 "bar2.js");
24292}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024293
24294
24295TEST(NewStringRangeError) {
24296 v8::Isolate* isolate = CcTest::isolate();
24297 v8::HandleScope handle_scope(isolate);
24298 const int length = i::String::kMaxLength + 1;
24299 const int buffer_size = length * sizeof(uint16_t);
24300 void* buffer = malloc(buffer_size);
24301 if (buffer == NULL) return;
24302 memset(buffer, 'A', buffer_size);
24303 {
24304 v8::TryCatch try_catch(isolate);
24305 char* data = reinterpret_cast<char*>(buffer);
24306 CHECK(v8::String::NewFromUtf8(isolate, data, v8::NewStringType::kNormal,
24307 length)
24308 .IsEmpty());
24309 CHECK(!try_catch.HasCaught());
24310 }
24311 {
24312 v8::TryCatch try_catch(isolate);
24313 uint8_t* data = reinterpret_cast<uint8_t*>(buffer);
24314 CHECK(v8::String::NewFromOneByte(isolate, data, v8::NewStringType::kNormal,
24315 length)
24316 .IsEmpty());
24317 CHECK(!try_catch.HasCaught());
24318 }
24319 {
24320 v8::TryCatch try_catch(isolate);
24321 uint16_t* data = reinterpret_cast<uint16_t*>(buffer);
24322 CHECK(v8::String::NewFromTwoByte(isolate, data, v8::NewStringType::kNormal,
24323 length)
24324 .IsEmpty());
24325 CHECK(!try_catch.HasCaught());
24326 }
24327 free(buffer);
24328}
24329
24330
24331TEST(SealHandleScope) {
24332 v8::Isolate* isolate = CcTest::isolate();
24333 v8::HandleScope handle_scope(isolate);
24334 LocalContext env;
24335
24336 v8::SealHandleScope seal(isolate);
24337
24338 // Should fail
24339 v8::Local<v8::Object> obj = v8::Object::New(isolate);
24340
24341 USE(obj);
24342}
24343
24344
24345TEST(SealHandleScopeNested) {
24346 v8::Isolate* isolate = CcTest::isolate();
24347 v8::HandleScope handle_scope(isolate);
24348 LocalContext env;
24349
24350 v8::SealHandleScope seal(isolate);
24351
24352 {
24353 v8::HandleScope handle_scope(isolate);
24354
24355 // Should work
24356 v8::Local<v8::Object> obj = v8::Object::New(isolate);
24357
24358 USE(obj);
24359 }
24360}
24361
24362
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024363static void ExtrasBindingTestRuntimeFunction(
24364 const v8::FunctionCallbackInfo<v8::Value>& args) {
24365 CHECK_EQ(
24366 3,
24367 args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust());
24368 args.GetReturnValue().Set(v8_num(7));
24369}
24370
Ben Murdoch097c5b22016-05-18 11:27:45 +010024371TEST(ExtrasFunctionSource) {
24372 v8::Isolate* isolate = CcTest::isolate();
24373 v8::HandleScope handle_scope(isolate);
24374 LocalContext env;
24375
24376 v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
24377
24378 // Functions defined in extras do not expose source code.
24379 auto func = binding->Get(env.local(), v8_str("testFunctionToString"))
24380 .ToLocalChecked()
24381 .As<v8::Function>();
24382 auto undefined = v8::Undefined(isolate);
24383 auto result = func->Call(env.local(), undefined, 0, {})
24384 .ToLocalChecked()
24385 .As<v8::String>();
24386 CHECK(result->StrictEquals(v8_str("function foo() { [native code] }")));
24387
24388 // Functions defined in extras do not show up in the stack trace.
24389 auto wrapper = binding->Get(env.local(), v8_str("testStackTrace"))
24390 .ToLocalChecked()
24391 .As<v8::Function>();
24392 CHECK(env->Global()->Set(env.local(), v8_str("wrapper"), wrapper).FromJust());
24393 ExpectString(
24394 "function f(x) { return wrapper(x) }"
24395 "function g() { return new Error().stack; }"
24396 "f(g)",
24397 "Error\n"
24398 " at g (<anonymous>:1:58)\n"
24399 " at f (<anonymous>:1:24)\n"
24400 " at <anonymous>:1:78");
24401}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024402
24403TEST(ExtrasBindingObject) {
24404 v8::Isolate* isolate = CcTest::isolate();
24405 v8::HandleScope handle_scope(isolate);
24406 LocalContext env;
24407
24408 // standalone.gypi ensures we include the test-extra.js file, which should
24409 // export the tested functions.
24410 v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
24411
24412 auto func = binding->Get(env.local(), v8_str("testExtraShouldReturnFive"))
24413 .ToLocalChecked()
24414 .As<v8::Function>();
24415 auto undefined = v8::Undefined(isolate);
24416 auto result = func->Call(env.local(), undefined, 0, {})
24417 .ToLocalChecked()
24418 .As<v8::Number>();
24419 CHECK_EQ(5, result->Int32Value(env.local()).FromJust());
24420
24421 v8::Local<v8::FunctionTemplate> runtimeFunction =
24422 v8::FunctionTemplate::New(isolate, ExtrasBindingTestRuntimeFunction);
24423 binding->Set(env.local(), v8_str("runtime"),
24424 runtimeFunction->GetFunction(env.local()).ToLocalChecked())
24425 .FromJust();
24426 func = binding->Get(env.local(), v8_str("testExtraShouldCallToRuntime"))
24427 .ToLocalChecked()
24428 .As<v8::Function>();
24429 result = func->Call(env.local(), undefined, 0, {})
24430 .ToLocalChecked()
24431 .As<v8::Number>();
24432 CHECK_EQ(7, result->Int32Value(env.local()).FromJust());
24433}
24434
24435
24436TEST(ExperimentalExtras) {
24437 i::FLAG_experimental_extras = true;
24438
24439 v8::Isolate* isolate = CcTest::isolate();
24440 v8::HandleScope handle_scope(isolate);
24441 LocalContext env;
24442
24443 // standalone.gypi ensures we include the test-experimental-extra.js file,
24444 // which should export the tested functions.
24445 v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
24446
24447 auto func =
24448 binding->Get(env.local(), v8_str("testExperimentalExtraShouldReturnTen"))
24449 .ToLocalChecked()
24450 .As<v8::Function>();
24451 auto undefined = v8::Undefined(isolate);
24452 auto result = func->Call(env.local(), undefined, 0, {})
24453 .ToLocalChecked()
24454 .As<v8::Number>();
24455 CHECK_EQ(10, result->Int32Value(env.local()).FromJust());
24456
24457 v8::Local<v8::FunctionTemplate> runtimeFunction =
24458 v8::FunctionTemplate::New(isolate, ExtrasBindingTestRuntimeFunction);
24459 binding->Set(env.local(), v8_str("runtime"),
24460 runtimeFunction->GetFunction(env.local()).ToLocalChecked())
24461 .FromJust();
24462 func = binding->Get(env.local(),
24463 v8_str("testExperimentalExtraShouldCallToRuntime"))
24464 .ToLocalChecked()
24465 .As<v8::Function>();
24466 result = func->Call(env.local(), undefined, 0, {})
24467 .ToLocalChecked()
24468 .As<v8::Number>();
24469 CHECK_EQ(7, result->Int32Value(env.local()).FromJust());
24470}
24471
24472
24473TEST(ExtrasUtilsObject) {
24474 LocalContext context;
24475 v8::Isolate* isolate = context->GetIsolate();
24476 v8::HandleScope handle_scope(isolate);
24477
24478 LocalContext env;
24479 v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
24480
24481 auto func = binding->Get(env.local(), v8_str("testExtraCanUseUtils"))
24482 .ToLocalChecked()
24483 .As<v8::Function>();
24484 auto undefined = v8::Undefined(isolate);
24485 auto result = func->Call(env.local(), undefined, 0, {})
24486 .ToLocalChecked()
24487 .As<v8::Object>();
24488
24489 auto private_symbol = result->Get(env.local(), v8_str("privateSymbol"))
24490 .ToLocalChecked()
24491 .As<v8::Symbol>();
24492 i::Handle<i::Symbol> ips = v8::Utils::OpenHandle(*private_symbol);
24493 CHECK_EQ(true, ips->IsPrivate());
24494
24495 CompileRun("var result = 0; function store(x) { result = x; }");
24496 auto store = CompileRun("store").As<v8::Function>();
24497
24498 auto fulfilled_promise = result->Get(env.local(), v8_str("fulfilledPromise"))
24499 .ToLocalChecked()
24500 .As<v8::Promise>();
24501 fulfilled_promise->Then(env.local(), store).ToLocalChecked();
24502 isolate->RunMicrotasks();
24503 CHECK_EQ(1, CompileRun("result")->Int32Value(env.local()).FromJust());
24504
24505 auto fulfilled_promise_2 =
24506 result->Get(env.local(), v8_str("fulfilledPromise2"))
24507 .ToLocalChecked()
24508 .As<v8::Promise>();
24509 fulfilled_promise_2->Then(env.local(), store).ToLocalChecked();
24510 isolate->RunMicrotasks();
24511 CHECK_EQ(2, CompileRun("result")->Int32Value(env.local()).FromJust());
24512
24513 auto rejected_promise = result->Get(env.local(), v8_str("rejectedPromise"))
24514 .ToLocalChecked()
24515 .As<v8::Promise>();
24516 rejected_promise->Catch(env.local(), store).ToLocalChecked();
24517 isolate->RunMicrotasks();
24518 CHECK_EQ(3, CompileRun("result")->Int32Value(env.local()).FromJust());
24519}
24520
24521
24522TEST(Map) {
24523 v8::Isolate* isolate = CcTest::isolate();
24524 v8::HandleScope handle_scope(isolate);
24525 LocalContext env;
24526
24527 v8::Local<v8::Map> map = v8::Map::New(isolate);
24528 CHECK(map->IsObject());
24529 CHECK(map->IsMap());
24530 CHECK(map->GetPrototype()->StrictEquals(CompileRun("Map.prototype")));
24531 CHECK_EQ(0U, map->Size());
24532
24533 v8::Local<v8::Value> val = CompileRun("new Map([[1, 2], [3, 4]])");
24534 CHECK(val->IsMap());
24535 map = v8::Local<v8::Map>::Cast(val);
24536 CHECK_EQ(2U, map->Size());
24537
24538 v8::Local<v8::Array> contents = map->AsArray();
24539 CHECK_EQ(4U, contents->Length());
24540 CHECK_EQ(
24541 1,
24542 contents->Get(env.local(), 0).ToLocalChecked().As<v8::Int32>()->Value());
24543 CHECK_EQ(
24544 2,
24545 contents->Get(env.local(), 1).ToLocalChecked().As<v8::Int32>()->Value());
24546 CHECK_EQ(
24547 3,
24548 contents->Get(env.local(), 2).ToLocalChecked().As<v8::Int32>()->Value());
24549 CHECK_EQ(
24550 4,
24551 contents->Get(env.local(), 3).ToLocalChecked().As<v8::Int32>()->Value());
24552
24553 CHECK_EQ(2U, map->Size());
24554
24555 CHECK(map->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
24556 CHECK(map->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
24557
24558 CHECK(!map->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
24559 CHECK(!map->Has(env.local(), map).FromJust());
24560
24561 CHECK_EQ(2, map->Get(env.local(), v8::Integer::New(isolate, 1))
24562 .ToLocalChecked()
24563 ->Int32Value(env.local())
24564 .FromJust());
24565 CHECK_EQ(4, map->Get(env.local(), v8::Integer::New(isolate, 3))
24566 .ToLocalChecked()
24567 ->Int32Value(env.local())
24568 .FromJust());
24569
24570 CHECK(map->Get(env.local(), v8::Integer::New(isolate, 42))
24571 .ToLocalChecked()
24572 ->IsUndefined());
24573
24574 CHECK(!map->Set(env.local(), map, map).IsEmpty());
24575 CHECK_EQ(3U, map->Size());
24576 CHECK(map->Has(env.local(), map).FromJust());
24577
24578 CHECK(map->Delete(env.local(), map).FromJust());
24579 CHECK_EQ(2U, map->Size());
24580 CHECK(!map->Has(env.local(), map).FromJust());
24581 CHECK(!map->Delete(env.local(), map).FromJust());
24582
24583 map->Clear();
24584 CHECK_EQ(0U, map->Size());
24585}
24586
24587
24588TEST(Set) {
24589 v8::Isolate* isolate = CcTest::isolate();
24590 v8::HandleScope handle_scope(isolate);
24591 LocalContext env;
24592
24593 v8::Local<v8::Set> set = v8::Set::New(isolate);
24594 CHECK(set->IsObject());
24595 CHECK(set->IsSet());
24596 CHECK(set->GetPrototype()->StrictEquals(CompileRun("Set.prototype")));
24597 CHECK_EQ(0U, set->Size());
24598
24599 v8::Local<v8::Value> val = CompileRun("new Set([1, 2])");
24600 CHECK(val->IsSet());
24601 set = v8::Local<v8::Set>::Cast(val);
24602 CHECK_EQ(2U, set->Size());
24603
24604 v8::Local<v8::Array> keys = set->AsArray();
24605 CHECK_EQ(2U, keys->Length());
24606 CHECK_EQ(1,
24607 keys->Get(env.local(), 0).ToLocalChecked().As<v8::Int32>()->Value());
24608 CHECK_EQ(2,
24609 keys->Get(env.local(), 1).ToLocalChecked().As<v8::Int32>()->Value());
24610
24611 CHECK_EQ(2U, set->Size());
24612
24613 CHECK(set->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
24614 CHECK(set->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
24615
24616 CHECK(!set->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
24617 CHECK(!set->Has(env.local(), set).FromJust());
24618
24619 CHECK(!set->Add(env.local(), set).IsEmpty());
24620 CHECK_EQ(3U, set->Size());
24621 CHECK(set->Has(env.local(), set).FromJust());
24622
24623 CHECK(set->Delete(env.local(), set).FromJust());
24624 CHECK_EQ(2U, set->Size());
24625 CHECK(!set->Has(env.local(), set).FromJust());
24626 CHECK(!set->Delete(env.local(), set).FromJust());
24627
24628 set->Clear();
24629 CHECK_EQ(0U, set->Size());
24630}
24631
24632
24633TEST(CompatibleReceiverCheckOnCachedICHandler) {
24634 v8::Isolate* isolate = CcTest::isolate();
24635 v8::HandleScope scope(isolate);
24636 v8::Local<v8::FunctionTemplate> parent = FunctionTemplate::New(isolate);
24637 v8::Local<v8::Signature> signature = v8::Signature::New(isolate, parent);
24638 auto returns_42 =
24639 v8::FunctionTemplate::New(isolate, Returns42, Local<Value>(), signature);
24640 parent->PrototypeTemplate()->SetAccessorProperty(v8_str("age"), returns_42);
24641 v8::Local<v8::FunctionTemplate> child = v8::FunctionTemplate::New(isolate);
24642 child->Inherit(parent);
24643 LocalContext env;
24644 CHECK(env->Global()
24645 ->Set(env.local(), v8_str("Child"),
24646 child->GetFunction(env.local()).ToLocalChecked())
24647 .FromJust());
24648
24649 // Make sure there's a compiled stub for "Child.prototype.age" in the cache.
24650 CompileRun(
24651 "var real = new Child();\n"
24652 "for (var i = 0; i < 3; ++i) {\n"
24653 " real.age;\n"
24654 "}\n");
24655
24656 // Check that the cached stub is never used.
24657 ExpectInt32(
24658 "var fake = Object.create(Child.prototype);\n"
24659 "var result = 0;\n"
24660 "function test(d) {\n"
24661 " if (d == 3) return;\n"
24662 " try {\n"
24663 " fake.age;\n"
24664 " result = 1;\n"
24665 " } catch (e) {\n"
24666 " }\n"
24667 " test(d+1);\n"
24668 "}\n"
24669 "test(0);\n"
24670 "result;\n",
24671 0);
24672}
24673
Ben Murdochda12d292016-06-02 14:46:10 +010024674THREADED_TEST(ReceiverConversionForAccessors) {
24675 LocalContext env;
24676 v8::Isolate* isolate = CcTest::isolate();
24677 v8::HandleScope scope(isolate);
24678 Local<v8::FunctionTemplate> acc =
24679 v8::FunctionTemplate::New(isolate, Returns42);
24680 CHECK(env->Global()
24681 ->Set(env.local(), v8_str("acc"),
24682 acc->GetFunction(env.local()).ToLocalChecked())
24683 .FromJust());
24684
24685 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
24686 templ->SetAccessorProperty(v8_str("acc"), acc, acc);
24687 Local<v8::Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
24688
24689 CHECK(env->Global()->Set(env.local(), v8_str("p"), instance).FromJust());
24690 CHECK(CompileRun("(p.acc == 42)")->BooleanValue(env.local()).FromJust());
24691 CHECK(CompileRun("(p.acc = 7) == 7")->BooleanValue(env.local()).FromJust());
24692
24693 CHECK(!CompileRun("Number.prototype.__proto__ = p;"
24694 "var a = 1;")
24695 .IsEmpty());
24696 CHECK(CompileRun("(a.acc == 42)")->BooleanValue(env.local()).FromJust());
24697 CHECK(CompileRun("(a.acc = 7) == 7")->BooleanValue(env.local()).FromJust());
24698
24699 CHECK(!CompileRun("Boolean.prototype.__proto__ = p;"
24700 "var a = true;")
24701 .IsEmpty());
24702 CHECK(CompileRun("(a.acc == 42)")->BooleanValue(env.local()).FromJust());
24703 CHECK(CompileRun("(a.acc = 7) == 7")->BooleanValue(env.local()).FromJust());
24704
24705 CHECK(!CompileRun("String.prototype.__proto__ = p;"
24706 "var a = 'foo';")
24707 .IsEmpty());
24708 CHECK(CompileRun("(a.acc == 42)")->BooleanValue(env.local()).FromJust());
24709 CHECK(CompileRun("(a.acc = 7) == 7")->BooleanValue(env.local()).FromJust());
24710
24711 CHECK(CompileRun("acc.call(1) == 42")->BooleanValue(env.local()).FromJust());
24712 CHECK(CompileRun("acc.call(true)==42")->BooleanValue(env.local()).FromJust());
24713 CHECK(CompileRun("acc.call('aa')==42")->BooleanValue(env.local()).FromJust());
24714 CHECK(
24715 CompileRun("acc.call(null) == 42")->BooleanValue(env.local()).FromJust());
24716 CHECK(CompileRun("acc.call(undefined) == 42")
24717 ->BooleanValue(env.local())
24718 .FromJust());
24719}
24720
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024721class FutexInterruptionThread : public v8::base::Thread {
24722 public:
24723 explicit FutexInterruptionThread(v8::Isolate* isolate)
24724 : Thread(Options("FutexInterruptionThread")), isolate_(isolate) {}
24725
24726 virtual void Run() {
24727 // Wait a bit before terminating.
24728 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
24729 isolate_->TerminateExecution();
24730 }
24731
24732 private:
24733 v8::Isolate* isolate_;
24734};
24735
24736
24737TEST(FutexInterruption) {
24738 i::FLAG_harmony_sharedarraybuffer = true;
24739 v8::Isolate* isolate = CcTest::isolate();
24740 v8::HandleScope scope(isolate);
24741 LocalContext env;
24742
24743 FutexInterruptionThread timeout_thread(isolate);
24744
24745 v8::TryCatch try_catch(CcTest::isolate());
24746 timeout_thread.Start();
24747
24748 CompileRun(
24749 "var ab = new SharedArrayBuffer(4);"
24750 "var i32a = new Int32Array(ab);"
24751 "Atomics.futexWait(i32a, 0, 0);");
24752 CHECK(try_catch.HasTerminated());
24753 timeout_thread.Join();
24754}
24755
24756
24757TEST(EstimatedContextSize) {
24758 v8::Isolate* isolate = CcTest::isolate();
24759 v8::HandleScope scope(isolate);
24760 LocalContext env;
24761 CHECK(50000 < env->EstimatedSize());
24762}
24763
24764
24765static int nb_uncaught_exception_callback_calls = 0;
24766
24767
24768bool NoAbortOnUncaughtException(v8::Isolate* isolate) {
24769 ++nb_uncaught_exception_callback_calls;
24770 return false;
24771}
24772
24773
24774TEST(AbortOnUncaughtExceptionNoAbort) {
24775 v8::Isolate* isolate = CcTest::isolate();
24776 v8::HandleScope handle_scope(isolate);
24777 v8::Local<v8::ObjectTemplate> global_template =
24778 v8::ObjectTemplate::New(isolate);
24779 LocalContext env(NULL, global_template);
24780
24781 i::FLAG_abort_on_uncaught_exception = true;
24782 isolate->SetAbortOnUncaughtExceptionCallback(NoAbortOnUncaughtException);
24783
24784 CompileRun("function boom() { throw new Error(\"boom\") }");
24785
24786 v8::Local<v8::Object> global_object = env->Global();
24787 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
24788 global_object->Get(env.local(), v8_str("boom")).ToLocalChecked());
24789
24790 CHECK(foo->Call(env.local(), global_object, 0, NULL).IsEmpty());
24791
24792 CHECK_EQ(1, nb_uncaught_exception_callback_calls);
24793}
24794
24795
24796TEST(AccessCheckedIsConcatSpreadable) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024797 v8::Isolate* isolate = CcTest::isolate();
24798 HandleScope scope(isolate);
24799 LocalContext env;
24800
24801 // Object with access check
24802 Local<ObjectTemplate> spreadable_template = v8::ObjectTemplate::New(isolate);
24803 spreadable_template->SetAccessCheckCallback(AccessBlocker);
24804 spreadable_template->Set(v8::Symbol::GetIsConcatSpreadable(isolate),
24805 v8::Boolean::New(isolate, true));
24806 Local<Object> object =
24807 spreadable_template->NewInstance(env.local()).ToLocalChecked();
24808
24809 allowed_access = true;
24810 CHECK(env->Global()->Set(env.local(), v8_str("object"), object).FromJust());
24811 object->Set(env.local(), v8_str("length"), v8_num(2)).FromJust();
24812 object->Set(env.local(), 0U, v8_str("a")).FromJust();
24813 object->Set(env.local(), 1U, v8_str("b")).FromJust();
24814
24815 // Access check is allowed, and the object is spread
24816 CompileRun("var result = [].concat(object)");
24817 ExpectTrue("Array.isArray(result)");
24818 ExpectString("result[0]", "a");
24819 ExpectString("result[1]", "b");
24820 ExpectTrue("result.length === 2");
24821 ExpectTrue("object[Symbol.isConcatSpreadable]");
24822
24823 // If access check fails, the value of @@isConcatSpreadable is ignored
24824 allowed_access = false;
24825 CompileRun("var result = [].concat(object)");
24826 ExpectTrue("Array.isArray(result)");
24827 ExpectTrue("result[0] === object");
24828 ExpectTrue("result.length === 1");
24829 ExpectTrue("object[Symbol.isConcatSpreadable] === undefined");
24830}
24831
24832
24833TEST(AccessCheckedToStringTag) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024834 v8::Isolate* isolate = CcTest::isolate();
24835 HandleScope scope(isolate);
24836 LocalContext env;
24837
24838 // Object with access check
24839 Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
24840 object_template->SetAccessCheckCallback(AccessBlocker);
24841 Local<Object> object =
24842 object_template->NewInstance(env.local()).ToLocalChecked();
24843
24844 allowed_access = true;
24845 env->Global()->Set(env.local(), v8_str("object"), object).FromJust();
24846 object->Set(env.local(), v8::Symbol::GetToStringTag(isolate), v8_str("hello"))
24847 .FromJust();
24848
24849 // Access check is allowed, and the toStringTag is read
24850 CompileRun("var result = Object.prototype.toString.call(object)");
24851 ExpectString("result", "[object hello]");
24852 ExpectString("object[Symbol.toStringTag]", "hello");
24853
24854 // ToString through the API should succeed too.
24855 String::Utf8Value result_allowed(
24856 object->ObjectProtoToString(env.local()).ToLocalChecked());
24857 CHECK_EQ(0, strcmp(*result_allowed, "[object hello]"));
24858
24859 // If access check fails, the value of @@toStringTag is ignored
24860 allowed_access = false;
24861 CompileRun("var result = Object.prototype.toString.call(object)");
24862 ExpectString("result", "[object Object]");
24863 ExpectTrue("object[Symbol.toStringTag] === undefined");
24864
24865 // ToString through the API should also fail.
24866 String::Utf8Value result_denied(
24867 object->ObjectProtoToString(env.local()).ToLocalChecked());
24868 CHECK_EQ(0, strcmp(*result_denied, "[object Object]"));
24869}
24870
24871
24872TEST(ObjectTemplateIntrinsics) {
24873 v8::Isolate* isolate = CcTest::isolate();
24874 v8::HandleScope scope(isolate);
24875 LocalContext env;
24876
24877 Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
24878 object_template->SetIntrinsicDataProperty(v8_str("values"),
24879 v8::kArrayProto_values);
24880 Local<Object> object =
24881 object_template->NewInstance(env.local()).ToLocalChecked();
24882
24883 CHECK(env->Global()->Set(env.local(), v8_str("obj1"), object).FromJust());
24884 ExpectString("typeof obj1.values", "function");
24885
24886 auto values = Local<Function>::Cast(
24887 object->Get(env.local(), v8_str("values")).ToLocalChecked());
24888 auto fn = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*values));
24889 auto ctx = v8::Utils::OpenHandle(*env.local());
24890 CHECK_EQ(fn->GetCreationContext(), *ctx);
24891
24892 {
24893 LocalContext env2;
24894 Local<Object> object2 =
24895 object_template->NewInstance(env2.local()).ToLocalChecked();
24896 CHECK(
24897 env2->Global()->Set(env2.local(), v8_str("obj2"), object2).FromJust());
24898 ExpectString("typeof obj2.values", "function");
24899 CHECK_NE(*object->Get(env2.local(), v8_str("values")).ToLocalChecked(),
24900 *object2->Get(env2.local(), v8_str("values")).ToLocalChecked());
24901
24902 auto values2 = Local<Function>::Cast(
24903 object2->Get(env2.local(), v8_str("values")).ToLocalChecked());
24904 auto fn2 = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*values2));
24905 auto ctx2 = v8::Utils::OpenHandle(*env2.local());
24906 CHECK_EQ(fn2->GetCreationContext(), *ctx2);
24907 }
24908}
24909
24910
24911TEST(Proxy) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024912 LocalContext context;
24913 v8::Isolate* isolate = CcTest::isolate();
24914 v8::HandleScope scope(isolate);
24915 v8::Local<v8::Object> target = CompileRun("({})").As<v8::Object>();
24916 v8::Local<v8::Object> handler = CompileRun("({})").As<v8::Object>();
24917
24918 v8::Local<v8::Proxy> proxy =
24919 v8::Proxy::New(context.local(), target, handler).ToLocalChecked();
24920 CHECK(proxy->IsProxy());
24921 CHECK(!target->IsProxy());
24922 CHECK(!proxy->IsRevoked());
24923 CHECK(proxy->GetTarget()->SameValue(target));
24924 CHECK(proxy->GetHandler()->SameValue(handler));
24925
24926 proxy->Revoke();
24927 CHECK(proxy->IsProxy());
24928 CHECK(!target->IsProxy());
24929 CHECK(proxy->IsRevoked());
24930 CHECK(proxy->GetTarget()->SameValue(target));
24931 CHECK(proxy->GetHandler()->IsNull());
24932}
Ben Murdochda12d292016-06-02 14:46:10 +010024933
24934WeakCallCounterAndPersistent<Value>* CreateGarbageWithWeakCallCounter(
24935 v8::Isolate* isolate, WeakCallCounter* counter) {
24936 v8::Locker locker(isolate);
24937 LocalContext env;
24938 HandleScope scope(isolate);
24939 WeakCallCounterAndPersistent<Value>* val =
24940 new WeakCallCounterAndPersistent<Value>(counter);
24941 val->handle.Reset(isolate, Object::New(isolate));
24942 val->handle.SetWeak(val, &WeakPointerCallback,
24943 v8::WeakCallbackType::kParameter);
24944 return val;
24945}
24946
24947class MemoryPressureThread : public v8::base::Thread {
24948 public:
24949 explicit MemoryPressureThread(v8::Isolate* isolate,
24950 v8::MemoryPressureLevel level)
24951 : Thread(Options("MemoryPressureThread")),
24952 isolate_(isolate),
24953 level_(level) {}
24954
24955 virtual void Run() { isolate_->MemoryPressureNotification(level_); }
24956
24957 private:
24958 v8::Isolate* isolate_;
24959 v8::MemoryPressureLevel level_;
24960};
24961
24962TEST(MemoryPressure) {
24963 v8::Isolate* isolate = CcTest::isolate();
24964 WeakCallCounter counter(1234);
24965
24966 // Check that critical memory pressure notification sets GC interrupt.
24967 auto garbage = CreateGarbageWithWeakCallCounter(isolate, &counter);
24968 CHECK(!v8::Locker::IsLocked(isolate));
24969 {
24970 v8::Locker locker(isolate);
24971 v8::HandleScope scope(isolate);
24972 LocalContext env;
24973 MemoryPressureThread memory_pressure_thread(
24974 isolate, v8::MemoryPressureLevel::kCritical);
24975 memory_pressure_thread.Start();
24976 memory_pressure_thread.Join();
24977 // This should trigger GC.
24978 CHECK_EQ(0, counter.NumberOfWeakCalls());
24979 CompileRun("(function noop() { return 0; })()");
24980 CHECK_EQ(1, counter.NumberOfWeakCalls());
24981 }
24982 delete garbage;
24983 // Check that critical memory pressure notification triggers GC.
24984 garbage = CreateGarbageWithWeakCallCounter(isolate, &counter);
24985 {
24986 v8::Locker locker(isolate);
24987 // If isolate is locked, memory pressure notification should trigger GC.
24988 CHECK_EQ(1, counter.NumberOfWeakCalls());
24989 isolate->MemoryPressureNotification(v8::MemoryPressureLevel::kCritical);
24990 CHECK_EQ(2, counter.NumberOfWeakCalls());
24991 }
24992 delete garbage;
24993 // Check that moderate memory pressure notification sets GC into memory
24994 // optimizing mode.
24995 isolate->MemoryPressureNotification(v8::MemoryPressureLevel::kModerate);
24996 CHECK(CcTest::i_isolate()->heap()->ShouldOptimizeForMemoryUsage());
24997 // Check that disabling memory pressure returns GC into normal mode.
24998 isolate->MemoryPressureNotification(v8::MemoryPressureLevel::kNone);
24999 CHECK(!CcTest::i_isolate()->heap()->ShouldOptimizeForMemoryUsage());
25000}
25001
25002TEST(SetIntegrityLevel) {
25003 LocalContext context;
25004 v8::Isolate* isolate = CcTest::isolate();
25005 v8::HandleScope scope(isolate);
25006
25007 v8::Local<v8::Object> obj = v8::Object::New(isolate);
25008 CHECK(context->Global()->Set(context.local(), v8_str("o"), obj).FromJust());
25009
25010 v8::Local<v8::Value> is_frozen = CompileRun("Object.isFrozen(o)");
25011 CHECK(!is_frozen->BooleanValue(context.local()).FromJust());
25012
25013 CHECK(obj->SetIntegrityLevel(context.local(), v8::IntegrityLevel::kFrozen)
25014 .FromJust());
25015
25016 is_frozen = CompileRun("Object.isFrozen(o)");
25017 CHECK(is_frozen->BooleanValue(context.local()).FromJust());
25018}
25019
25020TEST(PrivateForApiIsNumber) {
25021 LocalContext context;
25022 v8::Isolate* isolate = CcTest::isolate();
25023 v8::HandleScope scope(isolate);
25024
25025 // Shouldn't crash.
25026 v8::Private::ForApi(isolate, v8_str("42"));
25027}