blob: b78d450fcb4539b033a966e28c543b4dd5263d41 [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 Murdochb8a8cc12014-11-26 15:28:44 +00001892 v8::Isolate* isolate = CcTest::isolate();
1893 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001894 Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
1895 v8::Local<v8::String> class_name = v8_str("the_class_name");
1896 fun->SetClassName(class_name);
1897 Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate, fun);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001898 templ1->Set(isolate, "x", v8_num(10));
1899 templ1->Set(isolate, "y", v8_num(13));
Steve Blocka7e24c12009-10-30 11:49:00 +00001900 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001901 Local<v8::Object> instance1 =
1902 templ1->NewInstance(env.local()).ToLocalChecked();
1903 CHECK(class_name->StrictEquals(instance1->GetConstructorName()));
1904 CHECK(env->Global()->Set(env.local(), v8_str("p"), instance1).FromJust());
1905 CHECK(v8_compile("(p.x == 10)")
1906 ->Run(env.local())
1907 .ToLocalChecked()
1908 ->BooleanValue(env.local())
1909 .FromJust());
1910 CHECK(v8_compile("(p.y == 13)")
1911 ->Run(env.local())
1912 .ToLocalChecked()
1913 ->BooleanValue(env.local())
1914 .FromJust());
1915 Local<v8::FunctionTemplate> fun2 = v8::FunctionTemplate::New(isolate);
1916 fun2->PrototypeTemplate()->Set(isolate, "nirk", v8_num(123));
1917 Local<ObjectTemplate> templ2 = fun2->InstanceTemplate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001918 templ2->Set(isolate, "a", v8_num(12));
1919 templ2->Set(isolate, "b", templ1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001920 Local<v8::Object> instance2 =
1921 templ2->NewInstance(env.local()).ToLocalChecked();
1922 CHECK(env->Global()->Set(env.local(), v8_str("q"), instance2).FromJust());
1923 CHECK(v8_compile("(q.nirk == 123)")
1924 ->Run(env.local())
1925 .ToLocalChecked()
1926 ->BooleanValue(env.local())
1927 .FromJust());
1928 CHECK(v8_compile("(q.a == 12)")
1929 ->Run(env.local())
1930 .ToLocalChecked()
1931 ->BooleanValue(env.local())
1932 .FromJust());
1933 CHECK(v8_compile("(q.b.x == 10)")
1934 ->Run(env.local())
1935 .ToLocalChecked()
1936 ->BooleanValue(env.local())
1937 .FromJust());
1938 CHECK(v8_compile("(q.b.y == 13)")
1939 ->Run(env.local())
1940 .ToLocalChecked()
1941 ->BooleanValue(env.local())
1942 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001943}
1944
1945
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001946static void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001947 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001948 args.GetReturnValue().Set(v8_num(17.2));
Steve Blocka7e24c12009-10-30 11:49:00 +00001949}
1950
1951
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001952static void GetKnurd(Local<String> property,
1953 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001954 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001955 info.GetReturnValue().Set(v8_num(15.2));
Steve Blocka7e24c12009-10-30 11:49:00 +00001956}
1957
1958
1959THREADED_TEST(DescriptorInheritance) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001960 v8::Isolate* isolate = CcTest::isolate();
1961 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001962 v8::Local<v8::FunctionTemplate> super = v8::FunctionTemplate::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001963 super->PrototypeTemplate()->Set(isolate, "flabby",
1964 v8::FunctionTemplate::New(isolate,
1965 GetFlabby));
1966 super->PrototypeTemplate()->Set(isolate, "PI", v8_num(3.14));
Steve Blocka7e24c12009-10-30 11:49:00 +00001967
1968 super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
1969
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001970 v8::Local<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001971 base1->Inherit(super);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001972 base1->PrototypeTemplate()->Set(isolate, "v1", v8_num(20.1));
Steve Blocka7e24c12009-10-30 11:49:00 +00001973
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001974 v8::Local<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001975 base2->Inherit(super);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001976 base2->PrototypeTemplate()->Set(isolate, "v2", v8_num(10.1));
Steve Blocka7e24c12009-10-30 11:49:00 +00001977
1978 LocalContext env;
1979
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001980 CHECK(env->Global()
1981 ->Set(env.local(), v8_str("s"),
1982 super->GetFunction(env.local()).ToLocalChecked())
1983 .FromJust());
1984 CHECK(env->Global()
1985 ->Set(env.local(), v8_str("base1"),
1986 base1->GetFunction(env.local()).ToLocalChecked())
1987 .FromJust());
1988 CHECK(env->Global()
1989 ->Set(env.local(), v8_str("base2"),
1990 base2->GetFunction(env.local()).ToLocalChecked())
1991 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001992
1993 // Checks right __proto__ chain.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001994 CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")
1995 ->BooleanValue(env.local())
1996 .FromJust());
1997 CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")
1998 ->BooleanValue(env.local())
1999 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002000
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002001 CHECK(v8_compile("s.prototype.PI == 3.14")
2002 ->Run(env.local())
2003 .ToLocalChecked()
2004 ->BooleanValue(env.local())
2005 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002006
2007 // Instance accessor should not be visible on function object or its prototype
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002008 CHECK(
2009 CompileRun("s.knurd == undefined")->BooleanValue(env.local()).FromJust());
2010 CHECK(CompileRun("s.prototype.knurd == undefined")
2011 ->BooleanValue(env.local())
2012 .FromJust());
2013 CHECK(CompileRun("base1.prototype.knurd == undefined")
2014 ->BooleanValue(env.local())
2015 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002016
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002017 CHECK(env->Global()
2018 ->Set(env.local(), v8_str("obj"), base1->GetFunction(env.local())
2019 .ToLocalChecked()
2020 ->NewInstance(env.local())
2021 .ToLocalChecked())
2022 .FromJust());
2023 CHECK_EQ(17.2, v8_compile("obj.flabby()")
2024 ->Run(env.local())
2025 .ToLocalChecked()
2026 ->NumberValue(env.local())
2027 .FromJust());
2028 CHECK(v8_compile("'flabby' in obj")
2029 ->Run(env.local())
2030 .ToLocalChecked()
2031 ->BooleanValue(env.local())
2032 .FromJust());
2033 CHECK_EQ(15.2, v8_compile("obj.knurd")
2034 ->Run(env.local())
2035 .ToLocalChecked()
2036 ->NumberValue(env.local())
2037 .FromJust());
2038 CHECK(v8_compile("'knurd' in obj")
2039 ->Run(env.local())
2040 .ToLocalChecked()
2041 ->BooleanValue(env.local())
2042 .FromJust());
2043 CHECK_EQ(20.1, v8_compile("obj.v1")
2044 ->Run(env.local())
2045 .ToLocalChecked()
2046 ->NumberValue(env.local())
2047 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002048
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002049 CHECK(env->Global()
2050 ->Set(env.local(), v8_str("obj2"), base2->GetFunction(env.local())
2051 .ToLocalChecked()
2052 ->NewInstance(env.local())
2053 .ToLocalChecked())
2054 .FromJust());
2055 CHECK_EQ(17.2, v8_compile("obj2.flabby()")
2056 ->Run(env.local())
2057 .ToLocalChecked()
2058 ->NumberValue(env.local())
2059 .FromJust());
2060 CHECK(v8_compile("'flabby' in obj2")
2061 ->Run(env.local())
2062 .ToLocalChecked()
2063 ->BooleanValue(env.local())
2064 .FromJust());
2065 CHECK_EQ(15.2, v8_compile("obj2.knurd")
2066 ->Run(env.local())
2067 .ToLocalChecked()
2068 ->NumberValue(env.local())
2069 .FromJust());
2070 CHECK(v8_compile("'knurd' in obj2")
2071 ->Run(env.local())
2072 .ToLocalChecked()
2073 ->BooleanValue(env.local())
2074 .FromJust());
2075 CHECK_EQ(10.1, v8_compile("obj2.v2")
2076 ->Run(env.local())
2077 .ToLocalChecked()
2078 ->NumberValue(env.local())
2079 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002080
2081 // base1 and base2 cannot cross reference to each's prototype
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002082 CHECK(v8_compile("obj.v2")->Run(env.local()).ToLocalChecked()->IsUndefined());
2083 CHECK(
2084 v8_compile("obj2.v1")->Run(env.local()).ToLocalChecked()->IsUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +00002085}
2086
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002087
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002088// Helper functions for Interceptor/Accessor interaction tests
2089
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002090void SimpleAccessorGetter(Local<String> name,
2091 const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002092 Local<Object> self = Local<Object>::Cast(info.This());
2093 info.GetReturnValue().Set(self->Get(info.GetIsolate()->GetCurrentContext(),
2094 String::Concat(v8_str("accessor_"), name))
2095 .ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002096}
2097
2098void SimpleAccessorSetter(Local<String> name, Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002099 const v8::PropertyCallbackInfo<void>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002100 Local<Object> self = Local<Object>::Cast(info.This());
2101 CHECK(self->Set(info.GetIsolate()->GetCurrentContext(),
2102 String::Concat(v8_str("accessor_"), name), value)
2103 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002104}
2105
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002106void SymbolAccessorGetter(Local<Name> name,
2107 const v8::PropertyCallbackInfo<v8::Value>& info) {
2108 CHECK(name->IsSymbol());
2109 Local<Symbol> sym = Local<Symbol>::Cast(name);
2110 if (sym->Name()->IsUndefined())
2111 return;
2112 SimpleAccessorGetter(Local<String>::Cast(sym->Name()), info);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002113}
2114
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002115void SymbolAccessorSetter(Local<Name> name, Local<Value> value,
2116 const v8::PropertyCallbackInfo<void>& info) {
2117 CHECK(name->IsSymbol());
2118 Local<Symbol> sym = Local<Symbol>::Cast(name);
2119 if (sym->Name()->IsUndefined())
2120 return;
2121 SimpleAccessorSetter(Local<String>::Cast(sym->Name()), value, info);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002122}
2123
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002124void SymbolAccessorGetterReturnsDefault(
2125 Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
2126 CHECK(name->IsSymbol());
2127 Local<Symbol> sym = Local<Symbol>::Cast(name);
2128 if (sym->Name()->IsUndefined()) return;
2129 info.GetReturnValue().Set(info.Data());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002130}
2131
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002132static void ThrowingSymbolAccessorGetter(
2133 Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
2134 info.GetReturnValue().Set(info.GetIsolate()->ThrowException(name));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002135}
2136
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002137
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002138THREADED_TEST(ExecutableAccessorIsPreservedOnAttributeChange) {
2139 v8::Isolate* isolate = CcTest::isolate();
2140 v8::HandleScope scope(isolate);
2141 LocalContext env;
2142 v8::Local<v8::Value> res = CompileRun("var a = []; a;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002143 i::Handle<i::JSReceiver> a(v8::Utils::OpenHandle(v8::Object::Cast(*res)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002144 CHECK(a->map()->instance_descriptors()->IsFixedArray());
2145 CHECK_GT(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
2146 CompileRun("Object.defineProperty(a, 'length', { writable: false });");
2147 CHECK_EQ(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
2148 // But we should still have an ExecutableAccessorInfo.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002149 i::Handle<i::String> name(v8::Utils::OpenHandle(*v8_str("length")));
2150 i::LookupIterator it(a, name, i::LookupIterator::OWN_SKIP_INTERCEPTOR);
2151 CHECK_EQ(i::LookupIterator::ACCESSOR, it.state());
2152 CHECK(it.GetAccessors()->IsExecutableAccessorInfo());
2153}
2154
2155
Steve Blocka7e24c12009-10-30 11:49:00 +00002156THREADED_TEST(UndefinedIsNotEnumerable) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002157 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002158 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002159 v8::Local<Value> result = CompileRun("this.propertyIsEnumerable(undefined)");
Steve Blocka7e24c12009-10-30 11:49:00 +00002160 CHECK(result->IsFalse());
2161}
2162
2163
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002164v8::Local<Script> call_recursively_script;
2165static const int kTargetRecursionDepth = 150; // near maximum
Steve Blocka7e24c12009-10-30 11:49:00 +00002166
2167
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002168static void CallScriptRecursivelyCall(
2169 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002170 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002171 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
2172 int depth = args.This()
2173 ->Get(context, v8_str("depth"))
2174 .ToLocalChecked()
2175 ->Int32Value(context)
2176 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002177 if (depth == kTargetRecursionDepth) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002178 CHECK(args.This()
2179 ->Set(context, v8_str("depth"),
2180 v8::Integer::New(args.GetIsolate(), depth + 1))
2181 .FromJust());
2182 args.GetReturnValue().Set(
2183 call_recursively_script->Run(context).ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00002184}
2185
2186
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002187static void CallFunctionRecursivelyCall(
2188 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002189 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002190 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
2191 int depth = args.This()
2192 ->Get(context, v8_str("depth"))
2193 .ToLocalChecked()
2194 ->Int32Value(context)
2195 .FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00002196 if (depth == kTargetRecursionDepth) {
2197 printf("[depth = %d]\n", depth);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002198 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002199 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002200 CHECK(args.This()
2201 ->Set(context, v8_str("depth"),
2202 v8::Integer::New(args.GetIsolate(), depth + 1))
2203 .FromJust());
2204 v8::Local<Value> function =
2205 args.This()
2206 ->Get(context, v8_str("callFunctionRecursively"))
2207 .ToLocalChecked();
2208 args.GetReturnValue().Set(function.As<Function>()
2209 ->Call(context, args.This(), 0, NULL)
2210 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00002211}
2212
2213
2214THREADED_TEST(DeepCrossLanguageRecursion) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002215 v8::Isolate* isolate = CcTest::isolate();
2216 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002217 v8::Local<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002218 global->Set(v8_str("callScriptRecursively"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002219 v8::FunctionTemplate::New(isolate, CallScriptRecursivelyCall));
Steve Blocka7e24c12009-10-30 11:49:00 +00002220 global->Set(v8_str("callFunctionRecursively"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002221 v8::FunctionTemplate::New(isolate, CallFunctionRecursivelyCall));
Steve Blocka7e24c12009-10-30 11:49:00 +00002222 LocalContext env(NULL, global);
2223
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002224 CHECK(env->Global()
2225 ->Set(env.local(), v8_str("depth"), v8::Integer::New(isolate, 0))
2226 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002227 call_recursively_script = v8_compile("callScriptRecursively()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002228 call_recursively_script->Run(env.local()).ToLocalChecked();
2229 call_recursively_script = v8::Local<Script>();
Steve Blocka7e24c12009-10-30 11:49:00 +00002230
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002231 CHECK(env->Global()
2232 ->Set(env.local(), v8_str("depth"), v8::Integer::New(isolate, 0))
2233 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002234 CompileRun("callFunctionRecursively()");
Steve Blocka7e24c12009-10-30 11:49:00 +00002235}
2236
2237
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002238static void ThrowingPropertyHandlerGet(
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002239 Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>& info) {
2240 // Since this interceptor is used on "with" objects, the runtime will look up
2241 // @@unscopables. Punt.
2242 if (key->IsSymbol()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002243 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002244 info.GetReturnValue().Set(info.GetIsolate()->ThrowException(key));
Steve Blocka7e24c12009-10-30 11:49:00 +00002245}
2246
2247
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002248static void ThrowingPropertyHandlerSet(
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002249 Local<Name> key, Local<Value>,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002250 const v8::PropertyCallbackInfo<v8::Value>& info) {
2251 info.GetIsolate()->ThrowException(key);
2252 info.GetReturnValue().SetUndefined(); // not the same as empty handle
Steve Blocka7e24c12009-10-30 11:49:00 +00002253}
2254
2255
2256THREADED_TEST(CallbackExceptionRegression) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002257 v8::Isolate* isolate = CcTest::isolate();
2258 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002259 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002260 obj->SetHandler(v8::NamedPropertyHandlerConfiguration(
2261 ThrowingPropertyHandlerGet, ThrowingPropertyHandlerSet));
Steve Blocka7e24c12009-10-30 11:49:00 +00002262 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002263 CHECK(env->Global()
2264 ->Set(env.local(), v8_str("obj"),
2265 obj->NewInstance(env.local()).ToLocalChecked())
2266 .FromJust());
2267 v8::Local<Value> otto =
2268 CompileRun("try { with (obj) { otto; } } catch (e) { e; }");
2269 CHECK(v8_str("otto")->Equals(env.local(), otto).FromJust());
2270 v8::Local<Value> netto =
2271 CompileRun("try { with (obj) { netto = 4; } } catch (e) { e; }");
2272 CHECK(v8_str("netto")->Equals(env.local(), netto).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002273}
2274
2275
Steve Blocka7e24c12009-10-30 11:49:00 +00002276THREADED_TEST(FunctionPrototype) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002277 v8::Isolate* isolate = CcTest::isolate();
2278 v8::HandleScope scope(isolate);
2279 Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002280 Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
2281 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002282 CHECK(env->Global()
2283 ->Set(env.local(), v8_str("Foo"),
2284 Foo->GetFunction(env.local()).ToLocalChecked())
2285 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002286 Local<Script> script = v8_compile("Foo.prototype.plak");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002287 CHECK_EQ(v8_run_int32value(script), 321);
Steve Blocka7e24c12009-10-30 11:49:00 +00002288}
2289
2290
2291THREADED_TEST(InternalFields) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002292 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002293 v8::Isolate* isolate = env->GetIsolate();
2294 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002295
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002296 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002297 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2298 instance_templ->SetInternalFieldCount(1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002299 Local<v8::Object> obj = templ->GetFunction(env.local())
2300 .ToLocalChecked()
2301 ->NewInstance(env.local())
2302 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00002303 CHECK_EQ(1, obj->InternalFieldCount());
2304 CHECK(obj->GetInternalField(0)->IsUndefined());
2305 obj->SetInternalField(0, v8_num(17));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002306 CHECK_EQ(17, obj->GetInternalField(0)->Int32Value(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002307}
2308
2309
Steve Block6ded16b2010-05-10 14:33:55 +01002310THREADED_TEST(GlobalObjectInternalFields) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002311 v8::Isolate* isolate = CcTest::isolate();
2312 v8::HandleScope scope(isolate);
2313 Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
Steve Block6ded16b2010-05-10 14:33:55 +01002314 global_template->SetInternalFieldCount(1);
2315 LocalContext env(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002316 v8::Local<v8::Object> global_proxy = env->Global();
2317 v8::Local<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
Steve Block6ded16b2010-05-10 14:33:55 +01002318 CHECK_EQ(1, global->InternalFieldCount());
2319 CHECK(global->GetInternalField(0)->IsUndefined());
2320 global->SetInternalField(0, v8_num(17));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002321 CHECK_EQ(17, global->GetInternalField(0)->Int32Value(env.local()).FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +01002322}
2323
2324
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002325THREADED_TEST(GlobalObjectHasRealIndexedProperty) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002326 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002327 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00002328
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002329 v8::Local<v8::Object> global = env->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002330 CHECK(global->Set(env.local(), 0, v8_str("value")).FromJust());
2331 CHECK(global->HasRealIndexedProperty(env.local(), 0).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002332}
2333
2334
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002335static void CheckAlignedPointerInInternalField(Local<v8::Object> obj,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002336 void* value) {
2337 CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
2338 obj->SetAlignedPointerInInternalField(0, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002339 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002340 CHECK_EQ(value, obj->GetAlignedPointerFromInternalField(0));
2341}
Steve Block3ce2e202009-11-05 08:53:23 +00002342
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002343
2344THREADED_TEST(InternalFieldsAlignedPointers) {
2345 LocalContext env;
2346 v8::Isolate* isolate = env->GetIsolate();
2347 v8::HandleScope scope(isolate);
2348
2349 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Steve Block3ce2e202009-11-05 08:53:23 +00002350 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2351 instance_templ->SetInternalFieldCount(1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002352 Local<v8::Object> obj = templ->GetFunction(env.local())
2353 .ToLocalChecked()
2354 ->NewInstance(env.local())
2355 .ToLocalChecked();
Steve Block3ce2e202009-11-05 08:53:23 +00002356 CHECK_EQ(1, obj->InternalFieldCount());
Steve Block3ce2e202009-11-05 08:53:23 +00002357
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002358 CheckAlignedPointerInInternalField(obj, NULL);
Steve Block3ce2e202009-11-05 08:53:23 +00002359
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002360 int* heap_allocated = new int[100];
2361 CheckAlignedPointerInInternalField(obj, heap_allocated);
2362 delete[] heap_allocated;
Steve Block3ce2e202009-11-05 08:53:23 +00002363
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002364 int stack_allocated[100];
2365 CheckAlignedPointerInInternalField(obj, stack_allocated);
Steve Block3ce2e202009-11-05 08:53:23 +00002366
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002367 void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2368 CheckAlignedPointerInInternalField(obj, huge);
Steve Block3ce2e202009-11-05 08:53:23 +00002369
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002370 v8::Global<v8::Object> persistent(isolate, obj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002371 CHECK_EQ(1, Object::InternalFieldCount(persistent));
2372 CHECK_EQ(huge, Object::GetAlignedPointerFromInternalField(persistent, 0));
2373}
Steve Block3ce2e202009-11-05 08:53:23 +00002374
Steve Block3ce2e202009-11-05 08:53:23 +00002375
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002376static void CheckAlignedPointerInEmbedderData(LocalContext* env, int index,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002377 void* value) {
2378 CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
2379 (*env)->SetAlignedPointerInEmbedderData(index, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002380 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002381 CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
2382}
2383
2384
2385static void* AlignedTestPointer(int i) {
2386 return reinterpret_cast<void*>(i * 1234);
2387}
2388
2389
2390THREADED_TEST(EmbedderDataAlignedPointers) {
2391 LocalContext env;
2392 v8::HandleScope scope(env->GetIsolate());
2393
2394 CheckAlignedPointerInEmbedderData(&env, 0, NULL);
2395
2396 int* heap_allocated = new int[100];
2397 CheckAlignedPointerInEmbedderData(&env, 1, heap_allocated);
2398 delete[] heap_allocated;
2399
2400 int stack_allocated[100];
2401 CheckAlignedPointerInEmbedderData(&env, 2, stack_allocated);
2402
2403 void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2404 CheckAlignedPointerInEmbedderData(&env, 3, huge);
2405
2406 // Test growing of the embedder data's backing store.
2407 for (int i = 0; i < 100; i++) {
2408 env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
2409 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002410 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002411 for (int i = 0; i < 100; i++) {
2412 CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
2413 }
2414}
2415
2416
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002417static void CheckEmbedderData(LocalContext* env, int index,
2418 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002419 (*env)->SetEmbedderData(index, data);
2420 CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
2421}
2422
2423
2424THREADED_TEST(EmbedderData) {
2425 LocalContext env;
2426 v8::Isolate* isolate = env->GetIsolate();
2427 v8::HandleScope scope(isolate);
2428
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002429 CheckEmbedderData(&env, 3, v8_str("The quick brown fox jumps"));
2430 CheckEmbedderData(&env, 2, v8_str("over the lazy dog."));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002431 CheckEmbedderData(&env, 1, v8::Number::New(isolate, 1.2345));
2432 CheckEmbedderData(&env, 0, v8::Boolean::New(isolate, true));
Steve Block3ce2e202009-11-05 08:53:23 +00002433}
2434
2435
Steve Blocka7e24c12009-10-30 11:49:00 +00002436THREADED_TEST(IdentityHash) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002437 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002438 v8::Isolate* isolate = env->GetIsolate();
2439 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002440
2441 // Ensure that the test starts with an fresh heap to test whether the hash
2442 // code is based on the address.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002443 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002444 Local<v8::Object> obj = v8::Object::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002445 int hash = obj->GetIdentityHash();
2446 int hash1 = obj->GetIdentityHash();
2447 CHECK_EQ(hash, hash1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002448 int hash2 = v8::Object::New(isolate)->GetIdentityHash();
Steve Blocka7e24c12009-10-30 11:49:00 +00002449 // Since the identity hash is essentially a random number two consecutive
2450 // objects should not be assigned the same hash code. If the test below fails
2451 // the random number generator should be evaluated.
2452 CHECK_NE(hash, hash2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002453 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002454 int hash3 = v8::Object::New(isolate)->GetIdentityHash();
Steve Blocka7e24c12009-10-30 11:49:00 +00002455 // Make sure that the identity hash is not based on the initial address of
2456 // the object alone. If the test below fails the random number generator
2457 // should be evaluated.
2458 CHECK_NE(hash, hash3);
2459 int hash4 = obj->GetIdentityHash();
2460 CHECK_EQ(hash, hash4);
Steve Block1e0659c2011-05-24 12:43:12 +01002461
2462 // Check identity hashes behaviour in the presence of JS accessors.
2463 // Put a getter for 'v8::IdentityHash' on the Object's prototype:
2464 {
2465 CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002466 Local<v8::Object> o1 = v8::Object::New(isolate);
2467 Local<v8::Object> o2 = v8::Object::New(isolate);
Steve Block1e0659c2011-05-24 12:43:12 +01002468 CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2469 }
2470 {
2471 CompileRun(
2472 "function cnst() { return 42; };\n"
2473 "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002474 Local<v8::Object> o1 = v8::Object::New(isolate);
2475 Local<v8::Object> o2 = v8::Object::New(isolate);
Steve Block1e0659c2011-05-24 12:43:12 +01002476 CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2477 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002478}
2479
2480
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002481void GlobalProxyIdentityHash(bool set_in_js) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002482 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002483 v8::Isolate* isolate = env->GetIsolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002484 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002485 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002486 Local<Object> global_proxy = env->Global();
2487 i::Handle<i::Object> i_global_proxy = v8::Utils::OpenHandle(*global_proxy);
2488 CHECK(env->Global()
2489 ->Set(env.local(), v8_str("global"), global_proxy)
2490 .FromJust());
2491 i::Handle<i::Object> original_hash;
2492 if (set_in_js) {
2493 CompileRun("var m = new Set(); m.add(global);");
2494 original_hash = i::Handle<i::Object>(i_global_proxy->GetHash(), i_isolate);
2495 } else {
2496 original_hash = i::Handle<i::Object>(
2497 i::Object::GetOrCreateHash(i_isolate, i_global_proxy));
2498 }
2499 CHECK(original_hash->IsSmi());
2500 int32_t hash1 = i::Handle<i::Smi>::cast(original_hash)->value();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002501 // Hash should be retained after being detached.
2502 env->DetachGlobal();
2503 int hash2 = global_proxy->GetIdentityHash();
2504 CHECK_EQ(hash1, hash2);
2505 {
2506 // Re-attach global proxy to a new context, hash should stay the same.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002507 LocalContext env2(NULL, Local<ObjectTemplate>(), global_proxy);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002508 int hash3 = global_proxy->GetIdentityHash();
2509 CHECK_EQ(hash1, hash3);
2510 }
2511}
Steve Blocka7e24c12009-10-30 11:49:00 +00002512
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002513
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002514THREADED_TEST(GlobalProxyIdentityHash) {
2515 GlobalProxyIdentityHash(true);
2516 GlobalProxyIdentityHash(false);
2517}
2518
2519
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002520TEST(SymbolIdentityHash) {
2521 LocalContext env;
2522 v8::Isolate* isolate = env->GetIsolate();
2523 v8::HandleScope scope(isolate);
2524
2525 {
2526 Local<v8::Symbol> symbol = v8::Symbol::New(isolate);
2527 int hash = symbol->GetIdentityHash();
2528 int hash1 = symbol->GetIdentityHash();
2529 CHECK_EQ(hash, hash1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002530 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002531 int hash3 = symbol->GetIdentityHash();
2532 CHECK_EQ(hash, hash3);
2533 }
2534
2535 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002536 v8::Local<v8::Symbol> js_symbol =
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002537 CompileRun("Symbol('foo')").As<v8::Symbol>();
2538 int hash = js_symbol->GetIdentityHash();
2539 int hash1 = js_symbol->GetIdentityHash();
2540 CHECK_EQ(hash, hash1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002541 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002542 int hash3 = js_symbol->GetIdentityHash();
2543 CHECK_EQ(hash, hash3);
2544 }
2545}
2546
2547
2548TEST(StringIdentityHash) {
2549 LocalContext env;
2550 v8::Isolate* isolate = env->GetIsolate();
2551 v8::HandleScope scope(isolate);
2552
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002553 Local<v8::String> str = v8_str("str1");
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002554 int hash = str->GetIdentityHash();
2555 int hash1 = str->GetIdentityHash();
2556 CHECK_EQ(hash, hash1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002557 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002558 int hash3 = str->GetIdentityHash();
2559 CHECK_EQ(hash, hash3);
2560
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002561 Local<v8::String> str2 = v8_str("str1");
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002562 int hash4 = str2->GetIdentityHash();
2563 CHECK_EQ(hash, hash4);
2564}
2565
2566
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002567THREADED_TEST(SymbolProperties) {
2568 LocalContext env;
2569 v8::Isolate* isolate = env->GetIsolate();
2570 v8::HandleScope scope(isolate);
2571
2572 v8::Local<v8::Object> obj = v8::Object::New(isolate);
2573 v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002574 v8::Local<v8::Symbol> sym2 = v8::Symbol::New(isolate, v8_str("my-symbol"));
2575 v8::Local<v8::Symbol> sym3 = v8::Symbol::New(isolate, v8_str("sym3"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002576
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002577 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002578
2579 // Check basic symbol functionality.
2580 CHECK(sym1->IsSymbol());
2581 CHECK(sym2->IsSymbol());
2582 CHECK(!obj->IsSymbol());
2583
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002584 CHECK(sym1->Equals(env.local(), sym1).FromJust());
2585 CHECK(sym2->Equals(env.local(), sym2).FromJust());
2586 CHECK(!sym1->Equals(env.local(), sym2).FromJust());
2587 CHECK(!sym2->Equals(env.local(), sym1).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002588 CHECK(sym1->StrictEquals(sym1));
2589 CHECK(sym2->StrictEquals(sym2));
2590 CHECK(!sym1->StrictEquals(sym2));
2591 CHECK(!sym2->StrictEquals(sym1));
2592
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002593 CHECK(sym2->Name()->Equals(env.local(), v8_str("my-symbol")).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002594
2595 v8::Local<v8::Value> sym_val = sym2;
2596 CHECK(sym_val->IsSymbol());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002597 CHECK(sym_val->Equals(env.local(), sym2).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002598 CHECK(sym_val->StrictEquals(sym2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002599 CHECK(v8::Symbol::Cast(*sym_val)->Equals(env.local(), sym2).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002600
2601 v8::Local<v8::Value> sym_obj = v8::SymbolObject::New(isolate, sym2);
2602 CHECK(sym_obj->IsSymbolObject());
2603 CHECK(!sym2->IsSymbolObject());
2604 CHECK(!obj->IsSymbolObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002605 CHECK(sym_obj->Equals(env.local(), sym2).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002606 CHECK(!sym_obj->StrictEquals(sym2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002607 CHECK(v8::SymbolObject::Cast(*sym_obj)
2608 ->Equals(env.local(), sym_obj)
2609 .FromJust());
2610 CHECK(v8::SymbolObject::Cast(*sym_obj)
2611 ->ValueOf()
2612 ->Equals(env.local(), sym2)
2613 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002614
2615 // Make sure delete of a non-existent symbol property works.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002616 CHECK(obj->Delete(env.local(), sym1).FromJust());
2617 CHECK(!obj->Has(env.local(), sym1).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002618
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002619 CHECK(
2620 obj->Set(env.local(), sym1, v8::Integer::New(isolate, 1503)).FromJust());
2621 CHECK(obj->Has(env.local(), sym1).FromJust());
2622 CHECK_EQ(1503, obj->Get(env.local(), sym1)
2623 .ToLocalChecked()
2624 ->Int32Value(env.local())
2625 .FromJust());
2626 CHECK(
2627 obj->Set(env.local(), sym1, v8::Integer::New(isolate, 2002)).FromJust());
2628 CHECK(obj->Has(env.local(), sym1).FromJust());
2629 CHECK_EQ(2002, obj->Get(env.local(), sym1)
2630 .ToLocalChecked()
2631 ->Int32Value(env.local())
2632 .FromJust());
2633 CHECK_EQ(v8::None, obj->GetPropertyAttributes(env.local(), sym1).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002634
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002635 CHECK_EQ(0u,
2636 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
2637 unsigned num_props =
2638 obj->GetPropertyNames(env.local()).ToLocalChecked()->Length();
2639 CHECK(obj->Set(env.local(), v8_str("bla"), v8::Integer::New(isolate, 20))
2640 .FromJust());
2641 CHECK_EQ(1u,
2642 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
2643 CHECK_EQ(num_props + 1,
2644 obj->GetPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002645
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002646 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002647
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002648 CHECK(obj->SetAccessor(env.local(), sym3, SymbolAccessorGetter,
2649 SymbolAccessorSetter)
2650 .FromJust());
2651 CHECK(obj->Get(env.local(), sym3).ToLocalChecked()->IsUndefined());
2652 CHECK(obj->Set(env.local(), sym3, v8::Integer::New(isolate, 42)).FromJust());
2653 CHECK(obj->Get(env.local(), sym3)
2654 .ToLocalChecked()
2655 ->Equals(env.local(), v8::Integer::New(isolate, 42))
2656 .FromJust());
2657 CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
2658 .ToLocalChecked()
2659 ->Equals(env.local(), v8::Integer::New(isolate, 42))
2660 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002661
2662 // Add another property and delete it afterwards to force the object in
2663 // slow case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002664 CHECK(
2665 obj->Set(env.local(), sym2, v8::Integer::New(isolate, 2008)).FromJust());
2666 CHECK_EQ(2002, obj->Get(env.local(), sym1)
2667 .ToLocalChecked()
2668 ->Int32Value(env.local())
2669 .FromJust());
2670 CHECK_EQ(2008, obj->Get(env.local(), sym2)
2671 .ToLocalChecked()
2672 ->Int32Value(env.local())
2673 .FromJust());
2674 CHECK_EQ(2002, obj->Get(env.local(), sym1)
2675 .ToLocalChecked()
2676 ->Int32Value(env.local())
2677 .FromJust());
2678 CHECK_EQ(2u,
2679 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002680
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002681 CHECK(obj->Has(env.local(), sym1).FromJust());
2682 CHECK(obj->Has(env.local(), sym2).FromJust());
2683 CHECK(obj->Has(env.local(), sym3).FromJust());
2684 CHECK(obj->Has(env.local(), v8_str("accessor_sym3")).FromJust());
2685 CHECK(obj->Delete(env.local(), sym2).FromJust());
2686 CHECK(obj->Has(env.local(), sym1).FromJust());
2687 CHECK(!obj->Has(env.local(), sym2).FromJust());
2688 CHECK(obj->Has(env.local(), sym3).FromJust());
2689 CHECK(obj->Has(env.local(), v8_str("accessor_sym3")).FromJust());
2690 CHECK_EQ(2002, obj->Get(env.local(), sym1)
2691 .ToLocalChecked()
2692 ->Int32Value(env.local())
2693 .FromJust());
2694 CHECK(obj->Get(env.local(), sym3)
2695 .ToLocalChecked()
2696 ->Equals(env.local(), v8::Integer::New(isolate, 42))
2697 .FromJust());
2698 CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
2699 .ToLocalChecked()
2700 ->Equals(env.local(), v8::Integer::New(isolate, 42))
2701 .FromJust());
2702 CHECK_EQ(2u,
2703 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002704
2705 // Symbol properties are inherited.
2706 v8::Local<v8::Object> child = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002707 CHECK(child->SetPrototype(env.local(), obj).FromJust());
2708 CHECK(child->Has(env.local(), sym1).FromJust());
2709 CHECK_EQ(2002, child->Get(env.local(), sym1)
2710 .ToLocalChecked()
2711 ->Int32Value(env.local())
2712 .FromJust());
2713 CHECK(obj->Get(env.local(), sym3)
2714 .ToLocalChecked()
2715 ->Equals(env.local(), v8::Integer::New(isolate, 42))
2716 .FromJust());
2717 CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
2718 .ToLocalChecked()
2719 ->Equals(env.local(), v8::Integer::New(isolate, 42))
2720 .FromJust());
2721 CHECK_EQ(0u,
2722 child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002723}
2724
2725
2726THREADED_TEST(SymbolTemplateProperties) {
2727 LocalContext env;
2728 v8::Isolate* isolate = env->GetIsolate();
2729 v8::HandleScope scope(isolate);
2730 v8::Local<v8::FunctionTemplate> foo = v8::FunctionTemplate::New(isolate);
2731 v8::Local<v8::Name> name = v8::Symbol::New(isolate);
2732 CHECK(!name.IsEmpty());
2733 foo->PrototypeTemplate()->Set(name, v8::FunctionTemplate::New(isolate));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002734 v8::Local<v8::Object> new_instance =
2735 foo->InstanceTemplate()->NewInstance(env.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002736 CHECK(!new_instance.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002737 CHECK(new_instance->Has(env.local(), name).FromJust());
2738}
2739
2740
2741THREADED_TEST(PrivatePropertiesOnProxies) {
2742 i::FLAG_harmony_proxies = true;
2743 LocalContext env;
2744 v8::Isolate* isolate = env->GetIsolate();
2745 v8::HandleScope scope(isolate);
2746
2747 v8::Local<v8::Object> target = CompileRun("({})").As<v8::Object>();
2748 v8::Local<v8::Object> handler = CompileRun("({})").As<v8::Object>();
2749
2750 v8::Local<v8::Proxy> proxy =
2751 v8::Proxy::New(env.local(), target, handler).ToLocalChecked();
2752
2753 v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
2754 v8::Local<v8::Private> priv2 =
2755 v8::Private::New(isolate, v8_str("my-private"));
2756
2757 CcTest::heap()->CollectAllGarbage();
2758
2759 CHECK(priv2->Name()
2760 ->Equals(env.local(),
2761 v8::String::NewFromUtf8(isolate, "my-private",
2762 v8::NewStringType::kNormal)
2763 .ToLocalChecked())
2764 .FromJust());
2765
2766 // Make sure delete of a non-existent private symbol property works.
2767 proxy->DeletePrivate(env.local(), priv1).FromJust();
2768 CHECK(!proxy->HasPrivate(env.local(), priv1).FromJust());
2769
2770 CHECK(proxy->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 1503))
2771 .FromJust());
2772 CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
2773 CHECK_EQ(1503, proxy->GetPrivate(env.local(), priv1)
2774 .ToLocalChecked()
2775 ->Int32Value(env.local())
2776 .FromJust());
2777 CHECK(proxy->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 2002))
2778 .FromJust());
2779 CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
2780 CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
2781 .ToLocalChecked()
2782 ->Int32Value(env.local())
2783 .FromJust());
2784
2785 CHECK_EQ(0u,
2786 proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
2787 unsigned num_props =
2788 proxy->GetPropertyNames(env.local()).ToLocalChecked()->Length();
2789 CHECK(proxy->Set(env.local(), v8::String::NewFromUtf8(
2790 isolate, "bla", v8::NewStringType::kNormal)
2791 .ToLocalChecked(),
2792 v8::Integer::New(isolate, 20))
2793 .FromJust());
2794 CHECK_EQ(1u,
2795 proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
2796 CHECK_EQ(num_props + 1,
2797 proxy->GetPropertyNames(env.local()).ToLocalChecked()->Length());
2798
2799 CcTest::heap()->CollectAllGarbage();
2800
2801 // Add another property and delete it afterwards to force the object in
2802 // slow case.
2803 CHECK(proxy->SetPrivate(env.local(), priv2, v8::Integer::New(isolate, 2008))
2804 .FromJust());
2805 CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
2806 .ToLocalChecked()
2807 ->Int32Value(env.local())
2808 .FromJust());
2809 CHECK_EQ(2008, proxy->GetPrivate(env.local(), priv2)
2810 .ToLocalChecked()
2811 ->Int32Value(env.local())
2812 .FromJust());
2813 CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
2814 .ToLocalChecked()
2815 ->Int32Value(env.local())
2816 .FromJust());
2817 CHECK_EQ(1u,
2818 proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
2819
2820 CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
2821 CHECK(proxy->HasPrivate(env.local(), priv2).FromJust());
2822 CHECK(proxy->DeletePrivate(env.local(), priv2).FromJust());
2823 CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
2824 CHECK(!proxy->HasPrivate(env.local(), priv2).FromJust());
2825 CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
2826 .ToLocalChecked()
2827 ->Int32Value(env.local())
2828 .FromJust());
2829 CHECK_EQ(1u,
2830 proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
2831
2832 // Private properties are not inherited (for the time being).
2833 v8::Local<v8::Object> child = v8::Object::New(isolate);
2834 CHECK(child->SetPrototype(env.local(), proxy).FromJust());
2835 CHECK(!child->HasPrivate(env.local(), priv1).FromJust());
2836 CHECK_EQ(0u,
2837 child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002838}
2839
2840
2841THREADED_TEST(PrivateProperties) {
2842 LocalContext env;
2843 v8::Isolate* isolate = env->GetIsolate();
2844 v8::HandleScope scope(isolate);
2845
2846 v8::Local<v8::Object> obj = v8::Object::New(isolate);
2847 v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
2848 v8::Local<v8::Private> priv2 =
2849 v8::Private::New(isolate, v8_str("my-private"));
2850
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002851 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002852
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002853 CHECK(priv2->Name()
2854 ->Equals(env.local(),
2855 v8::String::NewFromUtf8(isolate, "my-private",
2856 v8::NewStringType::kNormal)
2857 .ToLocalChecked())
2858 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002859
2860 // Make sure delete of a non-existent private symbol property works.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002861 obj->DeletePrivate(env.local(), priv1).FromJust();
2862 CHECK(!obj->HasPrivate(env.local(), priv1).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002863
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002864 CHECK(obj->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 1503))
2865 .FromJust());
2866 CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
2867 CHECK_EQ(1503, obj->GetPrivate(env.local(), priv1)
2868 .ToLocalChecked()
2869 ->Int32Value(env.local())
2870 .FromJust());
2871 CHECK(obj->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 2002))
2872 .FromJust());
2873 CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
2874 CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
2875 .ToLocalChecked()
2876 ->Int32Value(env.local())
2877 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002878
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002879 CHECK_EQ(0u,
2880 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
2881 unsigned num_props =
2882 obj->GetPropertyNames(env.local()).ToLocalChecked()->Length();
2883 CHECK(obj->Set(env.local(), v8::String::NewFromUtf8(
2884 isolate, "bla", v8::NewStringType::kNormal)
2885 .ToLocalChecked(),
2886 v8::Integer::New(isolate, 20))
2887 .FromJust());
2888 CHECK_EQ(1u,
2889 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
2890 CHECK_EQ(num_props + 1,
2891 obj->GetPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002892
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002893 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002894
2895 // Add another property and delete it afterwards to force the object in
2896 // slow case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002897 CHECK(obj->SetPrivate(env.local(), priv2, v8::Integer::New(isolate, 2008))
2898 .FromJust());
2899 CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
2900 .ToLocalChecked()
2901 ->Int32Value(env.local())
2902 .FromJust());
2903 CHECK_EQ(2008, obj->GetPrivate(env.local(), priv2)
2904 .ToLocalChecked()
2905 ->Int32Value(env.local())
2906 .FromJust());
2907 CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
2908 .ToLocalChecked()
2909 ->Int32Value(env.local())
2910 .FromJust());
2911 CHECK_EQ(1u,
2912 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002913
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002914 CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
2915 CHECK(obj->HasPrivate(env.local(), priv2).FromJust());
2916 CHECK(obj->DeletePrivate(env.local(), priv2).FromJust());
2917 CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
2918 CHECK(!obj->HasPrivate(env.local(), priv2).FromJust());
2919 CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
2920 .ToLocalChecked()
2921 ->Int32Value(env.local())
2922 .FromJust());
2923 CHECK_EQ(1u,
2924 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002925
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002926 // Private properties are not inherited (for the time being).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002927 v8::Local<v8::Object> child = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002928 CHECK(child->SetPrototype(env.local(), obj).FromJust());
2929 CHECK(!child->HasPrivate(env.local(), priv1).FromJust());
2930 CHECK_EQ(0u,
2931 child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002932}
2933
2934
2935THREADED_TEST(GlobalSymbols) {
2936 LocalContext env;
2937 v8::Isolate* isolate = env->GetIsolate();
2938 v8::HandleScope scope(isolate);
2939
2940 v8::Local<String> name = v8_str("my-symbol");
2941 v8::Local<v8::Symbol> glob = v8::Symbol::For(isolate, name);
2942 v8::Local<v8::Symbol> glob2 = v8::Symbol::For(isolate, name);
2943 CHECK(glob2->SameValue(glob));
2944
2945 v8::Local<v8::Symbol> glob_api = v8::Symbol::ForApi(isolate, name);
2946 v8::Local<v8::Symbol> glob_api2 = v8::Symbol::ForApi(isolate, name);
2947 CHECK(glob_api2->SameValue(glob_api));
2948 CHECK(!glob_api->SameValue(glob));
2949
2950 v8::Local<v8::Symbol> sym = v8::Symbol::New(isolate, name);
2951 CHECK(!sym->SameValue(glob));
2952
2953 CompileRun("var sym2 = Symbol.for('my-symbol')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002954 v8::Local<Value> sym2 =
2955 env->Global()->Get(env.local(), v8_str("sym2")).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002956 CHECK(sym2->SameValue(glob));
2957 CHECK(!sym2->SameValue(glob_api));
2958}
2959
2960
2961static void CheckWellKnownSymbol(v8::Local<v8::Symbol>(*getter)(v8::Isolate*),
2962 const char* name) {
2963 LocalContext env;
2964 v8::Isolate* isolate = env->GetIsolate();
2965 v8::HandleScope scope(isolate);
2966
2967 v8::Local<v8::Symbol> symbol = getter(isolate);
2968 std::string script = std::string("var sym = ") + name;
2969 CompileRun(script.c_str());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002970 v8::Local<Value> value =
2971 env->Global()->Get(env.local(), v8_str("sym")).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002972
2973 CHECK(!value.IsEmpty());
2974 CHECK(!symbol.IsEmpty());
2975 CHECK(value->SameValue(symbol));
2976}
2977
2978
2979THREADED_TEST(WellKnownSymbols) {
2980 CheckWellKnownSymbol(v8::Symbol::GetIterator, "Symbol.iterator");
2981 CheckWellKnownSymbol(v8::Symbol::GetUnscopables, "Symbol.unscopables");
2982}
2983
2984
2985THREADED_TEST(GlobalPrivates) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002986 i::FLAG_allow_natives_syntax = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002987 LocalContext env;
2988 v8::Isolate* isolate = env->GetIsolate();
2989 v8::HandleScope scope(isolate);
2990
2991 v8::Local<String> name = v8_str("my-private");
2992 v8::Local<v8::Private> glob = v8::Private::ForApi(isolate, name);
2993 v8::Local<v8::Object> obj = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002994 CHECK(obj->SetPrivate(env.local(), glob, v8::Integer::New(isolate, 3))
2995 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002996
2997 v8::Local<v8::Private> glob2 = v8::Private::ForApi(isolate, name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002998 CHECK(obj->HasPrivate(env.local(), glob2).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002999
3000 v8::Local<v8::Private> priv = v8::Private::New(isolate, name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003001 CHECK(!obj->HasPrivate(env.local(), priv).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003002
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003003 CompileRun("var intern = %CreatePrivateSymbol('my-private')");
3004 v8::Local<Value> intern =
3005 env->Global()->Get(env.local(), v8_str("intern")).ToLocalChecked();
3006 CHECK(!obj->Has(env.local(), intern).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003007}
3008
3009
3010class ScopedArrayBufferContents {
3011 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003012 explicit ScopedArrayBufferContents(const v8::ArrayBuffer::Contents& contents)
3013 : contents_(contents) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003014 ~ScopedArrayBufferContents() { free(contents_.Data()); }
3015 void* Data() const { return contents_.Data(); }
3016 size_t ByteLength() const { return contents_.ByteLength(); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003017
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003018 private:
3019 const v8::ArrayBuffer::Contents contents_;
3020};
3021
3022template <typename T>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003023static void CheckInternalFieldsAreZero(v8::Local<T> value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003024 CHECK_EQ(T::kInternalFieldCount, value->InternalFieldCount());
3025 for (int i = 0; i < value->InternalFieldCount(); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003026 CHECK_EQ(0, value->GetInternalField(i)
3027 ->Int32Value(CcTest::isolate()->GetCurrentContext())
3028 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003029 }
3030}
3031
3032
3033THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
3034 LocalContext env;
3035 v8::Isolate* isolate = env->GetIsolate();
3036 v8::HandleScope handle_scope(isolate);
3037
3038 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 1024);
3039 CheckInternalFieldsAreZero(ab);
3040 CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
3041 CHECK(!ab->IsExternal());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003042 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003043
3044 ScopedArrayBufferContents ab_contents(ab->Externalize());
3045 CHECK(ab->IsExternal());
3046
3047 CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
3048 uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003049 CHECK(data != NULL);
3050 CHECK(env->Global()->Set(env.local(), v8_str("ab"), ab).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003051
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003052 v8::Local<v8::Value> result = CompileRun("ab.byteLength");
3053 CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003054
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003055 result = CompileRun(
3056 "var u8 = new Uint8Array(ab);"
3057 "u8[0] = 0xFF;"
3058 "u8[1] = 0xAA;"
3059 "u8.length");
3060 CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003061 CHECK_EQ(0xFF, data[0]);
3062 CHECK_EQ(0xAA, data[1]);
3063 data[0] = 0xCC;
3064 data[1] = 0x11;
3065 result = CompileRun("u8[0] + u8[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003066 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003067}
3068
3069
3070THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
3071 LocalContext env;
3072 v8::Isolate* isolate = env->GetIsolate();
3073 v8::HandleScope handle_scope(isolate);
3074
3075
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003076 v8::Local<v8::Value> result = CompileRun(
3077 "var ab1 = new ArrayBuffer(2);"
3078 "var u8_a = new Uint8Array(ab1);"
3079 "u8_a[0] = 0xAA;"
3080 "u8_a[1] = 0xFF; u8_a.buffer");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003081 Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
3082 CheckInternalFieldsAreZero(ab1);
3083 CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
3084 CHECK(!ab1->IsExternal());
3085 ScopedArrayBufferContents ab1_contents(ab1->Externalize());
3086 CHECK(ab1->IsExternal());
3087
3088 result = CompileRun("ab1.byteLength");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003089 CHECK_EQ(2, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003090 result = CompileRun("u8_a[0]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003091 CHECK_EQ(0xAA, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003092 result = CompileRun("u8_a[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003093 CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
3094 result = CompileRun(
3095 "var u8_b = new Uint8Array(ab1);"
3096 "u8_b[0] = 0xBB;"
3097 "u8_a[0]");
3098 CHECK_EQ(0xBB, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003099 result = CompileRun("u8_b[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003100 CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003101
3102 CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
3103 uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
3104 CHECK_EQ(0xBB, ab1_data[0]);
3105 CHECK_EQ(0xFF, ab1_data[1]);
3106 ab1_data[0] = 0xCC;
3107 ab1_data[1] = 0x11;
3108 result = CompileRun("u8_a[0] + u8_a[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003109 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003110}
3111
3112
3113THREADED_TEST(ArrayBuffer_External) {
3114 LocalContext env;
3115 v8::Isolate* isolate = env->GetIsolate();
3116 v8::HandleScope handle_scope(isolate);
3117
3118 i::ScopedVector<uint8_t> my_data(100);
3119 memset(my_data.start(), 0, 100);
3120 Local<v8::ArrayBuffer> ab3 =
3121 v8::ArrayBuffer::New(isolate, my_data.start(), 100);
3122 CheckInternalFieldsAreZero(ab3);
3123 CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
3124 CHECK(ab3->IsExternal());
3125
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003126 CHECK(env->Global()->Set(env.local(), v8_str("ab3"), ab3).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003127
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003128 v8::Local<v8::Value> result = CompileRun("ab3.byteLength");
3129 CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003130
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003131 result = CompileRun(
3132 "var u8_b = new Uint8Array(ab3);"
3133 "u8_b[0] = 0xBB;"
3134 "u8_b[1] = 0xCC;"
3135 "u8_b.length");
3136 CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003137 CHECK_EQ(0xBB, my_data[0]);
3138 CHECK_EQ(0xCC, my_data[1]);
3139 my_data[0] = 0xCC;
3140 my_data[1] = 0x11;
3141 result = CompileRun("u8_b[0] + u8_b[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003142 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003143}
3144
3145
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003146THREADED_TEST(ArrayBuffer_DisableNeuter) {
3147 LocalContext env;
3148 v8::Isolate* isolate = env->GetIsolate();
3149 v8::HandleScope handle_scope(isolate);
3150
3151 i::ScopedVector<uint8_t> my_data(100);
3152 memset(my_data.start(), 0, 100);
3153 Local<v8::ArrayBuffer> ab =
3154 v8::ArrayBuffer::New(isolate, my_data.start(), 100);
3155 CHECK(ab->IsNeuterable());
3156
3157 i::Handle<i::JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
3158 buf->set_is_neuterable(false);
3159
3160 CHECK(!ab->IsNeuterable());
3161}
3162
3163
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003164static void CheckDataViewIsNeutered(v8::Local<v8::DataView> dv) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003165 CHECK_EQ(0, static_cast<int>(dv->ByteLength()));
3166 CHECK_EQ(0, static_cast<int>(dv->ByteOffset()));
3167}
3168
3169
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003170static void CheckIsNeutered(v8::Local<v8::TypedArray> ta) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003171 CHECK_EQ(0, static_cast<int>(ta->ByteLength()));
3172 CHECK_EQ(0, static_cast<int>(ta->Length()));
3173 CHECK_EQ(0, static_cast<int>(ta->ByteOffset()));
3174}
3175
3176
3177static void CheckIsTypedArrayVarNeutered(const char* name) {
3178 i::ScopedVector<char> source(1024);
3179 i::SNPrintF(source,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003180 "%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
3181 name, name, name);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003182 CHECK(CompileRun(source.start())->IsTrue());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003183 v8::Local<v8::TypedArray> ta =
3184 v8::Local<v8::TypedArray>::Cast(CompileRun(name));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003185 CheckIsNeutered(ta);
3186}
3187
3188
3189template <typename TypedArray, int kElementSize>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003190static Local<TypedArray> CreateAndCheck(Local<v8::ArrayBuffer> ab,
3191 int byteOffset, int length) {
3192 v8::Local<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003193 CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
3194 CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
3195 CHECK_EQ(length, static_cast<int>(ta->Length()));
3196 CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
3197 return ta;
3198}
3199
3200
3201THREADED_TEST(ArrayBuffer_NeuteringApi) {
3202 LocalContext env;
3203 v8::Isolate* isolate = env->GetIsolate();
3204 v8::HandleScope handle_scope(isolate);
3205
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003206 v8::Local<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1024);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003207
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003208 v8::Local<v8::Uint8Array> u8a =
3209 CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
3210 v8::Local<v8::Uint8ClampedArray> u8c =
3211 CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
3212 v8::Local<v8::Int8Array> i8a =
3213 CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003214
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003215 v8::Local<v8::Uint16Array> u16a =
3216 CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
3217 v8::Local<v8::Int16Array> i16a =
3218 CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003219
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003220 v8::Local<v8::Uint32Array> u32a =
3221 CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
3222 v8::Local<v8::Int32Array> i32a =
3223 CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003224
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003225 v8::Local<v8::Float32Array> f32a =
3226 CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
3227 v8::Local<v8::Float64Array> f64a =
3228 CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003229
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003230 v8::Local<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003231 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
3232 CHECK_EQ(1, static_cast<int>(dv->ByteOffset()));
3233 CHECK_EQ(1023, static_cast<int>(dv->ByteLength()));
3234
3235 ScopedArrayBufferContents contents(buffer->Externalize());
3236 buffer->Neuter();
3237 CHECK_EQ(0, static_cast<int>(buffer->ByteLength()));
3238 CheckIsNeutered(u8a);
3239 CheckIsNeutered(u8c);
3240 CheckIsNeutered(i8a);
3241 CheckIsNeutered(u16a);
3242 CheckIsNeutered(i16a);
3243 CheckIsNeutered(u32a);
3244 CheckIsNeutered(i32a);
3245 CheckIsNeutered(f32a);
3246 CheckIsNeutered(f64a);
3247 CheckDataViewIsNeutered(dv);
3248}
3249
3250
3251THREADED_TEST(ArrayBuffer_NeuteringScript) {
3252 LocalContext env;
3253 v8::Isolate* isolate = env->GetIsolate();
3254 v8::HandleScope handle_scope(isolate);
3255
3256 CompileRun(
3257 "var ab = new ArrayBuffer(1024);"
3258 "var u8a = new Uint8Array(ab, 1, 1023);"
3259 "var u8c = new Uint8ClampedArray(ab, 1, 1023);"
3260 "var i8a = new Int8Array(ab, 1, 1023);"
3261 "var u16a = new Uint16Array(ab, 2, 511);"
3262 "var i16a = new Int16Array(ab, 2, 511);"
3263 "var u32a = new Uint32Array(ab, 4, 255);"
3264 "var i32a = new Int32Array(ab, 4, 255);"
3265 "var f32a = new Float32Array(ab, 4, 255);"
3266 "var f64a = new Float64Array(ab, 8, 127);"
3267 "var dv = new DataView(ab, 1, 1023);");
3268
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003269 v8::Local<v8::ArrayBuffer> ab =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003270 Local<v8::ArrayBuffer>::Cast(CompileRun("ab"));
3271
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003272 v8::Local<v8::DataView> dv = v8::Local<v8::DataView>::Cast(CompileRun("dv"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003273
3274 ScopedArrayBufferContents contents(ab->Externalize());
3275 ab->Neuter();
3276 CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003277 CHECK_EQ(0, v8_run_int32value(v8_compile("ab.byteLength")));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003278
3279 CheckIsTypedArrayVarNeutered("u8a");
3280 CheckIsTypedArrayVarNeutered("u8c");
3281 CheckIsTypedArrayVarNeutered("i8a");
3282 CheckIsTypedArrayVarNeutered("u16a");
3283 CheckIsTypedArrayVarNeutered("i16a");
3284 CheckIsTypedArrayVarNeutered("u32a");
3285 CheckIsTypedArrayVarNeutered("i32a");
3286 CheckIsTypedArrayVarNeutered("f32a");
3287 CheckIsTypedArrayVarNeutered("f64a");
3288
3289 CHECK(CompileRun("dv.byteLength == 0 && dv.byteOffset == 0")->IsTrue());
3290 CheckDataViewIsNeutered(dv);
3291}
3292
3293
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003294class ScopedSharedArrayBufferContents {
3295 public:
3296 explicit ScopedSharedArrayBufferContents(
3297 const v8::SharedArrayBuffer::Contents& contents)
3298 : contents_(contents) {}
3299 ~ScopedSharedArrayBufferContents() { free(contents_.Data()); }
3300 void* Data() const { return contents_.Data(); }
3301 size_t ByteLength() const { return contents_.ByteLength(); }
3302
3303 private:
3304 const v8::SharedArrayBuffer::Contents contents_;
3305};
3306
3307
3308THREADED_TEST(SharedArrayBuffer_ApiInternalToExternal) {
3309 i::FLAG_harmony_sharedarraybuffer = true;
3310 LocalContext env;
3311 v8::Isolate* isolate = env->GetIsolate();
3312 v8::HandleScope handle_scope(isolate);
3313
3314 Local<v8::SharedArrayBuffer> ab = v8::SharedArrayBuffer::New(isolate, 1024);
3315 CheckInternalFieldsAreZero(ab);
3316 CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
3317 CHECK(!ab->IsExternal());
3318 CcTest::heap()->CollectAllGarbage();
3319
3320 ScopedSharedArrayBufferContents ab_contents(ab->Externalize());
3321 CHECK(ab->IsExternal());
3322
3323 CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
3324 uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
3325 CHECK(data != NULL);
3326 CHECK(env->Global()->Set(env.local(), v8_str("ab"), ab).FromJust());
3327
3328 v8::Local<v8::Value> result = CompileRun("ab.byteLength");
3329 CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
3330
3331 result = CompileRun(
3332 "var u8 = new Uint8Array(ab);"
3333 "u8[0] = 0xFF;"
3334 "u8[1] = 0xAA;"
3335 "u8.length");
3336 CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
3337 CHECK_EQ(0xFF, data[0]);
3338 CHECK_EQ(0xAA, data[1]);
3339 data[0] = 0xCC;
3340 data[1] = 0x11;
3341 result = CompileRun("u8[0] + u8[1]");
3342 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
3343}
3344
3345
3346THREADED_TEST(SharedArrayBuffer_JSInternalToExternal) {
3347 i::FLAG_harmony_sharedarraybuffer = true;
3348 LocalContext env;
3349 v8::Isolate* isolate = env->GetIsolate();
3350 v8::HandleScope handle_scope(isolate);
3351
3352
3353 v8::Local<v8::Value> result = CompileRun(
3354 "var ab1 = new SharedArrayBuffer(2);"
3355 "var u8_a = new Uint8Array(ab1);"
3356 "u8_a[0] = 0xAA;"
3357 "u8_a[1] = 0xFF; u8_a.buffer");
3358 Local<v8::SharedArrayBuffer> ab1 = Local<v8::SharedArrayBuffer>::Cast(result);
3359 CheckInternalFieldsAreZero(ab1);
3360 CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
3361 CHECK(!ab1->IsExternal());
3362 ScopedSharedArrayBufferContents ab1_contents(ab1->Externalize());
3363 CHECK(ab1->IsExternal());
3364
3365 result = CompileRun("ab1.byteLength");
3366 CHECK_EQ(2, result->Int32Value(env.local()).FromJust());
3367 result = CompileRun("u8_a[0]");
3368 CHECK_EQ(0xAA, result->Int32Value(env.local()).FromJust());
3369 result = CompileRun("u8_a[1]");
3370 CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
3371 result = CompileRun(
3372 "var u8_b = new Uint8Array(ab1);"
3373 "u8_b[0] = 0xBB;"
3374 "u8_a[0]");
3375 CHECK_EQ(0xBB, result->Int32Value(env.local()).FromJust());
3376 result = CompileRun("u8_b[1]");
3377 CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
3378
3379 CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
3380 uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
3381 CHECK_EQ(0xBB, ab1_data[0]);
3382 CHECK_EQ(0xFF, ab1_data[1]);
3383 ab1_data[0] = 0xCC;
3384 ab1_data[1] = 0x11;
3385 result = CompileRun("u8_a[0] + u8_a[1]");
3386 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
3387}
3388
3389
3390THREADED_TEST(SharedArrayBuffer_External) {
3391 i::FLAG_harmony_sharedarraybuffer = true;
3392 LocalContext env;
3393 v8::Isolate* isolate = env->GetIsolate();
3394 v8::HandleScope handle_scope(isolate);
3395
3396 i::ScopedVector<uint8_t> my_data(100);
3397 memset(my_data.start(), 0, 100);
3398 Local<v8::SharedArrayBuffer> ab3 =
3399 v8::SharedArrayBuffer::New(isolate, my_data.start(), 100);
3400 CheckInternalFieldsAreZero(ab3);
3401 CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
3402 CHECK(ab3->IsExternal());
3403
3404 CHECK(env->Global()->Set(env.local(), v8_str("ab3"), ab3).FromJust());
3405
3406 v8::Local<v8::Value> result = CompileRun("ab3.byteLength");
3407 CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
3408
3409 result = CompileRun(
3410 "var u8_b = new Uint8Array(ab3);"
3411 "u8_b[0] = 0xBB;"
3412 "u8_b[1] = 0xCC;"
3413 "u8_b.length");
3414 CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
3415 CHECK_EQ(0xBB, my_data[0]);
3416 CHECK_EQ(0xCC, my_data[1]);
3417 my_data[0] = 0xCC;
3418 my_data[1] = 0x11;
3419 result = CompileRun("u8_b[0] + u8_b[1]");
3420 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
3421}
3422
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003423
3424THREADED_TEST(HiddenProperties) {
3425 LocalContext env;
3426 v8::Isolate* isolate = env->GetIsolate();
3427 v8::HandleScope scope(isolate);
3428
3429 v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003430 v8::Local<v8::Private> key =
3431 v8::Private::ForApi(isolate, v8_str("api-test::hidden-key"));
Steve Blocka7e24c12009-10-30 11:49:00 +00003432 v8::Local<v8::String> empty = v8_str("");
3433 v8::Local<v8::String> prop_name = v8_str("prop_name");
3434
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003435 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +00003436
3437 // Make sure delete of a non-existent hidden value works
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003438 obj->DeletePrivate(env.local(), key).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00003439
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003440 CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 1503))
3441 .FromJust());
3442 CHECK_EQ(1503, obj->GetPrivate(env.local(), key)
3443 .ToLocalChecked()
3444 ->Int32Value(env.local())
3445 .FromJust());
3446 CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 2002))
3447 .FromJust());
3448 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3449 .ToLocalChecked()
3450 ->Int32Value(env.local())
3451 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00003452
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003453 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +00003454
3455 // Make sure we do not find the hidden property.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003456 CHECK(!obj->Has(env.local(), empty).FromJust());
3457 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3458 .ToLocalChecked()
3459 ->Int32Value(env.local())
3460 .FromJust());
3461 CHECK(obj->Get(env.local(), empty).ToLocalChecked()->IsUndefined());
3462 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3463 .ToLocalChecked()
3464 ->Int32Value(env.local())
3465 .FromJust());
3466 CHECK(
3467 obj->Set(env.local(), empty, v8::Integer::New(isolate, 2003)).FromJust());
3468 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3469 .ToLocalChecked()
3470 ->Int32Value(env.local())
3471 .FromJust());
3472 CHECK_EQ(2003, obj->Get(env.local(), empty)
3473 .ToLocalChecked()
3474 ->Int32Value(env.local())
3475 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00003476
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003477 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +00003478
3479 // Add another property and delete it afterwards to force the object in
3480 // slow case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003481 CHECK(obj->Set(env.local(), prop_name, v8::Integer::New(isolate, 2008))
3482 .FromJust());
3483 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3484 .ToLocalChecked()
3485 ->Int32Value(env.local())
3486 .FromJust());
3487 CHECK_EQ(2008, obj->Get(env.local(), prop_name)
3488 .ToLocalChecked()
3489 ->Int32Value(env.local())
3490 .FromJust());
3491 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3492 .ToLocalChecked()
3493 ->Int32Value(env.local())
3494 .FromJust());
3495 CHECK(obj->Delete(env.local(), prop_name).FromJust());
3496 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3497 .ToLocalChecked()
3498 ->Int32Value(env.local())
3499 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00003500
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003501 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +00003502
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003503 CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 2002))
3504 .FromJust());
3505 CHECK(obj->DeletePrivate(env.local(), key).FromJust());
3506 CHECK(!obj->HasPrivate(env.local(), key).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00003507}
3508
3509
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003510THREADED_TEST(Regress97784) {
3511 // Regression test for crbug.com/97784
3512 // Messing with the Object.prototype should not have effect on
3513 // hidden properties.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003514 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003515 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003516
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003517 v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003518 v8::Local<v8::Private> key =
3519 v8::Private::New(env->GetIsolate(), v8_str("hidden"));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003520
3521 CompileRun(
3522 "set_called = false;"
3523 "Object.defineProperty("
3524 " Object.prototype,"
3525 " 'hidden',"
3526 " {get: function() { return 45; },"
3527 " set: function() { set_called = true; }})");
3528
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003529 CHECK(!obj->HasPrivate(env.local(), key).FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003530 // Make sure that the getter and setter from Object.prototype is not invoked.
3531 // If it did we would have full access to the hidden properties in
3532 // the accessor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003533 CHECK(
3534 obj->SetPrivate(env.local(), key, v8::Integer::New(env->GetIsolate(), 42))
3535 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003536 ExpectFalse("set_called");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003537 CHECK_EQ(42, obj->GetPrivate(env.local(), key)
3538 .ToLocalChecked()
3539 ->Int32Value(env.local())
3540 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00003541}
3542
3543
3544THREADED_TEST(External) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003545 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00003546 int x = 3;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003547 Local<v8::External> ext = v8::External::New(CcTest::isolate(), &x);
Steve Blocka7e24c12009-10-30 11:49:00 +00003548 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003549 CHECK(env->Global()->Set(env.local(), v8_str("ext"), ext).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003550 Local<Value> reext_obj = CompileRun("this.ext");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003551 v8::Local<v8::External> reext = reext_obj.As<v8::External>();
Steve Blocka7e24c12009-10-30 11:49:00 +00003552 int* ptr = static_cast<int*>(reext->Value());
3553 CHECK_EQ(x, 3);
3554 *ptr = 10;
3555 CHECK_EQ(x, 10);
3556
3557 // Make sure unaligned pointers are wrapped properly.
3558 char* data = i::StrDup("0123456789");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003559 Local<v8::Value> zero = v8::External::New(CcTest::isolate(), &data[0]);
3560 Local<v8::Value> one = v8::External::New(CcTest::isolate(), &data[1]);
3561 Local<v8::Value> two = v8::External::New(CcTest::isolate(), &data[2]);
3562 Local<v8::Value> three = v8::External::New(CcTest::isolate(), &data[3]);
Steve Blocka7e24c12009-10-30 11:49:00 +00003563
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003564 char* char_ptr = reinterpret_cast<char*>(v8::External::Cast(*zero)->Value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003565 CHECK_EQ('0', *char_ptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003566 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*one)->Value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003567 CHECK_EQ('1', *char_ptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003568 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*two)->Value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003569 CHECK_EQ('2', *char_ptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003570 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*three)->Value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003571 CHECK_EQ('3', *char_ptr);
3572 i::DeleteArray(data);
3573}
3574
3575
3576THREADED_TEST(GlobalHandle) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003577 v8::Isolate* isolate = CcTest::isolate();
Steve Blocka7e24c12009-10-30 11:49:00 +00003578 v8::Persistent<String> global;
3579 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003580 v8::HandleScope scope(isolate);
3581 global.Reset(isolate, v8_str("str"));
Steve Blocka7e24c12009-10-30 11:49:00 +00003582 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003583 {
3584 v8::HandleScope scope(isolate);
3585 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3586 }
3587 global.Reset();
3588 {
3589 v8::HandleScope scope(isolate);
3590 global.Reset(isolate, v8_str("str"));
3591 }
3592 {
3593 v8::HandleScope scope(isolate);
3594 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3595 }
3596 global.Reset();
3597}
3598
3599
3600THREADED_TEST(ResettingGlobalHandle) {
3601 v8::Isolate* isolate = CcTest::isolate();
3602 v8::Persistent<String> global;
3603 {
3604 v8::HandleScope scope(isolate);
3605 global.Reset(isolate, v8_str("str"));
3606 }
3607 v8::internal::GlobalHandles* global_handles =
3608 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3609 int initial_handle_count = global_handles->global_handles_count();
3610 {
3611 v8::HandleScope scope(isolate);
3612 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3613 }
3614 {
3615 v8::HandleScope scope(isolate);
3616 global.Reset(isolate, v8_str("longer"));
3617 }
3618 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count);
3619 {
3620 v8::HandleScope scope(isolate);
3621 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 6);
3622 }
3623 global.Reset();
3624 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
3625}
3626
3627
3628THREADED_TEST(ResettingGlobalHandleToEmpty) {
3629 v8::Isolate* isolate = CcTest::isolate();
3630 v8::Persistent<String> global;
3631 {
3632 v8::HandleScope scope(isolate);
3633 global.Reset(isolate, v8_str("str"));
3634 }
3635 v8::internal::GlobalHandles* global_handles =
3636 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3637 int initial_handle_count = global_handles->global_handles_count();
3638 {
3639 v8::HandleScope scope(isolate);
3640 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3641 }
3642 {
3643 v8::HandleScope scope(isolate);
3644 Local<String> empty;
3645 global.Reset(isolate, empty);
3646 }
3647 CHECK(global.IsEmpty());
3648 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
3649}
3650
3651
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003652template <class T>
3653static v8::Global<T> PassUnique(v8::Global<T> unique) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003654 return unique.Pass();
3655}
3656
3657
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003658template <class T>
3659static v8::Global<T> ReturnUnique(v8::Isolate* isolate,
3660 const v8::Persistent<T>& global) {
3661 v8::Global<String> unique(isolate, global);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003662 return unique.Pass();
3663}
3664
3665
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003666THREADED_TEST(Global) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003667 v8::Isolate* isolate = CcTest::isolate();
3668 v8::Persistent<String> global;
3669 {
3670 v8::HandleScope scope(isolate);
3671 global.Reset(isolate, v8_str("str"));
3672 }
3673 v8::internal::GlobalHandles* global_handles =
3674 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3675 int initial_handle_count = global_handles->global_handles_count();
3676 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003677 v8::Global<String> unique(isolate, global);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003678 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3679 // Test assignment via Pass
3680 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003681 v8::Global<String> copy = unique.Pass();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003682 CHECK(unique.IsEmpty());
3683 CHECK(copy == global);
3684 CHECK_EQ(initial_handle_count + 1,
3685 global_handles->global_handles_count());
3686 unique = copy.Pass();
3687 }
3688 // Test ctor via Pass
3689 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003690 v8::Global<String> copy(unique.Pass());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003691 CHECK(unique.IsEmpty());
3692 CHECK(copy == global);
3693 CHECK_EQ(initial_handle_count + 1,
3694 global_handles->global_handles_count());
3695 unique = copy.Pass();
3696 }
3697 // Test pass through function call
3698 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003699 v8::Global<String> copy = PassUnique(unique.Pass());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003700 CHECK(unique.IsEmpty());
3701 CHECK(copy == global);
3702 CHECK_EQ(initial_handle_count + 1,
3703 global_handles->global_handles_count());
3704 unique = copy.Pass();
3705 }
3706 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3707 }
3708 // Test pass from function call
3709 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003710 v8::Global<String> unique = ReturnUnique(isolate, global);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003711 CHECK(unique == global);
3712 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3713 }
3714 CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
3715 global.Reset();
3716}
3717
3718
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003719namespace {
3720
3721class TwoPassCallbackData;
3722void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
3723void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
3724
3725
3726class TwoPassCallbackData {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003727 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003728 TwoPassCallbackData(v8::Isolate* isolate, int* instance_counter)
3729 : first_pass_called_(false),
3730 second_pass_called_(false),
3731 trigger_gc_(false),
3732 instance_counter_(instance_counter) {
3733 HandleScope scope(isolate);
3734 i::ScopedVector<char> buffer(40);
3735 i::SNPrintF(buffer, "%p", static_cast<void*>(this));
3736 auto string =
3737 v8::String::NewFromUtf8(isolate, buffer.start(),
3738 v8::NewStringType::kNormal).ToLocalChecked();
3739 cell_.Reset(isolate, string);
3740 (*instance_counter_)++;
3741 }
3742
3743 ~TwoPassCallbackData() {
3744 CHECK(first_pass_called_);
3745 CHECK(second_pass_called_);
3746 CHECK(cell_.IsEmpty());
3747 (*instance_counter_)--;
3748 }
3749
3750 void FirstPass() {
3751 CHECK(!first_pass_called_);
3752 CHECK(!second_pass_called_);
3753 CHECK(!cell_.IsEmpty());
3754 cell_.Reset();
3755 first_pass_called_ = true;
3756 }
3757
3758 void SecondPass() {
3759 CHECK(first_pass_called_);
3760 CHECK(!second_pass_called_);
3761 CHECK(cell_.IsEmpty());
3762 second_pass_called_ = true;
3763 delete this;
3764 }
3765
3766 void SetWeak() {
3767 cell_.SetWeak(this, FirstPassCallback, v8::WeakCallbackType::kParameter);
3768 }
3769
3770 void MarkTriggerGc() { trigger_gc_ = true; }
3771 bool trigger_gc() { return trigger_gc_; }
3772
3773 int* instance_counter() { return instance_counter_; }
3774
3775 private:
3776 bool first_pass_called_;
3777 bool second_pass_called_;
3778 bool trigger_gc_;
3779 v8::Global<v8::String> cell_;
3780 int* instance_counter_;
3781};
3782
3783
3784void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
3785 ApiTestFuzzer::Fuzz();
3786 bool trigger_gc = data.GetParameter()->trigger_gc();
3787 int* instance_counter = data.GetParameter()->instance_counter();
3788 data.GetParameter()->SecondPass();
3789 if (!trigger_gc) return;
3790 auto data_2 = new TwoPassCallbackData(data.GetIsolate(), instance_counter);
3791 data_2->SetWeak();
3792 CcTest::heap()->CollectAllGarbage();
3793}
3794
3795
3796void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
3797 data.GetParameter()->FirstPass();
3798 data.SetSecondPassCallback(SecondPassCallback);
3799}
3800
3801} // namespace
3802
3803
3804TEST(TwoPassPhantomCallbacks) {
3805 auto isolate = CcTest::isolate();
3806 const size_t kLength = 20;
3807 int instance_counter = 0;
3808 for (size_t i = 0; i < kLength; ++i) {
3809 auto data = new TwoPassCallbackData(isolate, &instance_counter);
3810 data->SetWeak();
3811 }
3812 CHECK_EQ(static_cast<int>(kLength), instance_counter);
3813 CcTest::heap()->CollectAllGarbage();
3814 EmptyMessageQueues(isolate);
3815 CHECK_EQ(0, instance_counter);
3816}
3817
3818
3819TEST(TwoPassPhantomCallbacksNestedGc) {
3820 auto isolate = CcTest::isolate();
3821 const size_t kLength = 20;
3822 TwoPassCallbackData* array[kLength];
3823 int instance_counter = 0;
3824 for (size_t i = 0; i < kLength; ++i) {
3825 array[i] = new TwoPassCallbackData(isolate, &instance_counter);
3826 array[i]->SetWeak();
3827 }
3828 array[5]->MarkTriggerGc();
3829 array[10]->MarkTriggerGc();
3830 array[15]->MarkTriggerGc();
3831 CHECK_EQ(static_cast<int>(kLength), instance_counter);
3832 CcTest::heap()->CollectAllGarbage();
3833 EmptyMessageQueues(isolate);
3834 CHECK_EQ(0, instance_counter);
3835}
3836
3837
3838namespace {
3839
3840void* IntKeyToVoidPointer(int key) { return reinterpret_cast<void*>(key << 1); }
3841
3842
3843Local<v8::Object> NewObjectForIntKey(
3844 v8::Isolate* isolate, const v8::Global<v8::ObjectTemplate>& templ,
3845 int key) {
3846 auto local = Local<v8::ObjectTemplate>::New(isolate, templ);
3847 auto obj = local->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
3848 obj->SetAlignedPointerInInternalField(0, IntKeyToVoidPointer(key));
3849 return obj;
3850}
3851
3852
3853template <typename K, typename V>
3854class PhantomStdMapTraits : public v8::StdMapTraits<K, V> {
3855 public:
3856 typedef typename v8::GlobalValueMap<K, V, PhantomStdMapTraits<K, V>> MapType;
3857 static const v8::PersistentContainerCallbackType kCallbackType =
3858 v8::kWeakWithInternalFields;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003859 struct WeakCallbackDataType {
3860 MapType* map;
3861 K key;
3862 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003863 static WeakCallbackDataType* WeakCallbackParameter(MapType* map, const K& key,
3864 Local<V> value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003865 WeakCallbackDataType* data = new WeakCallbackDataType;
3866 data->map = map;
3867 data->key = key;
3868 return data;
3869 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003870 static MapType* MapFromWeakCallbackInfo(
3871 const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003872 return data.GetParameter()->map;
3873 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003874 static K KeyFromWeakCallbackInfo(
3875 const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003876 return data.GetParameter()->key;
3877 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003878 static void DisposeCallbackData(WeakCallbackDataType* data) { delete data; }
3879 static void Dispose(v8::Isolate* isolate, v8::Global<V> value, K key) {
3880 CHECK_EQ(IntKeyToVoidPointer(key),
3881 v8::Object::GetAlignedPointerFromInternalField(value, 0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003882 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003883 static void OnWeakCallback(
3884 const v8::WeakCallbackInfo<WeakCallbackDataType>&) {}
3885 static void DisposeWeak(
3886 const v8::WeakCallbackInfo<WeakCallbackDataType>& info) {
3887 K key = KeyFromWeakCallbackInfo(info);
3888 CHECK_EQ(IntKeyToVoidPointer(key), info.GetInternalField(0));
3889 DisposeCallbackData(info.GetParameter());
3890 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003891};
3892
3893
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003894template <typename Map>
3895void TestGlobalValueMap() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003896 LocalContext env;
3897 v8::Isolate* isolate = env->GetIsolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003898 v8::Global<ObjectTemplate> templ;
3899 {
3900 HandleScope scope(isolate);
3901 auto t = ObjectTemplate::New(isolate);
3902 t->SetInternalFieldCount(1);
3903 templ.Reset(isolate, t);
3904 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003905 Map map(isolate);
3906 v8::internal::GlobalHandles* global_handles =
3907 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3908 int initial_handle_count = global_handles->global_handles_count();
3909 CHECK_EQ(0, static_cast<int>(map.Size()));
3910 {
3911 HandleScope scope(isolate);
3912 Local<v8::Object> obj = map.Get(7);
3913 CHECK(obj.IsEmpty());
3914 Local<v8::Object> expected = v8::Object::New(isolate);
3915 map.Set(7, expected);
3916 CHECK_EQ(1, static_cast<int>(map.Size()));
3917 obj = map.Get(7);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003918 CHECK(expected->Equals(env.local(), obj).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003919 {
3920 typename Map::PersistentValueReference ref = map.GetReference(7);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003921 CHECK(expected->Equals(env.local(), ref.NewLocal(isolate)).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003922 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003923 v8::Global<v8::Object> removed = map.Remove(7);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003924 CHECK_EQ(0, static_cast<int>(map.Size()));
3925 CHECK(expected == removed);
3926 removed = map.Remove(7);
3927 CHECK(removed.IsEmpty());
3928 map.Set(8, expected);
3929 CHECK_EQ(1, static_cast<int>(map.Size()));
3930 map.Set(8, expected);
3931 CHECK_EQ(1, static_cast<int>(map.Size()));
3932 {
3933 typename Map::PersistentValueReference ref;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003934 Local<v8::Object> expected2 = NewObjectForIntKey(isolate, templ, 8);
3935 removed = map.Set(8, v8::Global<v8::Object>(isolate, expected2), &ref);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003936 CHECK_EQ(1, static_cast<int>(map.Size()));
3937 CHECK(expected == removed);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003938 CHECK(expected2->Equals(env.local(), ref.NewLocal(isolate)).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003939 }
3940 }
3941 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3942 if (map.IsWeak()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003943 CcTest::i_isolate()->heap()->CollectAllGarbage(
3944 i::Heap::kAbortIncrementalMarkingMask);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003945 } else {
3946 map.Clear();
3947 }
3948 CHECK_EQ(0, static_cast<int>(map.Size()));
3949 CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003950 {
3951 HandleScope scope(isolate);
3952 Local<v8::Object> value = NewObjectForIntKey(isolate, templ, 9);
3953 map.Set(9, value);
3954 map.Clear();
3955 }
3956 CHECK_EQ(0, static_cast<int>(map.Size()));
3957 CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003958}
3959
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003960} // namespace
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003961
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003962
3963TEST(GlobalValueMap) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003964 // Default case, w/o weak callbacks:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003965 TestGlobalValueMap<v8::StdGlobalValueMap<int, v8::Object>>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003966
3967 // Custom traits with weak callbacks:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003968 typedef v8::GlobalValueMap<int, v8::Object,
3969 PhantomStdMapTraits<int, v8::Object>> WeakMap;
3970 TestGlobalValueMap<WeakMap>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003971}
3972
3973
3974TEST(PersistentValueVector) {
3975 LocalContext env;
3976 v8::Isolate* isolate = env->GetIsolate();
3977 v8::internal::GlobalHandles* global_handles =
3978 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3979 int handle_count = global_handles->global_handles_count();
3980 HandleScope scope(isolate);
3981
3982 v8::PersistentValueVector<v8::Object> vector(isolate);
3983
3984 Local<v8::Object> obj1 = v8::Object::New(isolate);
3985 Local<v8::Object> obj2 = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003986 v8::Global<v8::Object> obj3(isolate, v8::Object::New(isolate));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003987
3988 CHECK(vector.IsEmpty());
3989 CHECK_EQ(0, static_cast<int>(vector.Size()));
3990
3991 vector.ReserveCapacity(3);
3992 CHECK(vector.IsEmpty());
3993
3994 vector.Append(obj1);
3995 vector.Append(obj2);
3996 vector.Append(obj1);
3997 vector.Append(obj3.Pass());
3998 vector.Append(obj1);
3999
4000 CHECK(!vector.IsEmpty());
4001 CHECK_EQ(5, static_cast<int>(vector.Size()));
4002 CHECK(obj3.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004003 CHECK(obj1->Equals(env.local(), vector.Get(0)).FromJust());
4004 CHECK(obj1->Equals(env.local(), vector.Get(2)).FromJust());
4005 CHECK(obj1->Equals(env.local(), vector.Get(4)).FromJust());
4006 CHECK(obj2->Equals(env.local(), vector.Get(1)).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004007
4008 CHECK_EQ(5 + handle_count, global_handles->global_handles_count());
4009
4010 vector.Clear();
4011 CHECK(vector.IsEmpty());
4012 CHECK_EQ(0, static_cast<int>(vector.Size()));
4013 CHECK_EQ(handle_count, global_handles->global_handles_count());
4014}
4015
4016
4017THREADED_TEST(GlobalHandleUpcast) {
4018 v8::Isolate* isolate = CcTest::isolate();
4019 v8::HandleScope scope(isolate);
4020 v8::Local<String> local = v8::Local<String>::New(isolate, v8_str("str"));
4021 v8::Persistent<String> global_string(isolate, local);
4022 v8::Persistent<Value>& global_value =
4023 v8::Persistent<Value>::Cast(global_string);
4024 CHECK(v8::Local<v8::Value>::New(isolate, global_value)->IsString());
4025 CHECK(global_string == v8::Persistent<String>::Cast(global_value));
4026 global_string.Reset();
4027}
4028
4029
4030THREADED_TEST(HandleEquality) {
4031 v8::Isolate* isolate = CcTest::isolate();
4032 v8::Persistent<String> global1;
4033 v8::Persistent<String> global2;
4034 {
4035 v8::HandleScope scope(isolate);
4036 global1.Reset(isolate, v8_str("str"));
4037 global2.Reset(isolate, v8_str("str2"));
4038 }
4039 CHECK_EQ(global1 == global1, true);
4040 CHECK_EQ(global1 != global1, false);
4041 {
4042 v8::HandleScope scope(isolate);
4043 Local<String> local1 = Local<String>::New(isolate, global1);
4044 Local<String> local2 = Local<String>::New(isolate, global2);
4045
4046 CHECK_EQ(global1 == local1, true);
4047 CHECK_EQ(global1 != local1, false);
4048 CHECK_EQ(local1 == global1, true);
4049 CHECK_EQ(local1 != global1, false);
4050
4051 CHECK_EQ(global1 == local2, false);
4052 CHECK_EQ(global1 != local2, true);
4053 CHECK_EQ(local2 == global1, false);
4054 CHECK_EQ(local2 != global1, true);
4055
4056 CHECK_EQ(local1 == local2, false);
4057 CHECK_EQ(local1 != local2, true);
4058
4059 Local<String> anotherLocal1 = Local<String>::New(isolate, global1);
4060 CHECK_EQ(local1 == anotherLocal1, true);
4061 CHECK_EQ(local1 != anotherLocal1, false);
4062 }
4063 global1.Reset();
4064 global2.Reset();
4065}
4066
4067
4068THREADED_TEST(LocalHandle) {
4069 v8::HandleScope scope(CcTest::isolate());
4070 v8::Local<String> local =
4071 v8::Local<String>::New(CcTest::isolate(), v8_str("str"));
4072 CHECK_EQ(local->Length(), 3);
Steve Blocka7e24c12009-10-30 11:49:00 +00004073}
4074
4075
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004076class WeakCallCounter {
4077 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004078 explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) {}
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004079 int id() { return id_; }
4080 void increment() { number_of_weak_calls_++; }
4081 int NumberOfWeakCalls() { return number_of_weak_calls_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004082
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004083 private:
4084 int id_;
4085 int number_of_weak_calls_;
4086};
4087
4088
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004089template <typename T>
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004090struct WeakCallCounterAndPersistent {
4091 explicit WeakCallCounterAndPersistent(WeakCallCounter* counter)
4092 : counter(counter) {}
4093 WeakCallCounter* counter;
4094 v8::Persistent<T> handle;
4095};
4096
4097
4098template <typename T>
4099static void WeakPointerCallback(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004100 const v8::WeakCallbackInfo<WeakCallCounterAndPersistent<T>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004101 CHECK_EQ(1234, data.GetParameter()->counter->id());
4102 data.GetParameter()->counter->increment();
4103 data.GetParameter()->handle.Reset();
4104}
4105
4106
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004107template <typename T>
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004108static UniqueId MakeUniqueId(const Persistent<T>& p) {
4109 return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
Steve Block44f0eee2011-05-26 01:26:41 +01004110}
4111
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004112
Steve Block44f0eee2011-05-26 01:26:41 +01004113THREADED_TEST(ApiObjectGroups) {
Steve Block44f0eee2011-05-26 01:26:41 +01004114 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004115 v8::Isolate* iso = env->GetIsolate();
4116 HandleScope scope(iso);
Steve Block44f0eee2011-05-26 01:26:41 +01004117
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004118 WeakCallCounter counter(1234);
4119
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004120 WeakCallCounterAndPersistent<Value> g1s1(&counter);
4121 WeakCallCounterAndPersistent<Value> g1s2(&counter);
4122 WeakCallCounterAndPersistent<Value> g1c1(&counter);
4123 WeakCallCounterAndPersistent<Value> g2s1(&counter);
4124 WeakCallCounterAndPersistent<Value> g2s2(&counter);
4125 WeakCallCounterAndPersistent<Value> g2c1(&counter);
Steve Block44f0eee2011-05-26 01:26:41 +01004126
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004127 {
4128 HandleScope scope(iso);
4129 g1s1.handle.Reset(iso, Object::New(iso));
4130 g1s2.handle.Reset(iso, Object::New(iso));
4131 g1c1.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004132 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
4133 v8::WeakCallbackType::kParameter);
4134 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
4135 v8::WeakCallbackType::kParameter);
4136 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
4137 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004138
4139 g2s1.handle.Reset(iso, Object::New(iso));
4140 g2s2.handle.Reset(iso, Object::New(iso));
4141 g2c1.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004142 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
4143 v8::WeakCallbackType::kParameter);
4144 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
4145 v8::WeakCallbackType::kParameter);
4146 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
4147 v8::WeakCallbackType::kParameter);
Steve Block44f0eee2011-05-26 01:26:41 +01004148 }
4149
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004150 WeakCallCounterAndPersistent<Value> root(&counter);
4151 root.handle.Reset(iso, g1s1.handle); // make a root.
Steve Block44f0eee2011-05-26 01:26:41 +01004152
4153 // Connect group 1 and 2, make a cycle.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004154 {
4155 HandleScope scope(iso);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004156 CHECK(Local<Object>::New(iso, g1s2.handle.As<Object>())
4157 ->Set(env.local(), 0, Local<Value>::New(iso, g2s2.handle))
4158 .FromJust());
4159 CHECK(Local<Object>::New(iso, g2s1.handle.As<Object>())
4160 ->Set(env.local(), 0, Local<Value>::New(iso, g1s1.handle))
4161 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004162 }
Steve Block44f0eee2011-05-26 01:26:41 +01004163
4164 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004165 UniqueId id1 = MakeUniqueId(g1s1.handle);
4166 UniqueId id2 = MakeUniqueId(g2s2.handle);
4167 iso->SetObjectGroupId(g1s1.handle, id1);
4168 iso->SetObjectGroupId(g1s2.handle, id1);
4169 iso->SetReferenceFromGroup(id1, g1c1.handle);
4170 iso->SetObjectGroupId(g2s1.handle, id2);
4171 iso->SetObjectGroupId(g2s2.handle, id2);
4172 iso->SetReferenceFromGroup(id2, g2c1.handle);
Steve Block44f0eee2011-05-26 01:26:41 +01004173 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004174 // Do a single full GC, ensure incremental marking is stopped.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004175 v8::internal::Heap* heap =
4176 reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
4177 heap->CollectAllGarbage();
Steve Block44f0eee2011-05-26 01:26:41 +01004178
4179 // All object should be alive.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004180 CHECK_EQ(0, counter.NumberOfWeakCalls());
Steve Block44f0eee2011-05-26 01:26:41 +01004181
4182 // Weaken the root.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004183 root.handle.SetWeak(&root, &WeakPointerCallback,
4184 v8::WeakCallbackType::kParameter);
Steve Block44f0eee2011-05-26 01:26:41 +01004185 // But make children strong roots---all the objects (except for children)
4186 // should be collectable now.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004187 g1c1.handle.ClearWeak();
4188 g2c1.handle.ClearWeak();
Steve Block44f0eee2011-05-26 01:26:41 +01004189
4190 // Groups are deleted, rebuild groups.
4191 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004192 UniqueId id1 = MakeUniqueId(g1s1.handle);
4193 UniqueId id2 = MakeUniqueId(g2s2.handle);
4194 iso->SetObjectGroupId(g1s1.handle, id1);
4195 iso->SetObjectGroupId(g1s2.handle, id1);
4196 iso->SetReferenceFromGroup(id1, g1c1.handle);
4197 iso->SetObjectGroupId(g2s1.handle, id2);
4198 iso->SetObjectGroupId(g2s2.handle, id2);
4199 iso->SetReferenceFromGroup(id2, g2c1.handle);
Steve Block44f0eee2011-05-26 01:26:41 +01004200 }
4201
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004202 heap->CollectAllGarbage();
Steve Block44f0eee2011-05-26 01:26:41 +01004203
4204 // All objects should be gone. 5 global handles in total.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004205 CHECK_EQ(5, counter.NumberOfWeakCalls());
Steve Block44f0eee2011-05-26 01:26:41 +01004206
4207 // And now make children weak again and collect them.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004208 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
4209 v8::WeakCallbackType::kParameter);
4210 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
4211 v8::WeakCallbackType::kParameter);
Steve Block44f0eee2011-05-26 01:26:41 +01004212
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004213 heap->CollectAllGarbage();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004214 CHECK_EQ(7, counter.NumberOfWeakCalls());
Steve Block44f0eee2011-05-26 01:26:41 +01004215}
4216
4217
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004218THREADED_TEST(ApiObjectGroupsForSubtypes) {
Steve Block44f0eee2011-05-26 01:26:41 +01004219 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004220 v8::Isolate* iso = env->GetIsolate();
4221 HandleScope scope(iso);
Steve Block44f0eee2011-05-26 01:26:41 +01004222
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004223 WeakCallCounter counter(1234);
Steve Block44f0eee2011-05-26 01:26:41 +01004224
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004225 WeakCallCounterAndPersistent<Object> g1s1(&counter);
4226 WeakCallCounterAndPersistent<String> g1s2(&counter);
4227 WeakCallCounterAndPersistent<String> g1c1(&counter);
4228 WeakCallCounterAndPersistent<Object> g2s1(&counter);
4229 WeakCallCounterAndPersistent<String> g2s2(&counter);
4230 WeakCallCounterAndPersistent<String> g2c1(&counter);
Steve Block44f0eee2011-05-26 01:26:41 +01004231
4232 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004233 HandleScope scope(iso);
4234 g1s1.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004235 g1s2.handle.Reset(iso, v8_str("foo1"));
4236 g1c1.handle.Reset(iso, v8_str("foo2"));
4237 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
4238 v8::WeakCallbackType::kParameter);
4239 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
4240 v8::WeakCallbackType::kParameter);
4241 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
4242 v8::WeakCallbackType::kParameter);
Steve Block44f0eee2011-05-26 01:26:41 +01004243
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004244 g2s1.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004245 g2s2.handle.Reset(iso, v8_str("foo3"));
4246 g2c1.handle.Reset(iso, v8_str("foo4"));
4247 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
4248 v8::WeakCallbackType::kParameter);
4249 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
4250 v8::WeakCallbackType::kParameter);
4251 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
4252 v8::WeakCallbackType::kParameter);
Steve Block44f0eee2011-05-26 01:26:41 +01004253 }
4254
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004255 WeakCallCounterAndPersistent<Value> root(&counter);
4256 root.handle.Reset(iso, g1s1.handle); // make a root.
Steve Block44f0eee2011-05-26 01:26:41 +01004257
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004258 // Connect group 1 and 2, make a cycle.
Steve Block44f0eee2011-05-26 01:26:41 +01004259 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004260 HandleScope scope(iso);
4261 CHECK(Local<Object>::New(iso, g1s1.handle)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004262 ->Set(env.local(), 0, Local<Object>::New(iso, g2s1.handle))
4263 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004264 CHECK(Local<Object>::New(iso, g2s1.handle)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004265 ->Set(env.local(), 0, Local<Object>::New(iso, g1s1.handle))
4266 .FromJust());
Steve Block44f0eee2011-05-26 01:26:41 +01004267 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004268
4269 {
4270 UniqueId id1 = MakeUniqueId(g1s1.handle);
4271 UniqueId id2 = MakeUniqueId(g2s2.handle);
4272 iso->SetObjectGroupId(g1s1.handle, id1);
4273 iso->SetObjectGroupId(g1s2.handle, id1);
4274 iso->SetReference(g1s1.handle, g1c1.handle);
4275 iso->SetObjectGroupId(g2s1.handle, id2);
4276 iso->SetObjectGroupId(g2s2.handle, id2);
4277 iso->SetReferenceFromGroup(id2, g2c1.handle);
4278 }
4279 // Do a single full GC, ensure incremental marking is stopped.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004280 v8::internal::Heap* heap =
4281 reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
4282 heap->CollectAllGarbage();
Steve Block44f0eee2011-05-26 01:26:41 +01004283
4284 // All object should be alive.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004285 CHECK_EQ(0, counter.NumberOfWeakCalls());
Steve Block44f0eee2011-05-26 01:26:41 +01004286
4287 // Weaken the root.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004288 root.handle.SetWeak(&root, &WeakPointerCallback,
4289 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004290 // But make children strong roots---all the objects (except for children)
4291 // should be collectable now.
4292 g1c1.handle.ClearWeak();
4293 g2c1.handle.ClearWeak();
Steve Block44f0eee2011-05-26 01:26:41 +01004294
4295 // Groups are deleted, rebuild groups.
4296 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004297 UniqueId id1 = MakeUniqueId(g1s1.handle);
4298 UniqueId id2 = MakeUniqueId(g2s2.handle);
4299 iso->SetObjectGroupId(g1s1.handle, id1);
4300 iso->SetObjectGroupId(g1s2.handle, id1);
4301 iso->SetReference(g1s1.handle, g1c1.handle);
4302 iso->SetObjectGroupId(g2s1.handle, id2);
4303 iso->SetObjectGroupId(g2s2.handle, id2);
4304 iso->SetReferenceFromGroup(id2, g2c1.handle);
Steve Block44f0eee2011-05-26 01:26:41 +01004305 }
4306
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004307 heap->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004308
4309 // All objects should be gone. 5 global handles in total.
4310 CHECK_EQ(5, counter.NumberOfWeakCalls());
4311
4312 // And now make children weak again and collect them.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004313 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
4314 v8::WeakCallbackType::kParameter);
4315 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
4316 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004317
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004318 heap->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004319 CHECK_EQ(7, counter.NumberOfWeakCalls());
4320}
4321
4322
4323THREADED_TEST(ApiObjectGroupsCycle) {
4324 LocalContext env;
4325 v8::Isolate* iso = env->GetIsolate();
4326 HandleScope scope(iso);
4327
4328 WeakCallCounter counter(1234);
4329
4330 WeakCallCounterAndPersistent<Value> g1s1(&counter);
4331 WeakCallCounterAndPersistent<Value> g1s2(&counter);
4332 WeakCallCounterAndPersistent<Value> g2s1(&counter);
4333 WeakCallCounterAndPersistent<Value> g2s2(&counter);
4334 WeakCallCounterAndPersistent<Value> g3s1(&counter);
4335 WeakCallCounterAndPersistent<Value> g3s2(&counter);
4336 WeakCallCounterAndPersistent<Value> g4s1(&counter);
4337 WeakCallCounterAndPersistent<Value> g4s2(&counter);
4338
4339 {
4340 HandleScope scope(iso);
4341 g1s1.handle.Reset(iso, Object::New(iso));
4342 g1s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004343 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
4344 v8::WeakCallbackType::kParameter);
4345 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
4346 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004347 CHECK(g1s1.handle.IsWeak());
4348 CHECK(g1s2.handle.IsWeak());
4349
4350 g2s1.handle.Reset(iso, Object::New(iso));
4351 g2s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004352 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
4353 v8::WeakCallbackType::kParameter);
4354 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
4355 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004356 CHECK(g2s1.handle.IsWeak());
4357 CHECK(g2s2.handle.IsWeak());
4358
4359 g3s1.handle.Reset(iso, Object::New(iso));
4360 g3s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004361 g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback,
4362 v8::WeakCallbackType::kParameter);
4363 g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback,
4364 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004365 CHECK(g3s1.handle.IsWeak());
4366 CHECK(g3s2.handle.IsWeak());
4367
4368 g4s1.handle.Reset(iso, Object::New(iso));
4369 g4s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004370 g4s1.handle.SetWeak(&g4s1, &WeakPointerCallback,
4371 v8::WeakCallbackType::kParameter);
4372 g4s2.handle.SetWeak(&g4s2, &WeakPointerCallback,
4373 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004374 CHECK(g4s1.handle.IsWeak());
4375 CHECK(g4s2.handle.IsWeak());
4376 }
4377
4378 WeakCallCounterAndPersistent<Value> root(&counter);
4379 root.handle.Reset(iso, g1s1.handle); // make a root.
4380
4381 // Connect groups. We're building the following cycle:
4382 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
4383 // groups.
4384 {
4385 UniqueId id1 = MakeUniqueId(g1s1.handle);
4386 UniqueId id2 = MakeUniqueId(g2s1.handle);
4387 UniqueId id3 = MakeUniqueId(g3s1.handle);
4388 UniqueId id4 = MakeUniqueId(g4s1.handle);
4389 iso->SetObjectGroupId(g1s1.handle, id1);
4390 iso->SetObjectGroupId(g1s2.handle, id1);
4391 iso->SetReferenceFromGroup(id1, g2s1.handle);
4392 iso->SetObjectGroupId(g2s1.handle, id2);
4393 iso->SetObjectGroupId(g2s2.handle, id2);
4394 iso->SetReferenceFromGroup(id2, g3s1.handle);
4395 iso->SetObjectGroupId(g3s1.handle, id3);
4396 iso->SetObjectGroupId(g3s2.handle, id3);
4397 iso->SetReferenceFromGroup(id3, g4s1.handle);
4398 iso->SetObjectGroupId(g4s1.handle, id4);
4399 iso->SetObjectGroupId(g4s2.handle, id4);
4400 iso->SetReferenceFromGroup(id4, g1s1.handle);
4401 }
4402 // Do a single full GC
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004403 v8::internal::Heap* heap =
4404 reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
4405 heap->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004406
4407 // All object should be alive.
4408 CHECK_EQ(0, counter.NumberOfWeakCalls());
4409
4410 // Weaken the root.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004411 root.handle.SetWeak(&root, &WeakPointerCallback,
4412 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004413
4414 // Groups are deleted, rebuild groups.
4415 {
4416 UniqueId id1 = MakeUniqueId(g1s1.handle);
4417 UniqueId id2 = MakeUniqueId(g2s1.handle);
4418 UniqueId id3 = MakeUniqueId(g3s1.handle);
4419 UniqueId id4 = MakeUniqueId(g4s1.handle);
4420 iso->SetObjectGroupId(g1s1.handle, id1);
4421 iso->SetObjectGroupId(g1s2.handle, id1);
4422 iso->SetReferenceFromGroup(id1, g2s1.handle);
4423 iso->SetObjectGroupId(g2s1.handle, id2);
4424 iso->SetObjectGroupId(g2s2.handle, id2);
4425 iso->SetReferenceFromGroup(id2, g3s1.handle);
4426 iso->SetObjectGroupId(g3s1.handle, id3);
4427 iso->SetObjectGroupId(g3s2.handle, id3);
4428 iso->SetReferenceFromGroup(id3, g4s1.handle);
4429 iso->SetObjectGroupId(g4s1.handle, id4);
4430 iso->SetObjectGroupId(g4s2.handle, id4);
4431 iso->SetReferenceFromGroup(id4, g1s1.handle);
4432 }
4433
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004434 heap->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004435
4436 // All objects should be gone. 9 global handles in total.
4437 CHECK_EQ(9, counter.NumberOfWeakCalls());
4438}
4439
4440
4441// TODO(mstarzinger): This should be a THREADED_TEST but causes failures
4442// on the buildbots, so was made non-threaded for the time being.
4443TEST(ApiObjectGroupsCycleForScavenger) {
4444 i::FLAG_stress_compaction = false;
4445 i::FLAG_gc_global = false;
4446 LocalContext env;
4447 v8::Isolate* iso = env->GetIsolate();
4448 HandleScope scope(iso);
4449
4450 WeakCallCounter counter(1234);
4451
4452 WeakCallCounterAndPersistent<Value> g1s1(&counter);
4453 WeakCallCounterAndPersistent<Value> g1s2(&counter);
4454 WeakCallCounterAndPersistent<Value> g2s1(&counter);
4455 WeakCallCounterAndPersistent<Value> g2s2(&counter);
4456 WeakCallCounterAndPersistent<Value> g3s1(&counter);
4457 WeakCallCounterAndPersistent<Value> g3s2(&counter);
4458
4459 {
4460 HandleScope scope(iso);
4461 g1s1.handle.Reset(iso, Object::New(iso));
4462 g1s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004463 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
4464 v8::WeakCallbackType::kParameter);
4465 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
4466 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004467
4468 g2s1.handle.Reset(iso, Object::New(iso));
4469 g2s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004470 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
4471 v8::WeakCallbackType::kParameter);
4472 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
4473 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004474
4475 g3s1.handle.Reset(iso, Object::New(iso));
4476 g3s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004477 g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback,
4478 v8::WeakCallbackType::kParameter);
4479 g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback,
4480 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004481 }
4482
4483 // Make a root.
4484 WeakCallCounterAndPersistent<Value> root(&counter);
4485 root.handle.Reset(iso, g1s1.handle);
4486 root.handle.MarkPartiallyDependent();
4487
4488 // Connect groups. We're building the following cycle:
4489 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
4490 // groups.
4491 {
4492 HandleScope handle_scope(iso);
4493 g1s1.handle.MarkPartiallyDependent();
4494 g1s2.handle.MarkPartiallyDependent();
4495 g2s1.handle.MarkPartiallyDependent();
4496 g2s2.handle.MarkPartiallyDependent();
4497 g3s1.handle.MarkPartiallyDependent();
4498 g3s2.handle.MarkPartiallyDependent();
4499 iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
4500 iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004501 Local<Object>::New(iso, g1s1.handle.As<Object>())
4502 ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g2s1.handle))
4503 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004504 iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
4505 iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004506 Local<Object>::New(iso, g2s1.handle.As<Object>())
4507 ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g3s1.handle))
4508 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004509 iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
4510 iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004511 Local<Object>::New(iso, g3s1.handle.As<Object>())
4512 ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g1s1.handle))
4513 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004514 }
4515
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004516 v8::internal::Heap* heap =
4517 reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
4518 heap->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004519
4520 // All objects should be alive.
4521 CHECK_EQ(0, counter.NumberOfWeakCalls());
4522
4523 // Weaken the root.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004524 root.handle.SetWeak(&root, &WeakPointerCallback,
4525 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004526 root.handle.MarkPartiallyDependent();
4527
4528 // Groups are deleted, rebuild groups.
4529 {
4530 HandleScope handle_scope(iso);
4531 g1s1.handle.MarkPartiallyDependent();
4532 g1s2.handle.MarkPartiallyDependent();
4533 g2s1.handle.MarkPartiallyDependent();
4534 g2s2.handle.MarkPartiallyDependent();
4535 g3s1.handle.MarkPartiallyDependent();
4536 g3s2.handle.MarkPartiallyDependent();
4537 iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
4538 iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004539 Local<Object>::New(iso, g1s1.handle.As<Object>())
4540 ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g2s1.handle))
4541 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004542 iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
4543 iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004544 Local<Object>::New(iso, g2s1.handle.As<Object>())
4545 ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g3s1.handle))
4546 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004547 iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
4548 iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004549 Local<Object>::New(iso, g3s1.handle.As<Object>())
4550 ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g1s1.handle))
4551 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004552 }
4553
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004554 heap->CollectAllGarbage();
Steve Block44f0eee2011-05-26 01:26:41 +01004555
4556 // All objects should be gone. 7 global handles in total.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004557 CHECK_EQ(7, counter.NumberOfWeakCalls());
Steve Block44f0eee2011-05-26 01:26:41 +01004558}
4559
4560
Steve Blocka7e24c12009-10-30 11:49:00 +00004561THREADED_TEST(ScriptException) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004562 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004563 v8::HandleScope scope(env->GetIsolate());
4564 Local<Script> script = v8_compile("throw 'panama!';");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004565 v8::TryCatch try_catch(env->GetIsolate());
4566 v8::MaybeLocal<Value> result = script->Run(env.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00004567 CHECK(result.IsEmpty());
4568 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004569 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004570 CHECK_EQ(0, strcmp(*exception_value, "panama!"));
Steve Blocka7e24c12009-10-30 11:49:00 +00004571}
4572
4573
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004574TEST(TryCatchCustomException) {
4575 LocalContext env;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004576 v8::Isolate* isolate = env->GetIsolate();
4577 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004578 v8::TryCatch try_catch(isolate);
4579 CompileRun(
4580 "function CustomError() { this.a = 'b'; }"
4581 "(function f() { throw new CustomError(); })();");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004582 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004583 CHECK(try_catch.Exception()
4584 ->ToObject(env.local())
4585 .ToLocalChecked()
4586 ->Get(env.local(), v8_str("a"))
4587 .ToLocalChecked()
4588 ->Equals(env.local(), v8_str("b"))
4589 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004590}
4591
4592
Steve Blocka7e24c12009-10-30 11:49:00 +00004593bool message_received;
4594
4595
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004596static void check_message_0(v8::Local<v8::Message> message,
4597 v8::Local<Value> data) {
4598 CHECK_EQ(5.76, data->NumberValue(CcTest::isolate()->GetCurrentContext())
4599 .FromJust());
4600 CHECK_EQ(6.75, message->GetScriptOrigin()
4601 .ResourceName()
4602 ->NumberValue(CcTest::isolate()->GetCurrentContext())
4603 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004604 CHECK(!message->IsSharedCrossOrigin());
Steve Blocka7e24c12009-10-30 11:49:00 +00004605 message_received = true;
4606}
4607
4608
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004609THREADED_TEST(MessageHandler0) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004610 message_received = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004611 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00004612 CHECK(!message_received);
Steve Blocka7e24c12009-10-30 11:49:00 +00004613 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004614 CcTest::isolate()->AddMessageListener(check_message_0, v8_num(5.76));
4615 v8::Local<v8::Script> script = CompileWithOrigin("throw 'error'", "6.75");
4616 CHECK(script->Run(context.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00004617 CHECK(message_received);
4618 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004619 CcTest::isolate()->RemoveMessageListeners(check_message_0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004620}
4621
4622
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004623static void check_message_1(v8::Local<v8::Message> message,
4624 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004625 CHECK(data->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004626 CHECK_EQ(1337,
4627 data->Int32Value(CcTest::isolate()->GetCurrentContext()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004628 CHECK(!message->IsSharedCrossOrigin());
4629 message_received = true;
4630}
4631
4632
4633TEST(MessageHandler1) {
4634 message_received = false;
4635 v8::HandleScope scope(CcTest::isolate());
4636 CHECK(!message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004637 CcTest::isolate()->AddMessageListener(check_message_1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004638 LocalContext context;
4639 CompileRun("throw 1337;");
4640 CHECK(message_received);
4641 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004642 CcTest::isolate()->RemoveMessageListeners(check_message_1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004643}
4644
4645
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004646static void check_message_2(v8::Local<v8::Message> message,
4647 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004648 LocalContext context;
4649 CHECK(data->IsObject());
4650 v8::Local<v8::Value> hidden_property =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004651 v8::Object::Cast(*data)
4652 ->GetPrivate(
4653 context.local(),
4654 v8::Private::ForApi(CcTest::isolate(), v8_str("hidden key")))
4655 .ToLocalChecked();
4656 CHECK(v8_str("hidden value")
4657 ->Equals(context.local(), hidden_property)
4658 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004659 CHECK(!message->IsSharedCrossOrigin());
4660 message_received = true;
4661}
4662
4663
4664TEST(MessageHandler2) {
4665 message_received = false;
4666 v8::HandleScope scope(CcTest::isolate());
4667 CHECK(!message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004668 CcTest::isolate()->AddMessageListener(check_message_2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004669 LocalContext context;
4670 v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004671 v8::Object::Cast(*error)
4672 ->SetPrivate(context.local(),
4673 v8::Private::ForApi(CcTest::isolate(), v8_str("hidden key")),
4674 v8_str("hidden value"))
4675 .FromJust();
4676 CHECK(context->Global()
4677 ->Set(context.local(), v8_str("error"), error)
4678 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004679 CompileRun("throw error;");
4680 CHECK(message_received);
4681 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004682 CcTest::isolate()->RemoveMessageListeners(check_message_2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004683}
4684
4685
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004686static void check_message_3(v8::Local<v8::Message> message,
4687 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004688 CHECK(message->IsSharedCrossOrigin());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004689 CHECK(message->GetScriptOrigin().Options().IsSharedCrossOrigin());
4690 CHECK(message->GetScriptOrigin().Options().IsEmbedderDebugScript());
4691 CHECK(message->GetScriptOrigin().Options().IsOpaque());
4692 CHECK_EQ(6.75, message->GetScriptOrigin()
4693 .ResourceName()
4694 ->NumberValue(CcTest::isolate()->GetCurrentContext())
4695 .FromJust());
4696 CHECK_EQ(7.40, message->GetScriptOrigin()
4697 .SourceMapUrl()
4698 ->NumberValue(CcTest::isolate()->GetCurrentContext())
4699 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004700 message_received = true;
4701}
4702
4703
4704TEST(MessageHandler3) {
4705 message_received = false;
4706 v8::Isolate* isolate = CcTest::isolate();
4707 v8::HandleScope scope(isolate);
4708 CHECK(!message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004709 isolate->AddMessageListener(check_message_3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004710 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004711 v8::ScriptOrigin origin = v8::ScriptOrigin(
4712 v8_str("6.75"), v8::Integer::New(isolate, 1),
4713 v8::Integer::New(isolate, 2), v8::True(isolate), Local<v8::Integer>(),
4714 v8::True(isolate), v8_str("7.40"), v8::True(isolate));
4715 v8::Local<v8::Script> script =
4716 Script::Compile(context.local(), v8_str("throw 'error'"), &origin)
4717 .ToLocalChecked();
4718 CHECK(script->Run(context.local()).IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004719 CHECK(message_received);
4720 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004721 isolate->RemoveMessageListeners(check_message_3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004722}
4723
4724
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004725static void check_message_4(v8::Local<v8::Message> message,
4726 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004727 CHECK(!message->IsSharedCrossOrigin());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004728 CHECK_EQ(6.75, message->GetScriptOrigin()
4729 .ResourceName()
4730 ->NumberValue(CcTest::isolate()->GetCurrentContext())
4731 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004732 message_received = true;
4733}
4734
4735
4736TEST(MessageHandler4) {
4737 message_received = false;
4738 v8::Isolate* isolate = CcTest::isolate();
4739 v8::HandleScope scope(isolate);
4740 CHECK(!message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004741 isolate->AddMessageListener(check_message_4);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004742 LocalContext context;
4743 v8::ScriptOrigin origin =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004744 v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
4745 v8::Integer::New(isolate, 2), v8::False(isolate));
4746 v8::Local<v8::Script> script =
4747 Script::Compile(context.local(), v8_str("throw 'error'"), &origin)
4748 .ToLocalChecked();
4749 CHECK(script->Run(context.local()).IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004750 CHECK(message_received);
4751 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004752 isolate->RemoveMessageListeners(check_message_4);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004753}
4754
4755
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004756static void check_message_5a(v8::Local<v8::Message> message,
4757 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004758 CHECK(message->IsSharedCrossOrigin());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004759 CHECK_EQ(6.75, message->GetScriptOrigin()
4760 .ResourceName()
4761 ->NumberValue(CcTest::isolate()->GetCurrentContext())
4762 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004763 message_received = true;
4764}
4765
4766
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004767static void check_message_5b(v8::Local<v8::Message> message,
4768 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004769 CHECK(!message->IsSharedCrossOrigin());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004770 CHECK_EQ(6.75, message->GetScriptOrigin()
4771 .ResourceName()
4772 ->NumberValue(CcTest::isolate()->GetCurrentContext())
4773 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004774 message_received = true;
4775}
4776
4777
4778TEST(MessageHandler5) {
4779 message_received = false;
4780 v8::Isolate* isolate = CcTest::isolate();
4781 v8::HandleScope scope(isolate);
4782 CHECK(!message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004783 isolate->AddMessageListener(check_message_5a);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004784 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004785 v8::ScriptOrigin origin1 =
4786 v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
4787 v8::Integer::New(isolate, 2), v8::True(isolate));
4788 v8::Local<v8::Script> script =
4789 Script::Compile(context.local(), v8_str("throw 'error'"), &origin1)
4790 .ToLocalChecked();
4791 CHECK(script->Run(context.local()).IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004792 CHECK(message_received);
4793 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004794 isolate->RemoveMessageListeners(check_message_5a);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004795
4796 message_received = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004797 isolate->AddMessageListener(check_message_5b);
4798 v8::ScriptOrigin origin2 =
4799 v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
4800 v8::Integer::New(isolate, 2), v8::False(isolate));
4801 script = Script::Compile(context.local(), v8_str("throw 'error'"), &origin2)
4802 .ToLocalChecked();
4803 CHECK(script->Run(context.local()).IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004804 CHECK(message_received);
4805 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004806 isolate->RemoveMessageListeners(check_message_5b);
4807}
4808
4809
4810TEST(NativeWeakMap) {
4811 v8::Isolate* isolate = CcTest::isolate();
4812 HandleScope scope(isolate);
4813 Local<v8::NativeWeakMap> weak_map(v8::NativeWeakMap::New(isolate));
4814 CHECK(!weak_map.IsEmpty());
4815
4816 LocalContext env;
4817 Local<Object> value = v8::Object::New(isolate);
4818
4819 Local<Object> local1 = v8::Object::New(isolate);
4820 CHECK(!weak_map->Has(local1));
4821 CHECK(weak_map->Get(local1)->IsUndefined());
4822 weak_map->Set(local1, value);
4823 CHECK(weak_map->Has(local1));
4824 CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
4825
4826 WeakCallCounter counter(1234);
4827 WeakCallCounterAndPersistent<Value> o1(&counter);
4828 WeakCallCounterAndPersistent<Value> o2(&counter);
4829 WeakCallCounterAndPersistent<Value> s1(&counter);
4830 {
4831 HandleScope scope(isolate);
4832 Local<v8::Object> obj1 = v8::Object::New(isolate);
4833 Local<v8::Object> obj2 = v8::Object::New(isolate);
4834 Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
4835
4836 weak_map->Set(obj1, value);
4837 weak_map->Set(obj2, value);
4838 weak_map->Set(sym1, value);
4839
4840 o1.handle.Reset(isolate, obj1);
4841 o2.handle.Reset(isolate, obj2);
4842 s1.handle.Reset(isolate, sym1);
4843
4844 CHECK(weak_map->Has(local1));
4845 CHECK(weak_map->Has(obj1));
4846 CHECK(weak_map->Has(obj2));
4847 CHECK(weak_map->Has(sym1));
4848
4849 CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
4850 CHECK(value->Equals(env.local(), weak_map->Get(obj1)).FromJust());
4851 CHECK(value->Equals(env.local(), weak_map->Get(obj2)).FromJust());
4852 CHECK(value->Equals(env.local(), weak_map->Get(sym1)).FromJust());
4853 }
4854 CcTest::heap()->CollectAllGarbage();
4855 {
4856 HandleScope scope(isolate);
4857 CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
4858 CHECK(value->Equals(env.local(),
4859 weak_map->Get(Local<Value>::New(isolate, o1.handle)))
4860 .FromJust());
4861 CHECK(value->Equals(env.local(),
4862 weak_map->Get(Local<Value>::New(isolate, o2.handle)))
4863 .FromJust());
4864 CHECK(value->Equals(env.local(),
4865 weak_map->Get(Local<Value>::New(isolate, s1.handle)))
4866 .FromJust());
4867 }
4868
4869 o1.handle.SetWeak(&o1, &WeakPointerCallback,
4870 v8::WeakCallbackType::kParameter);
4871 o2.handle.SetWeak(&o2, &WeakPointerCallback,
4872 v8::WeakCallbackType::kParameter);
4873 s1.handle.SetWeak(&s1, &WeakPointerCallback,
4874 v8::WeakCallbackType::kParameter);
4875
4876 CcTest::heap()->CollectAllGarbage();
4877 CHECK_EQ(3, counter.NumberOfWeakCalls());
4878
4879 CHECK(o1.handle.IsEmpty());
4880 CHECK(o2.handle.IsEmpty());
4881 CHECK(s1.handle.IsEmpty());
4882
4883 CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
4884 CHECK(weak_map->Delete(local1));
4885 CHECK(!weak_map->Has(local1));
4886 CHECK(weak_map->Get(local1)->IsUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +00004887}
4888
4889
4890THREADED_TEST(GetSetProperty) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004891 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004892 v8::Isolate* isolate = context->GetIsolate();
4893 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004894 CHECK(context->Global()
4895 ->Set(context.local(), v8_str("foo"), v8_num(14))
4896 .FromJust());
4897 CHECK(context->Global()
4898 ->Set(context.local(), v8_str("12"), v8_num(92))
4899 .FromJust());
4900 CHECK(context->Global()
4901 ->Set(context.local(), v8::Integer::New(isolate, 16), v8_num(32))
4902 .FromJust());
4903 CHECK(context->Global()
4904 ->Set(context.local(), v8_num(13), v8_num(56))
4905 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004906 Local<Value> foo = CompileRun("this.foo");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004907 CHECK_EQ(14, foo->Int32Value(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004908 Local<Value> twelve = CompileRun("this[12]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004909 CHECK_EQ(92, twelve->Int32Value(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004910 Local<Value> sixteen = CompileRun("this[16]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004911 CHECK_EQ(32, sixteen->Int32Value(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004912 Local<Value> thirteen = CompileRun("this[13]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004913 CHECK_EQ(56, thirteen->Int32Value(context.local()).FromJust());
4914 CHECK_EQ(92, context->Global()
4915 ->Get(context.local(), v8::Integer::New(isolate, 12))
4916 .ToLocalChecked()
4917 ->Int32Value(context.local())
4918 .FromJust());
4919 CHECK_EQ(92, context->Global()
4920 ->Get(context.local(), v8_str("12"))
4921 .ToLocalChecked()
4922 ->Int32Value(context.local())
4923 .FromJust());
4924 CHECK_EQ(92, context->Global()
4925 ->Get(context.local(), v8_num(12))
4926 .ToLocalChecked()
4927 ->Int32Value(context.local())
4928 .FromJust());
4929 CHECK_EQ(32, context->Global()
4930 ->Get(context.local(), v8::Integer::New(isolate, 16))
4931 .ToLocalChecked()
4932 ->Int32Value(context.local())
4933 .FromJust());
4934 CHECK_EQ(32, context->Global()
4935 ->Get(context.local(), v8_str("16"))
4936 .ToLocalChecked()
4937 ->Int32Value(context.local())
4938 .FromJust());
4939 CHECK_EQ(32, context->Global()
4940 ->Get(context.local(), v8_num(16))
4941 .ToLocalChecked()
4942 ->Int32Value(context.local())
4943 .FromJust());
4944 CHECK_EQ(56, context->Global()
4945 ->Get(context.local(), v8::Integer::New(isolate, 13))
4946 .ToLocalChecked()
4947 ->Int32Value(context.local())
4948 .FromJust());
4949 CHECK_EQ(56, context->Global()
4950 ->Get(context.local(), v8_str("13"))
4951 .ToLocalChecked()
4952 ->Int32Value(context.local())
4953 .FromJust());
4954 CHECK_EQ(56, context->Global()
4955 ->Get(context.local(), v8_num(13))
4956 .ToLocalChecked()
4957 ->Int32Value(context.local())
4958 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004959}
4960
4961
4962THREADED_TEST(PropertyAttributes) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004963 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004964 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004965 // none
4966 Local<String> prop = v8_str("none");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004967 CHECK(context->Global()->Set(context.local(), prop, v8_num(7)).FromJust());
4968 CHECK_EQ(v8::None, context->Global()
4969 ->GetPropertyAttributes(context.local(), prop)
4970 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004971 // read-only
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004972 prop = v8_str("read_only");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004973 context->Global()
4974 ->DefineOwnProperty(context.local(), prop, v8_num(7), v8::ReadOnly)
4975 .FromJust();
4976 CHECK_EQ(7, context->Global()
4977 ->Get(context.local(), prop)
4978 .ToLocalChecked()
4979 ->Int32Value(context.local())
4980 .FromJust());
4981 CHECK_EQ(v8::ReadOnly, context->Global()
4982 ->GetPropertyAttributes(context.local(), prop)
4983 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004984 CompileRun("read_only = 9");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004985 CHECK_EQ(7, context->Global()
4986 ->Get(context.local(), prop)
4987 .ToLocalChecked()
4988 ->Int32Value(context.local())
4989 .FromJust());
4990 CHECK(context->Global()->Set(context.local(), prop, v8_num(10)).FromJust());
4991 CHECK_EQ(7, context->Global()
4992 ->Get(context.local(), prop)
4993 .ToLocalChecked()
4994 ->Int32Value(context.local())
4995 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004996 // dont-delete
4997 prop = v8_str("dont_delete");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004998 context->Global()
4999 ->DefineOwnProperty(context.local(), prop, v8_num(13), v8::DontDelete)
5000 .FromJust();
5001 CHECK_EQ(13, context->Global()
5002 ->Get(context.local(), prop)
5003 .ToLocalChecked()
5004 ->Int32Value(context.local())
5005 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005006 CompileRun("delete dont_delete");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005007 CHECK_EQ(13, context->Global()
5008 ->Get(context.local(), prop)
5009 .ToLocalChecked()
5010 ->Int32Value(context.local())
5011 .FromJust());
5012 CHECK_EQ(v8::DontDelete, context->Global()
5013 ->GetPropertyAttributes(context.local(), prop)
5014 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005015 // dont-enum
5016 prop = v8_str("dont_enum");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005017 context->Global()
5018 ->DefineOwnProperty(context.local(), prop, v8_num(28), v8::DontEnum)
5019 .FromJust();
5020 CHECK_EQ(v8::DontEnum, context->Global()
5021 ->GetPropertyAttributes(context.local(), prop)
5022 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005023 // absent
5024 prop = v8_str("absent");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005025 CHECK_EQ(v8::None, context->Global()
5026 ->GetPropertyAttributes(context.local(), prop)
5027 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005028 Local<Value> fake_prop = v8_num(1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005029 CHECK_EQ(v8::None, context->Global()
5030 ->GetPropertyAttributes(context.local(), fake_prop)
5031 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005032 // exception
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005033 TryCatch try_catch(context->GetIsolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005034 Local<Value> exception =
5035 CompileRun("({ toString: function() { throw 'exception';} })");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005036 CHECK(context->Global()
5037 ->GetPropertyAttributes(context.local(), exception)
5038 .IsNothing());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005039 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005040 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005041 CHECK_EQ(0, strcmp("exception", *exception_value));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005042 try_catch.Reset();
Steve Blocka7e24c12009-10-30 11:49:00 +00005043}
5044
5045
5046THREADED_TEST(Array) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005047 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005048 v8::HandleScope scope(context->GetIsolate());
5049 Local<v8::Array> array = v8::Array::New(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005050 CHECK_EQ(0u, array->Length());
5051 CHECK(array->Get(context.local(), 0).ToLocalChecked()->IsUndefined());
5052 CHECK(!array->Has(context.local(), 0).FromJust());
5053 CHECK(array->Get(context.local(), 100).ToLocalChecked()->IsUndefined());
5054 CHECK(!array->Has(context.local(), 100).FromJust());
5055 CHECK(array->Set(context.local(), 2, v8_num(7)).FromJust());
5056 CHECK_EQ(3u, array->Length());
5057 CHECK(!array->Has(context.local(), 0).FromJust());
5058 CHECK(!array->Has(context.local(), 1).FromJust());
5059 CHECK(array->Has(context.local(), 2).FromJust());
5060 CHECK_EQ(7, array->Get(context.local(), 2)
5061 .ToLocalChecked()
5062 ->Int32Value(context.local())
5063 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005064 Local<Value> obj = CompileRun("[1, 2, 3]");
Steve Block6ded16b2010-05-10 14:33:55 +01005065 Local<v8::Array> arr = obj.As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005066 CHECK_EQ(3u, arr->Length());
5067 CHECK_EQ(1, arr->Get(context.local(), 0)
5068 .ToLocalChecked()
5069 ->Int32Value(context.local())
5070 .FromJust());
5071 CHECK_EQ(2, arr->Get(context.local(), 1)
5072 .ToLocalChecked()
5073 ->Int32Value(context.local())
5074 .FromJust());
5075 CHECK_EQ(3, arr->Get(context.local(), 2)
5076 .ToLocalChecked()
5077 ->Int32Value(context.local())
5078 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005079 array = v8::Array::New(context->GetIsolate(), 27);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005080 CHECK_EQ(27u, array->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005081 array = v8::Array::New(context->GetIsolate(), -27);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005082 CHECK_EQ(0u, array->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +00005083}
5084
5085
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005086void HandleF(const v8::FunctionCallbackInfo<v8::Value>& args) {
5087 v8::EscapableHandleScope scope(args.GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00005088 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005089 Local<v8::Array> result = v8::Array::New(args.GetIsolate(), args.Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005090 for (int i = 0; i < args.Length(); i++) {
5091 CHECK(result->Set(CcTest::isolate()->GetCurrentContext(), i, args[i])
5092 .FromJust());
5093 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005094 args.GetReturnValue().Set(scope.Escape(result));
Steve Blocka7e24c12009-10-30 11:49:00 +00005095}
5096
5097
5098THREADED_TEST(Vector) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005099 v8::Isolate* isolate = CcTest::isolate();
5100 v8::HandleScope scope(isolate);
5101 Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
5102 global->Set(v8_str("f"), v8::FunctionTemplate::New(isolate, HandleF));
Steve Blocka7e24c12009-10-30 11:49:00 +00005103 LocalContext context(0, global);
5104
5105 const char* fun = "f()";
Steve Block6ded16b2010-05-10 14:33:55 +01005106 Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005107 CHECK_EQ(0u, a0->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +00005108
5109 const char* fun2 = "f(11)";
Steve Block6ded16b2010-05-10 14:33:55 +01005110 Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005111 CHECK_EQ(1u, a1->Length());
5112 CHECK_EQ(11, a1->Get(context.local(), 0)
5113 .ToLocalChecked()
5114 ->Int32Value(context.local())
5115 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005116
5117 const char* fun3 = "f(12, 13)";
Steve Block6ded16b2010-05-10 14:33:55 +01005118 Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005119 CHECK_EQ(2u, a2->Length());
5120 CHECK_EQ(12, a2->Get(context.local(), 0)
5121 .ToLocalChecked()
5122 ->Int32Value(context.local())
5123 .FromJust());
5124 CHECK_EQ(13, a2->Get(context.local(), 1)
5125 .ToLocalChecked()
5126 ->Int32Value(context.local())
5127 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005128
5129 const char* fun4 = "f(14, 15, 16)";
Steve Block6ded16b2010-05-10 14:33:55 +01005130 Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005131 CHECK_EQ(3u, a3->Length());
5132 CHECK_EQ(14, a3->Get(context.local(), 0)
5133 .ToLocalChecked()
5134 ->Int32Value(context.local())
5135 .FromJust());
5136 CHECK_EQ(15, a3->Get(context.local(), 1)
5137 .ToLocalChecked()
5138 ->Int32Value(context.local())
5139 .FromJust());
5140 CHECK_EQ(16, a3->Get(context.local(), 2)
5141 .ToLocalChecked()
5142 ->Int32Value(context.local())
5143 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005144
5145 const char* fun5 = "f(17, 18, 19, 20)";
Steve Block6ded16b2010-05-10 14:33:55 +01005146 Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005147 CHECK_EQ(4u, a4->Length());
5148 CHECK_EQ(17, a4->Get(context.local(), 0)
5149 .ToLocalChecked()
5150 ->Int32Value(context.local())
5151 .FromJust());
5152 CHECK_EQ(18, a4->Get(context.local(), 1)
5153 .ToLocalChecked()
5154 ->Int32Value(context.local())
5155 .FromJust());
5156 CHECK_EQ(19, a4->Get(context.local(), 2)
5157 .ToLocalChecked()
5158 ->Int32Value(context.local())
5159 .FromJust());
5160 CHECK_EQ(20, a4->Get(context.local(), 3)
5161 .ToLocalChecked()
5162 ->Int32Value(context.local())
5163 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005164}
5165
5166
5167THREADED_TEST(FunctionCall) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005168 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005169 v8::Isolate* isolate = context->GetIsolate();
5170 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005171 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005172 "function Foo() {"
5173 " var result = [];"
5174 " for (var i = 0; i < arguments.length; i++) {"
5175 " result.push(arguments[i]);"
5176 " }"
5177 " return result;"
5178 "}"
5179 "function ReturnThisSloppy() {"
5180 " return this;"
5181 "}"
5182 "function ReturnThisStrict() {"
5183 " 'use strict';"
5184 " return this;"
5185 "}");
5186 Local<Function> Foo = Local<Function>::Cast(
5187 context->Global()->Get(context.local(), v8_str("Foo")).ToLocalChecked());
5188 Local<Function> ReturnThisSloppy = Local<Function>::Cast(
5189 context->Global()
5190 ->Get(context.local(), v8_str("ReturnThisSloppy"))
5191 .ToLocalChecked());
5192 Local<Function> ReturnThisStrict = Local<Function>::Cast(
5193 context->Global()
5194 ->Get(context.local(), v8_str("ReturnThisStrict"))
5195 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00005196
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005197 v8::Local<Value>* args0 = NULL;
5198 Local<v8::Array> a0 = Local<v8::Array>::Cast(
5199 Foo->Call(context.local(), Foo, 0, args0).ToLocalChecked());
5200 CHECK_EQ(0u, a0->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +00005201
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005202 v8::Local<Value> args1[] = {v8_num(1.1)};
5203 Local<v8::Array> a1 = Local<v8::Array>::Cast(
5204 Foo->Call(context.local(), Foo, 1, args1).ToLocalChecked());
5205 CHECK_EQ(1u, a1->Length());
5206 CHECK_EQ(1.1, a1->Get(context.local(), v8::Integer::New(isolate, 0))
5207 .ToLocalChecked()
5208 ->NumberValue(context.local())
5209 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005210
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005211 v8::Local<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
5212 Local<v8::Array> a2 = Local<v8::Array>::Cast(
5213 Foo->Call(context.local(), Foo, 2, args2).ToLocalChecked());
5214 CHECK_EQ(2u, a2->Length());
5215 CHECK_EQ(2.2, a2->Get(context.local(), v8::Integer::New(isolate, 0))
5216 .ToLocalChecked()
5217 ->NumberValue(context.local())
5218 .FromJust());
5219 CHECK_EQ(3.3, a2->Get(context.local(), v8::Integer::New(isolate, 1))
5220 .ToLocalChecked()
5221 ->NumberValue(context.local())
5222 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005223
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005224 v8::Local<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
5225 Local<v8::Array> a3 = Local<v8::Array>::Cast(
5226 Foo->Call(context.local(), Foo, 3, args3).ToLocalChecked());
5227 CHECK_EQ(3u, a3->Length());
5228 CHECK_EQ(4.4, a3->Get(context.local(), v8::Integer::New(isolate, 0))
5229 .ToLocalChecked()
5230 ->NumberValue(context.local())
5231 .FromJust());
5232 CHECK_EQ(5.5, a3->Get(context.local(), v8::Integer::New(isolate, 1))
5233 .ToLocalChecked()
5234 ->NumberValue(context.local())
5235 .FromJust());
5236 CHECK_EQ(6.6, a3->Get(context.local(), v8::Integer::New(isolate, 2))
5237 .ToLocalChecked()
5238 ->NumberValue(context.local())
5239 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005240
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005241 v8::Local<Value> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
5242 v8_num(10.11)};
5243 Local<v8::Array> a4 = Local<v8::Array>::Cast(
5244 Foo->Call(context.local(), Foo, 4, args4).ToLocalChecked());
5245 CHECK_EQ(4u, a4->Length());
5246 CHECK_EQ(7.7, a4->Get(context.local(), v8::Integer::New(isolate, 0))
5247 .ToLocalChecked()
5248 ->NumberValue(context.local())
5249 .FromJust());
5250 CHECK_EQ(8.8, a4->Get(context.local(), v8::Integer::New(isolate, 1))
5251 .ToLocalChecked()
5252 ->NumberValue(context.local())
5253 .FromJust());
5254 CHECK_EQ(9.9, a4->Get(context.local(), v8::Integer::New(isolate, 2))
5255 .ToLocalChecked()
5256 ->NumberValue(context.local())
5257 .FromJust());
5258 CHECK_EQ(10.11, a4->Get(context.local(), v8::Integer::New(isolate, 3))
5259 .ToLocalChecked()
5260 ->NumberValue(context.local())
5261 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005262
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005263 Local<v8::Value> r1 =
5264 ReturnThisSloppy->Call(context.local(), v8::Undefined(isolate), 0, NULL)
5265 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005266 CHECK(r1->StrictEquals(context->Global()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005267 Local<v8::Value> r2 =
5268 ReturnThisSloppy->Call(context.local(), v8::Null(isolate), 0, NULL)
5269 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005270 CHECK(r2->StrictEquals(context->Global()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005271 Local<v8::Value> r3 =
5272 ReturnThisSloppy->Call(context.local(), v8_num(42), 0, NULL)
5273 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005274 CHECK(r3->IsNumberObject());
5275 CHECK_EQ(42.0, r3.As<v8::NumberObject>()->ValueOf());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005276 Local<v8::Value> r4 =
5277 ReturnThisSloppy->Call(context.local(), v8_str("hello"), 0, NULL)
5278 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005279 CHECK(r4->IsStringObject());
5280 CHECK(r4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005281 Local<v8::Value> r5 =
5282 ReturnThisSloppy->Call(context.local(), v8::True(isolate), 0, NULL)
5283 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005284 CHECK(r5->IsBooleanObject());
5285 CHECK(r5.As<v8::BooleanObject>()->ValueOf());
Steve Blocka7e24c12009-10-30 11:49:00 +00005286
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005287 Local<v8::Value> r6 =
5288 ReturnThisStrict->Call(context.local(), v8::Undefined(isolate), 0, NULL)
5289 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005290 CHECK(r6->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005291 Local<v8::Value> r7 =
5292 ReturnThisStrict->Call(context.local(), v8::Null(isolate), 0, NULL)
5293 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005294 CHECK(r7->IsNull());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005295 Local<v8::Value> r8 =
5296 ReturnThisStrict->Call(context.local(), v8_num(42), 0, NULL)
5297 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005298 CHECK(r8->StrictEquals(v8_num(42)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005299 Local<v8::Value> r9 =
5300 ReturnThisStrict->Call(context.local(), v8_str("hello"), 0, NULL)
5301 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005302 CHECK(r9->StrictEquals(v8_str("hello")));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005303 Local<v8::Value> r10 =
5304 ReturnThisStrict->Call(context.local(), v8::True(isolate), 0, NULL)
5305 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005306 CHECK(r10->StrictEquals(v8::True(isolate)));
Steve Blocka7e24c12009-10-30 11:49:00 +00005307}
5308
5309
5310THREADED_TEST(ConstructCall) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005311 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005312 v8::Isolate* isolate = context->GetIsolate();
5313 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005314 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005315 "function Foo() {"
5316 " var result = [];"
5317 " for (var i = 0; i < arguments.length; i++) {"
5318 " result.push(arguments[i]);"
5319 " }"
5320 " return result;"
5321 "}");
5322 Local<Function> Foo = Local<Function>::Cast(
5323 context->Global()->Get(context.local(), v8_str("Foo")).ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00005324
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005325 v8::Local<Value>* args0 = NULL;
5326 Local<v8::Array> a0 = Local<v8::Array>::Cast(
5327 Foo->NewInstance(context.local(), 0, args0).ToLocalChecked());
5328 CHECK_EQ(0u, a0->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +00005329
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005330 v8::Local<Value> args1[] = {v8_num(1.1)};
5331 Local<v8::Array> a1 = Local<v8::Array>::Cast(
5332 Foo->NewInstance(context.local(), 1, args1).ToLocalChecked());
5333 CHECK_EQ(1u, a1->Length());
5334 CHECK_EQ(1.1, a1->Get(context.local(), v8::Integer::New(isolate, 0))
5335 .ToLocalChecked()
5336 ->NumberValue(context.local())
5337 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005338
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005339 v8::Local<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
5340 Local<v8::Array> a2 = Local<v8::Array>::Cast(
5341 Foo->NewInstance(context.local(), 2, args2).ToLocalChecked());
5342 CHECK_EQ(2u, a2->Length());
5343 CHECK_EQ(2.2, a2->Get(context.local(), v8::Integer::New(isolate, 0))
5344 .ToLocalChecked()
5345 ->NumberValue(context.local())
5346 .FromJust());
5347 CHECK_EQ(3.3, a2->Get(context.local(), v8::Integer::New(isolate, 1))
5348 .ToLocalChecked()
5349 ->NumberValue(context.local())
5350 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005351
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005352 v8::Local<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
5353 Local<v8::Array> a3 = Local<v8::Array>::Cast(
5354 Foo->NewInstance(context.local(), 3, args3).ToLocalChecked());
5355 CHECK_EQ(3u, a3->Length());
5356 CHECK_EQ(4.4, a3->Get(context.local(), v8::Integer::New(isolate, 0))
5357 .ToLocalChecked()
5358 ->NumberValue(context.local())
5359 .FromJust());
5360 CHECK_EQ(5.5, a3->Get(context.local(), v8::Integer::New(isolate, 1))
5361 .ToLocalChecked()
5362 ->NumberValue(context.local())
5363 .FromJust());
5364 CHECK_EQ(6.6, a3->Get(context.local(), v8::Integer::New(isolate, 2))
5365 .ToLocalChecked()
5366 ->NumberValue(context.local())
5367 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005368
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005369 v8::Local<Value> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
5370 v8_num(10.11)};
5371 Local<v8::Array> a4 = Local<v8::Array>::Cast(
5372 Foo->NewInstance(context.local(), 4, args4).ToLocalChecked());
5373 CHECK_EQ(4u, a4->Length());
5374 CHECK_EQ(7.7, a4->Get(context.local(), v8::Integer::New(isolate, 0))
5375 .ToLocalChecked()
5376 ->NumberValue(context.local())
5377 .FromJust());
5378 CHECK_EQ(8.8, a4->Get(context.local(), v8::Integer::New(isolate, 1))
5379 .ToLocalChecked()
5380 ->NumberValue(context.local())
5381 .FromJust());
5382 CHECK_EQ(9.9, a4->Get(context.local(), v8::Integer::New(isolate, 2))
5383 .ToLocalChecked()
5384 ->NumberValue(context.local())
5385 .FromJust());
5386 CHECK_EQ(10.11, a4->Get(context.local(), v8::Integer::New(isolate, 3))
5387 .ToLocalChecked()
5388 ->NumberValue(context.local())
5389 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005390}
5391
5392
Steve Block6ded16b2010-05-10 14:33:55 +01005393THREADED_TEST(ConversionNumber) {
Steve Block6ded16b2010-05-10 14:33:55 +01005394 LocalContext env;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005395 v8::Isolate* isolate = env->GetIsolate();
5396 v8::HandleScope scope(isolate);
Steve Block6ded16b2010-05-10 14:33:55 +01005397 // Very large number.
5398 CompileRun("var obj = Math.pow(2,32) * 1237;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005399 Local<Value> obj =
5400 env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5401 CHECK_EQ(5312874545152.0,
5402 obj->ToNumber(env.local()).ToLocalChecked()->Value());
5403 CHECK_EQ(0, obj->ToInt32(env.local()).ToLocalChecked()->Value());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005404 CHECK(0u ==
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005405 obj->ToUint32(env.local())
5406 .ToLocalChecked()
5407 ->Value()); // NOLINT - no CHECK_EQ for unsigned.
Steve Block6ded16b2010-05-10 14:33:55 +01005408 // Large number.
5409 CompileRun("var obj = -1234567890123;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005410 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5411 CHECK_EQ(-1234567890123.0,
5412 obj->ToNumber(env.local()).ToLocalChecked()->Value());
5413 CHECK_EQ(-1912276171, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5414 CHECK(2382691125u ==
5415 obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005416 // Small positive integer.
5417 CompileRun("var obj = 42;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005418 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5419 CHECK_EQ(42.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
5420 CHECK_EQ(42, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5421 CHECK(42u == obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005422 // Negative integer.
5423 CompileRun("var obj = -37;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005424 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5425 CHECK_EQ(-37.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
5426 CHECK_EQ(-37, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5427 CHECK(4294967259u ==
5428 obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005429 // Positive non-int32 integer.
5430 CompileRun("var obj = 0x81234567;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005431 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5432 CHECK_EQ(2166572391.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
5433 CHECK_EQ(-2128394905, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5434 CHECK(2166572391u ==
5435 obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005436 // Fraction.
5437 CompileRun("var obj = 42.3;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005438 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5439 CHECK_EQ(42.3, obj->ToNumber(env.local()).ToLocalChecked()->Value());
5440 CHECK_EQ(42, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5441 CHECK(42u == obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005442 // Large negative fraction.
5443 CompileRun("var obj = -5726623061.75;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005444 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5445 CHECK_EQ(-5726623061.75,
5446 obj->ToNumber(env.local()).ToLocalChecked()->Value());
5447 CHECK_EQ(-1431655765, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5448 CHECK(2863311531u ==
5449 obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005450}
5451
5452
5453THREADED_TEST(isNumberType) {
Steve Block6ded16b2010-05-10 14:33:55 +01005454 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005455 v8::HandleScope scope(env->GetIsolate());
Steve Block6ded16b2010-05-10 14:33:55 +01005456 // Very large number.
5457 CompileRun("var obj = Math.pow(2,32) * 1237;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005458 Local<Value> obj =
5459 env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005460 CHECK(!obj->IsInt32());
5461 CHECK(!obj->IsUint32());
5462 // Large negative number.
5463 CompileRun("var obj = -1234567890123;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005464 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005465 CHECK(!obj->IsInt32());
5466 CHECK(!obj->IsUint32());
5467 // Small positive integer.
5468 CompileRun("var obj = 42;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005469 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005470 CHECK(obj->IsInt32());
5471 CHECK(obj->IsUint32());
5472 // Negative integer.
5473 CompileRun("var obj = -37;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005474 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005475 CHECK(obj->IsInt32());
5476 CHECK(!obj->IsUint32());
5477 // Positive non-int32 integer.
5478 CompileRun("var obj = 0x81234567;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005479 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005480 CHECK(!obj->IsInt32());
5481 CHECK(obj->IsUint32());
5482 // Fraction.
5483 CompileRun("var obj = 42.3;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005484 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005485 CHECK(!obj->IsInt32());
5486 CHECK(!obj->IsUint32());
5487 // Large negative fraction.
5488 CompileRun("var obj = -5726623061.75;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005489 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005490 CHECK(!obj->IsInt32());
5491 CHECK(!obj->IsUint32());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005492 // Positive zero
5493 CompileRun("var obj = 0.0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005494 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005495 CHECK(obj->IsInt32());
5496 CHECK(obj->IsUint32());
5497 // Positive zero
5498 CompileRun("var obj = -0.0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005499 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005500 CHECK(!obj->IsInt32());
5501 CHECK(!obj->IsUint32());
Steve Block6ded16b2010-05-10 14:33:55 +01005502}
5503
5504
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005505static void CheckUncle(v8::TryCatch* try_catch) {
5506 CHECK(try_catch->HasCaught());
5507 String::Utf8Value str_value(try_catch->Exception());
5508 CHECK_EQ(0, strcmp(*str_value, "uncle?"));
5509 try_catch->Reset();
5510}
5511
5512
Steve Blocka7e24c12009-10-30 11:49:00 +00005513THREADED_TEST(ConversionException) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005514 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005515 v8::Isolate* isolate = env->GetIsolate();
5516 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005517 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005518 "function TestClass() { };"
5519 "TestClass.prototype.toString = function () { throw 'uncle?'; };"
5520 "var obj = new TestClass();");
5521 Local<Value> obj =
5522 env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00005523
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005524 v8::TryCatch try_catch(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005525
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005526 CHECK(obj->ToString(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005527 CheckUncle(&try_catch);
5528
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005529 CHECK(obj->ToNumber(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005530 CheckUncle(&try_catch);
5531
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005532 CHECK(obj->ToInteger(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005533 CheckUncle(&try_catch);
5534
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005535 CHECK(obj->ToUint32(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005536 CheckUncle(&try_catch);
5537
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005538 CHECK(obj->ToInt32(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005539 CheckUncle(&try_catch);
5540
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005541 CHECK(v8::Undefined(isolate)->ToObject(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005542 CHECK(try_catch.HasCaught());
5543 try_catch.Reset();
5544
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005545 CHECK(obj->Int32Value(env.local()).IsNothing());
Steve Blocka7e24c12009-10-30 11:49:00 +00005546 CheckUncle(&try_catch);
5547
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005548 CHECK(obj->Uint32Value(env.local()).IsNothing());
Steve Blocka7e24c12009-10-30 11:49:00 +00005549 CheckUncle(&try_catch);
5550
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005551 CHECK(obj->NumberValue(env.local()).IsNothing());
Steve Blocka7e24c12009-10-30 11:49:00 +00005552 CheckUncle(&try_catch);
5553
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005554 CHECK(obj->IntegerValue(env.local()).IsNothing());
Steve Blocka7e24c12009-10-30 11:49:00 +00005555 CheckUncle(&try_catch);
5556}
5557
5558
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005559void ThrowFromC(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005560 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005561 args.GetIsolate()->ThrowException(v8_str("konto"));
Steve Blocka7e24c12009-10-30 11:49:00 +00005562}
5563
5564
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005565void CCatcher(const v8::FunctionCallbackInfo<v8::Value>& args) {
5566 if (args.Length() < 1) {
5567 args.GetReturnValue().Set(false);
5568 return;
5569 }
5570 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005571 v8::TryCatch try_catch(args.GetIsolate());
5572 Local<Value> result =
5573 CompileRun(args[0]
5574 ->ToString(args.GetIsolate()->GetCurrentContext())
5575 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00005576 CHECK(!try_catch.HasCaught() || result.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005577 args.GetReturnValue().Set(try_catch.HasCaught());
Steve Blocka7e24c12009-10-30 11:49:00 +00005578}
5579
5580
5581THREADED_TEST(APICatch) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005582 v8::Isolate* isolate = CcTest::isolate();
5583 v8::HandleScope scope(isolate);
5584 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005585 templ->Set(v8_str("ThrowFromC"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005586 v8::FunctionTemplate::New(isolate, ThrowFromC));
Steve Blocka7e24c12009-10-30 11:49:00 +00005587 LocalContext context(0, templ);
5588 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005589 "var thrown = false;"
5590 "try {"
5591 " ThrowFromC();"
5592 "} catch (e) {"
5593 " thrown = true;"
5594 "}");
5595 Local<Value> thrown = context->Global()
5596 ->Get(context.local(), v8_str("thrown"))
5597 .ToLocalChecked();
5598 CHECK(thrown->BooleanValue(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005599}
5600
5601
5602THREADED_TEST(APIThrowTryCatch) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005603 v8::Isolate* isolate = CcTest::isolate();
5604 v8::HandleScope scope(isolate);
5605 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005606 templ->Set(v8_str("ThrowFromC"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005607 v8::FunctionTemplate::New(isolate, ThrowFromC));
Steve Blocka7e24c12009-10-30 11:49:00 +00005608 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005609 v8::TryCatch try_catch(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005610 CompileRun("ThrowFromC();");
5611 CHECK(try_catch.HasCaught());
5612}
5613
5614
5615// Test that a try-finally block doesn't shadow a try-catch block
5616// when setting up an external handler.
5617//
5618// BUG(271): Some of the exception propagation does not work on the
5619// ARM simulator because the simulator separates the C++ stack and the
5620// JS stack. This test therefore fails on the simulator. The test is
5621// not threaded to allow the threading tests to run on the simulator.
5622TEST(TryCatchInTryFinally) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005623 v8::Isolate* isolate = CcTest::isolate();
5624 v8::HandleScope scope(isolate);
5625 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005626 templ->Set(v8_str("CCatcher"), v8::FunctionTemplate::New(isolate, CCatcher));
Steve Blocka7e24c12009-10-30 11:49:00 +00005627 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005628 Local<Value> result = CompileRun(
5629 "try {"
5630 " try {"
5631 " CCatcher('throw 7;');"
5632 " } finally {"
5633 " }"
5634 "} catch (e) {"
5635 "}");
Steve Blocka7e24c12009-10-30 11:49:00 +00005636 CHECK(result->IsTrue());
5637}
5638
5639
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005640static void check_custom_error_tostring(v8::Local<v8::Message> message,
5641 v8::Local<v8::Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005642 const char* uncaught_error = "Uncaught MyError toString";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005643 CHECK(message->Get()
5644 ->Equals(CcTest::isolate()->GetCurrentContext(),
5645 v8_str(uncaught_error))
5646 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005647}
5648
5649
5650TEST(CustomErrorToString) {
5651 LocalContext context;
5652 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005653 context->GetIsolate()->AddMessageListener(check_custom_error_tostring);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005654 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005655 "function MyError(name, message) { "
5656 " this.name = name; "
5657 " this.message = message; "
5658 "} "
5659 "MyError.prototype = Object.create(Error.prototype); "
5660 "MyError.prototype.toString = function() { "
5661 " return 'MyError toString'; "
5662 "}; "
5663 "throw new MyError('my name', 'my message'); ");
5664 context->GetIsolate()->RemoveMessageListeners(check_custom_error_tostring);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005665}
5666
5667
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005668static void check_custom_error_message(v8::Local<v8::Message> message,
5669 v8::Local<v8::Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005670 const char* uncaught_error = "Uncaught MyError: my message";
5671 printf("%s\n", *v8::String::Utf8Value(message->Get()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005672 CHECK(message->Get()
5673 ->Equals(CcTest::isolate()->GetCurrentContext(),
5674 v8_str(uncaught_error))
5675 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005676}
5677
5678
5679TEST(CustomErrorMessage) {
5680 LocalContext context;
5681 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005682 context->GetIsolate()->AddMessageListener(check_custom_error_message);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005683
5684 // Handlebars.
5685 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005686 "function MyError(msg) { "
5687 " this.name = 'MyError'; "
5688 " this.message = msg; "
5689 "} "
5690 "MyError.prototype = new Error(); "
5691 "throw new MyError('my message'); ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005692
5693 // Closure.
5694 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005695 "function MyError(msg) { "
5696 " this.name = 'MyError'; "
5697 " this.message = msg; "
5698 "} "
5699 "inherits = function(childCtor, parentCtor) { "
5700 " function tempCtor() {}; "
5701 " tempCtor.prototype = parentCtor.prototype; "
5702 " childCtor.superClass_ = parentCtor.prototype; "
5703 " childCtor.prototype = new tempCtor(); "
5704 " childCtor.prototype.constructor = childCtor; "
5705 "}; "
5706 "inherits(MyError, Error); "
5707 "throw new MyError('my message'); ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005708
5709 // Object.create.
5710 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005711 "function MyError(msg) { "
5712 " this.name = 'MyError'; "
5713 " this.message = msg; "
5714 "} "
5715 "MyError.prototype = Object.create(Error.prototype); "
5716 "throw new MyError('my message'); ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005717
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005718 context->GetIsolate()->RemoveMessageListeners(check_custom_error_message);
Ben Murdochb8e0da22011-05-16 14:20:40 +01005719}
5720
5721
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005722static void check_custom_rethrowing_message(v8::Local<v8::Message> message,
5723 v8::Local<v8::Value> data) {
5724 const char* uncaught_error = "Uncaught exception";
5725 CHECK(message->Get()
5726 ->Equals(CcTest::isolate()->GetCurrentContext(),
5727 v8_str(uncaught_error))
5728 .FromJust());
5729}
5730
5731
5732TEST(CustomErrorRethrowsOnToString) {
5733 LocalContext context;
5734 v8::HandleScope scope(context->GetIsolate());
5735 context->GetIsolate()->AddMessageListener(check_custom_rethrowing_message);
5736
5737 CompileRun(
5738 "var e = { toString: function() { throw e; } };"
5739 "try { throw e; } finally {}");
5740
5741 context->GetIsolate()->RemoveMessageListeners(
5742 check_custom_rethrowing_message);
5743}
5744
5745
5746static void receive_message(v8::Local<v8::Message> message,
5747 v8::Local<v8::Value> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005748 message->Get();
5749 message_received = true;
5750}
5751
5752
5753TEST(APIThrowMessage) {
5754 message_received = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005755 v8::Isolate* isolate = CcTest::isolate();
5756 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005757 isolate->AddMessageListener(receive_message);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005758 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005759 templ->Set(v8_str("ThrowFromC"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005760 v8::FunctionTemplate::New(isolate, ThrowFromC));
Steve Blocka7e24c12009-10-30 11:49:00 +00005761 LocalContext context(0, templ);
5762 CompileRun("ThrowFromC();");
5763 CHECK(message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005764 isolate->RemoveMessageListeners(receive_message);
Steve Blocka7e24c12009-10-30 11:49:00 +00005765}
5766
5767
5768TEST(APIThrowMessageAndVerboseTryCatch) {
5769 message_received = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005770 v8::Isolate* isolate = CcTest::isolate();
5771 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005772 isolate->AddMessageListener(receive_message);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005773 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005774 templ->Set(v8_str("ThrowFromC"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005775 v8::FunctionTemplate::New(isolate, ThrowFromC));
Steve Blocka7e24c12009-10-30 11:49:00 +00005776 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005777 v8::TryCatch try_catch(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005778 try_catch.SetVerbose(true);
5779 Local<Value> result = CompileRun("ThrowFromC();");
5780 CHECK(try_catch.HasCaught());
5781 CHECK(result.IsEmpty());
5782 CHECK(message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005783 isolate->RemoveMessageListeners(receive_message);
Steve Blocka7e24c12009-10-30 11:49:00 +00005784}
5785
5786
Ben Murdoch8b112d22011-06-08 16:22:53 +01005787TEST(APIStackOverflowAndVerboseTryCatch) {
5788 message_received = false;
Ben Murdoch8b112d22011-06-08 16:22:53 +01005789 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005790 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005791 context->GetIsolate()->AddMessageListener(receive_message);
5792 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +01005793 try_catch.SetVerbose(true);
5794 Local<Value> result = CompileRun("function foo() { foo(); } foo();");
5795 CHECK(try_catch.HasCaught());
5796 CHECK(result.IsEmpty());
5797 CHECK(message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005798 context->GetIsolate()->RemoveMessageListeners(receive_message);
Ben Murdoch8b112d22011-06-08 16:22:53 +01005799}
5800
5801
Steve Blocka7e24c12009-10-30 11:49:00 +00005802THREADED_TEST(ExternalScriptException) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005803 v8::Isolate* isolate = CcTest::isolate();
5804 v8::HandleScope scope(isolate);
5805 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005806 templ->Set(v8_str("ThrowFromC"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005807 v8::FunctionTemplate::New(isolate, ThrowFromC));
Steve Blocka7e24c12009-10-30 11:49:00 +00005808 LocalContext context(0, templ);
5809
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005810 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005811 Local<Value> result = CompileRun("ThrowFromC(); throw 'panama';");
Steve Blocka7e24c12009-10-30 11:49:00 +00005812 CHECK(result.IsEmpty());
5813 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005814 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005815 CHECK_EQ(0, strcmp("konto", *exception_value));
Steve Blocka7e24c12009-10-30 11:49:00 +00005816}
5817
5818
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005819void CThrowCountDown(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005820 ApiTestFuzzer::Fuzz();
5821 CHECK_EQ(4, args.Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005822 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
5823 int count = args[0]->Int32Value(context).FromJust();
5824 int cInterval = args[2]->Int32Value(context).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00005825 if (count == 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005826 args.GetIsolate()->ThrowException(v8_str("FromC"));
5827 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00005828 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005829 Local<v8::Object> global = context->Global();
5830 Local<Value> fun =
5831 global->Get(context, v8_str("JSThrowCountDown")).ToLocalChecked();
5832 v8::Local<Value> argv[] = {v8_num(count - 1), args[1], args[2], args[3]};
Steve Blocka7e24c12009-10-30 11:49:00 +00005833 if (count % cInterval == 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005834 v8::TryCatch try_catch(args.GetIsolate());
5835 Local<Value> result = fun.As<Function>()
5836 ->Call(context, global, 4, argv)
5837 .FromMaybe(Local<Value>());
5838 int expected = args[3]->Int32Value(context).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00005839 if (try_catch.HasCaught()) {
5840 CHECK_EQ(expected, count);
5841 CHECK(result.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005842 CHECK(!CcTest::i_isolate()->has_scheduled_exception());
Steve Blocka7e24c12009-10-30 11:49:00 +00005843 } else {
5844 CHECK_NE(expected, count);
5845 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005846 args.GetReturnValue().Set(result);
5847 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00005848 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005849 args.GetReturnValue().Set(fun.As<Function>()
5850 ->Call(context, global, 4, argv)
5851 .FromMaybe(v8::Local<v8::Value>()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005852 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00005853 }
5854 }
5855}
5856
5857
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005858void JSCheck(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005859 ApiTestFuzzer::Fuzz();
5860 CHECK_EQ(3, args.Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005861 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
5862 bool equality = args[0]->BooleanValue(context).FromJust();
5863 int count = args[1]->Int32Value(context).FromJust();
5864 int expected = args[2]->Int32Value(context).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00005865 if (equality) {
5866 CHECK_EQ(count, expected);
5867 } else {
5868 CHECK_NE(count, expected);
5869 }
Steve Blocka7e24c12009-10-30 11:49:00 +00005870}
5871
5872
5873THREADED_TEST(EvalInTryFinally) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005874 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005875 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005876 v8::TryCatch try_catch(context->GetIsolate());
5877 CompileRun(
5878 "(function() {"
5879 " try {"
5880 " eval('asldkf (*&^&*^');"
5881 " } finally {"
5882 " return;"
5883 " }"
5884 "})()");
Steve Blocka7e24c12009-10-30 11:49:00 +00005885 CHECK(!try_catch.HasCaught());
5886}
5887
5888
5889// This test works by making a stack of alternating JavaScript and C
5890// activations. These activations set up exception handlers with regular
5891// intervals, one interval for C activations and another for JavaScript
5892// activations. When enough activations have been created an exception is
5893// thrown and we check that the right activation catches the exception and that
5894// no other activations do. The right activation is always the topmost one with
5895// a handler, regardless of whether it is in JavaScript or C.
5896//
5897// The notation used to describe a test case looks like this:
5898//
5899// *JS[4] *C[3] @JS[2] C[1] JS[0]
5900//
5901// Each entry is an activation, either JS or C. The index is the count at that
5902// level. Stars identify activations with exception handlers, the @ identifies
5903// the exception handler that should catch the exception.
5904//
5905// BUG(271): Some of the exception propagation does not work on the
5906// ARM simulator because the simulator separates the C++ stack and the
5907// JS stack. This test therefore fails on the simulator. The test is
5908// not threaded to allow the threading tests to run on the simulator.
5909TEST(ExceptionOrder) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005910 v8::Isolate* isolate = CcTest::isolate();
5911 v8::HandleScope scope(isolate);
5912 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5913 templ->Set(v8_str("check"), v8::FunctionTemplate::New(isolate, JSCheck));
Steve Blocka7e24c12009-10-30 11:49:00 +00005914 templ->Set(v8_str("CThrowCountDown"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005915 v8::FunctionTemplate::New(isolate, CThrowCountDown));
Steve Blocka7e24c12009-10-30 11:49:00 +00005916 LocalContext context(0, templ);
5917 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005918 "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
5919 " if (count == 0) throw 'FromJS';"
5920 " if (count % jsInterval == 0) {"
5921 " try {"
5922 " var value = CThrowCountDown(count - 1,"
5923 " jsInterval,"
5924 " cInterval,"
5925 " expected);"
5926 " check(false, count, expected);"
5927 " return value;"
5928 " } catch (e) {"
5929 " check(true, count, expected);"
5930 " }"
5931 " } else {"
5932 " return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
5933 " }"
5934 "}");
5935 Local<Function> fun = Local<Function>::Cast(
5936 context->Global()
5937 ->Get(context.local(), v8_str("JSThrowCountDown"))
5938 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00005939
5940 const int argc = 4;
5941 // count jsInterval cInterval expected
5942
5943 // *JS[4] *C[3] @JS[2] C[1] JS[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005944 v8::Local<Value> a0[argc] = {v8_num(4), v8_num(2), v8_num(3), v8_num(2)};
5945 fun->Call(context.local(), fun, argc, a0).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00005946
5947 // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005948 v8::Local<Value> a1[argc] = {v8_num(5), v8_num(6), v8_num(1), v8_num(2)};
5949 fun->Call(context.local(), fun, argc, a1).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00005950
5951 // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005952 v8::Local<Value> a2[argc] = {v8_num(6), v8_num(7), v8_num(5), v8_num(5)};
5953 fun->Call(context.local(), fun, argc, a2).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00005954
5955 // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005956 v8::Local<Value> a3[argc] = {v8_num(6), v8_num(6), v8_num(7), v8_num(6)};
5957 fun->Call(context.local(), fun, argc, a3).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00005958
5959 // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005960 v8::Local<Value> a4[argc] = {v8_num(6), v8_num(4), v8_num(5), v8_num(4)};
5961 fun->Call(context.local(), fun, argc, a4).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00005962
5963 // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005964 v8::Local<Value> a5[argc] = {v8_num(6), v8_num(4), v8_num(3), v8_num(3)};
5965 fun->Call(context.local(), fun, argc, a5).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00005966}
5967
5968
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005969void ThrowValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005970 ApiTestFuzzer::Fuzz();
5971 CHECK_EQ(1, args.Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005972 args.GetIsolate()->ThrowException(args[0]);
Steve Blocka7e24c12009-10-30 11:49:00 +00005973}
5974
5975
5976THREADED_TEST(ThrowValues) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005977 v8::Isolate* isolate = CcTest::isolate();
5978 v8::HandleScope scope(isolate);
5979 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5980 templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(isolate, ThrowValue));
Steve Blocka7e24c12009-10-30 11:49:00 +00005981 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005982 v8::Local<v8::Array> result = v8::Local<v8::Array>::Cast(
5983 CompileRun("function Run(obj) {"
5984 " try {"
5985 " Throw(obj);"
5986 " } catch (e) {"
5987 " return e;"
5988 " }"
5989 " return 'no exception';"
5990 "}"
5991 "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
5992 CHECK_EQ(5u, result->Length());
5993 CHECK(result->Get(context.local(), v8::Integer::New(isolate, 0))
5994 .ToLocalChecked()
5995 ->IsString());
5996 CHECK(result->Get(context.local(), v8::Integer::New(isolate, 1))
5997 .ToLocalChecked()
5998 ->IsNumber());
5999 CHECK_EQ(1, result->Get(context.local(), v8::Integer::New(isolate, 1))
6000 .ToLocalChecked()
6001 ->Int32Value(context.local())
6002 .FromJust());
6003 CHECK(result->Get(context.local(), v8::Integer::New(isolate, 2))
6004 .ToLocalChecked()
6005 ->IsNumber());
6006 CHECK_EQ(0, result->Get(context.local(), v8::Integer::New(isolate, 2))
6007 .ToLocalChecked()
6008 ->Int32Value(context.local())
6009 .FromJust());
6010 CHECK(result->Get(context.local(), v8::Integer::New(isolate, 3))
6011 .ToLocalChecked()
6012 ->IsNull());
6013 CHECK(result->Get(context.local(), v8::Integer::New(isolate, 4))
6014 .ToLocalChecked()
6015 ->IsUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +00006016}
6017
6018
6019THREADED_TEST(CatchZero) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006020 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006021 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006022 v8::TryCatch try_catch(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006023 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006024 CompileRun("throw 10");
Steve Blocka7e24c12009-10-30 11:49:00 +00006025 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006026 CHECK_EQ(10, try_catch.Exception()->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006027 try_catch.Reset();
6028 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006029 CompileRun("throw 0");
Steve Blocka7e24c12009-10-30 11:49:00 +00006030 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006031 CHECK_EQ(0, try_catch.Exception()->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006032}
6033
6034
6035THREADED_TEST(CatchExceptionFromWith) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006036 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006037 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006038 v8::TryCatch try_catch(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006039 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006040 CompileRun("var o = {}; with (o) { throw 42; }");
Steve Blocka7e24c12009-10-30 11:49:00 +00006041 CHECK(try_catch.HasCaught());
6042}
6043
6044
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006045THREADED_TEST(TryCatchAndFinallyHidingException) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006046 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006047 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006048 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006049 CHECK(!try_catch.HasCaught());
6050 CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
6051 CompileRun("f({toString: function() { throw 42; }});");
6052 CHECK(!try_catch.HasCaught());
6053}
6054
6055
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006056void WithTryCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006057 v8::TryCatch try_catch(args.GetIsolate());
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006058}
6059
6060
6061THREADED_TEST(TryCatchAndFinally) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006062 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006063 v8::Isolate* isolate = context->GetIsolate();
6064 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006065 CHECK(context->Global()
6066 ->Set(context.local(), v8_str("native_with_try_catch"),
6067 v8::FunctionTemplate::New(isolate, WithTryCatch)
6068 ->GetFunction(context.local())
6069 .ToLocalChecked())
6070 .FromJust());
6071 v8::TryCatch try_catch(isolate);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006072 CHECK(!try_catch.HasCaught());
6073 CompileRun(
6074 "try {\n"
6075 " throw new Error('a');\n"
6076 "} finally {\n"
6077 " native_with_try_catch();\n"
6078 "}\n");
6079 CHECK(try_catch.HasCaught());
6080}
6081
6082
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006083static void TryCatchNested1Helper(int depth) {
6084 if (depth > 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006085 v8::TryCatch try_catch(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006086 try_catch.SetVerbose(true);
6087 TryCatchNested1Helper(depth - 1);
6088 CHECK(try_catch.HasCaught());
6089 try_catch.ReThrow();
6090 } else {
6091 CcTest::isolate()->ThrowException(v8_str("E1"));
6092 }
6093}
6094
6095
6096static void TryCatchNested2Helper(int depth) {
6097 if (depth > 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006098 v8::TryCatch try_catch(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006099 try_catch.SetVerbose(true);
6100 TryCatchNested2Helper(depth - 1);
6101 CHECK(try_catch.HasCaught());
6102 try_catch.ReThrow();
6103 } else {
6104 CompileRun("throw 'E2';");
6105 }
6106}
6107
6108
6109TEST(TryCatchNested) {
6110 v8::V8::Initialize();
Steve Blocka7e24c12009-10-30 11:49:00 +00006111 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006112 v8::HandleScope scope(context->GetIsolate());
6113
6114 {
6115 // Test nested try-catch with a native throw in the end.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006116 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006117 TryCatchNested1Helper(5);
6118 CHECK(try_catch.HasCaught());
6119 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E1"));
6120 }
6121
6122 {
6123 // Test nested try-catch with a JavaScript throw in the end.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006124 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006125 TryCatchNested2Helper(5);
6126 CHECK(try_catch.HasCaught());
6127 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E2"));
6128 }
6129}
6130
6131
6132void TryCatchMixedNestingCheck(v8::TryCatch* try_catch) {
6133 CHECK(try_catch->HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006134 Local<Message> message = try_catch->Message();
6135 Local<Value> resource = message->GetScriptOrigin().ResourceName();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006136 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(resource), "inner"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006137 CHECK_EQ(0,
6138 strcmp(*v8::String::Utf8Value(message->Get()), "Uncaught Error: a"));
6139 CHECK_EQ(1, message->GetLineNumber(CcTest::isolate()->GetCurrentContext())
6140 .FromJust());
6141 CHECK_EQ(0, message->GetStartColumn(CcTest::isolate()->GetCurrentContext())
6142 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006143}
6144
6145
6146void TryCatchMixedNestingHelper(
6147 const v8::FunctionCallbackInfo<v8::Value>& args) {
6148 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006149 v8::TryCatch try_catch(args.GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006150 CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
6151 CHECK(try_catch.HasCaught());
6152 TryCatchMixedNestingCheck(&try_catch);
6153 try_catch.ReThrow();
6154}
6155
6156
6157// This test ensures that an outer TryCatch in the following situation:
6158// C++/TryCatch -> JS -> C++/TryCatch -> JS w/ SyntaxError
6159// does not clobber the Message object generated for the inner TryCatch.
6160// This exercises the ability of TryCatch.ReThrow() to restore the
6161// inner pending Message before throwing the exception again.
6162TEST(TryCatchMixedNesting) {
6163 v8::Isolate* isolate = CcTest::isolate();
6164 v8::HandleScope scope(isolate);
6165 v8::V8::Initialize();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006166 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006167 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6168 templ->Set(v8_str("TryCatchMixedNestingHelper"),
6169 v8::FunctionTemplate::New(isolate, TryCatchMixedNestingHelper));
6170 LocalContext context(0, templ);
6171 CompileRunWithOrigin("TryCatchMixedNestingHelper();\n", "outer", 1, 1);
6172 TryCatchMixedNestingCheck(&try_catch);
6173}
6174
6175
6176void TryCatchNativeHelper(const v8::FunctionCallbackInfo<v8::Value>& args) {
6177 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006178 v8::TryCatch try_catch(args.GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006179 args.GetIsolate()->ThrowException(v8_str("boom"));
6180 CHECK(try_catch.HasCaught());
6181}
6182
6183
6184TEST(TryCatchNative) {
6185 v8::Isolate* isolate = CcTest::isolate();
6186 v8::HandleScope scope(isolate);
6187 v8::V8::Initialize();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006188 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006189 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6190 templ->Set(v8_str("TryCatchNativeHelper"),
6191 v8::FunctionTemplate::New(isolate, TryCatchNativeHelper));
6192 LocalContext context(0, templ);
6193 CompileRun("TryCatchNativeHelper();");
6194 CHECK(!try_catch.HasCaught());
6195}
6196
6197
6198void TryCatchNativeResetHelper(
6199 const v8::FunctionCallbackInfo<v8::Value>& args) {
6200 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006201 v8::TryCatch try_catch(args.GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006202 args.GetIsolate()->ThrowException(v8_str("boom"));
6203 CHECK(try_catch.HasCaught());
6204 try_catch.Reset();
6205 CHECK(!try_catch.HasCaught());
6206}
6207
6208
6209TEST(TryCatchNativeReset) {
6210 v8::Isolate* isolate = CcTest::isolate();
6211 v8::HandleScope scope(isolate);
6212 v8::V8::Initialize();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006213 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006214 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6215 templ->Set(v8_str("TryCatchNativeResetHelper"),
6216 v8::FunctionTemplate::New(isolate, TryCatchNativeResetHelper));
6217 LocalContext context(0, templ);
6218 CompileRun("TryCatchNativeResetHelper();");
6219 CHECK(!try_catch.HasCaught());
6220}
6221
6222
6223THREADED_TEST(Equality) {
6224 LocalContext context;
6225 v8::Isolate* isolate = context->GetIsolate();
6226 v8::HandleScope scope(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006227 // Check that equality works at all before relying on CHECK_EQ
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006228 CHECK(v8_str("a")->Equals(context.local(), v8_str("a")).FromJust());
6229 CHECK(!v8_str("a")->Equals(context.local(), v8_str("b")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006230
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006231 CHECK(v8_str("a")->Equals(context.local(), v8_str("a")).FromJust());
6232 CHECK(!v8_str("a")->Equals(context.local(), v8_str("b")).FromJust());
6233 CHECK(v8_num(1)->Equals(context.local(), v8_num(1)).FromJust());
6234 CHECK(v8_num(1.00)->Equals(context.local(), v8_num(1)).FromJust());
6235 CHECK(!v8_num(1)->Equals(context.local(), v8_num(2)).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006236
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006237 // Assume String is not internalized.
Steve Blocka7e24c12009-10-30 11:49:00 +00006238 CHECK(v8_str("a")->StrictEquals(v8_str("a")));
6239 CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
6240 CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
6241 CHECK(v8_num(1)->StrictEquals(v8_num(1)));
6242 CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006243 CHECK(v8_num(0.0)->StrictEquals(v8_num(-0.0)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006244 Local<Value> not_a_number = v8_num(std::numeric_limits<double>::quiet_NaN());
Steve Blocka7e24c12009-10-30 11:49:00 +00006245 CHECK(!not_a_number->StrictEquals(not_a_number));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006246 CHECK(v8::False(isolate)->StrictEquals(v8::False(isolate)));
6247 CHECK(!v8::False(isolate)->StrictEquals(v8::Undefined(isolate)));
Steve Blocka7e24c12009-10-30 11:49:00 +00006248
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006249 v8::Local<v8::Object> obj = v8::Object::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006250 v8::Persistent<v8::Object> alias(isolate, obj);
6251 CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
6252 alias.Reset();
6253
6254 CHECK(v8_str("a")->SameValue(v8_str("a")));
6255 CHECK(!v8_str("a")->SameValue(v8_str("b")));
6256 CHECK(!v8_str("5")->SameValue(v8_num(5)));
6257 CHECK(v8_num(1)->SameValue(v8_num(1)));
6258 CHECK(!v8_num(1)->SameValue(v8_num(2)));
6259 CHECK(!v8_num(0.0)->SameValue(v8_num(-0.0)));
6260 CHECK(not_a_number->SameValue(not_a_number));
6261 CHECK(v8::False(isolate)->SameValue(v8::False(isolate)));
6262 CHECK(!v8::False(isolate)->SameValue(v8::Undefined(isolate)));
Steve Blocka7e24c12009-10-30 11:49:00 +00006263}
6264
6265
6266THREADED_TEST(MultiRun) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006267 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006268 v8::HandleScope scope(context->GetIsolate());
6269 Local<Script> script = v8_compile("x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006270 for (int i = 0; i < 10; i++) {
6271 script->Run(context.local()).IsEmpty();
6272 }
Steve Blocka7e24c12009-10-30 11:49:00 +00006273}
6274
6275
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006276static void GetXValue(Local<Name> name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006277 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006278 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006279 CHECK(info.Data()
6280 ->Equals(CcTest::isolate()->GetCurrentContext(), v8_str("donut"))
6281 .FromJust());
6282 CHECK(name->Equals(CcTest::isolate()->GetCurrentContext(), v8_str("x"))
6283 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006284 info.GetReturnValue().Set(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00006285}
6286
6287
6288THREADED_TEST(SimplePropertyRead) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006289 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006290 v8::Isolate* isolate = context->GetIsolate();
6291 v8::HandleScope scope(isolate);
6292 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6293 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006294 CHECK(context->Global()
6295 ->Set(context.local(), v8_str("obj"),
6296 templ->NewInstance(context.local()).ToLocalChecked())
6297 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006298 Local<Script> script = v8_compile("obj.x");
Steve Blocka7e24c12009-10-30 11:49:00 +00006299 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006300 Local<Value> result = script->Run(context.local()).ToLocalChecked();
6301 CHECK(result->Equals(context.local(), v8_str("x")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006302 }
6303}
6304
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006305
Andrei Popescu31002712010-02-23 13:46:05 +00006306THREADED_TEST(DefinePropertyOnAPIAccessor) {
Andrei Popescu31002712010-02-23 13:46:05 +00006307 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006308 v8::Isolate* isolate = context->GetIsolate();
6309 v8::HandleScope scope(isolate);
6310 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6311 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006312 CHECK(context->Global()
6313 ->Set(context.local(), v8_str("obj"),
6314 templ->NewInstance(context.local()).ToLocalChecked())
6315 .FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +00006316
6317 // Uses getOwnPropertyDescriptor to check the configurable status
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006318 Local<Script> script_desc = v8_compile(
6319 "var prop = Object.getOwnPropertyDescriptor( "
6320 "obj, 'x');"
6321 "prop.configurable;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006322 Local<Value> result = script_desc->Run(context.local()).ToLocalChecked();
6323 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), true);
Andrei Popescu31002712010-02-23 13:46:05 +00006324
6325 // Redefine get - but still configurable
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006326 Local<Script> script_define = v8_compile(
6327 "var desc = { get: function(){return 42; },"
6328 " configurable: true };"
6329 "Object.defineProperty(obj, 'x', desc);"
6330 "obj.x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006331 result = script_define->Run(context.local()).ToLocalChecked();
6332 CHECK(result->Equals(context.local(), v8_num(42)).FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +00006333
6334 // Check that the accessor is still configurable
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006335 result = script_desc->Run(context.local()).ToLocalChecked();
6336 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), true);
Andrei Popescu31002712010-02-23 13:46:05 +00006337
6338 // Redefine to a non-configurable
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006339 script_define = v8_compile(
6340 "var desc = { get: function(){return 43; },"
6341 " configurable: false };"
6342 "Object.defineProperty(obj, 'x', desc);"
6343 "obj.x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006344 result = script_define->Run(context.local()).ToLocalChecked();
6345 CHECK(result->Equals(context.local(), v8_num(43)).FromJust());
6346 result = script_desc->Run(context.local()).ToLocalChecked();
6347 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), false);
Andrei Popescu31002712010-02-23 13:46:05 +00006348
6349 // Make sure that it is not possible to redefine again
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006350 v8::TryCatch try_catch(isolate);
6351 CHECK(script_define->Run(context.local()).IsEmpty());
Andrei Popescu31002712010-02-23 13:46:05 +00006352 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006353 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006354 CHECK_EQ(0,
6355 strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
Andrei Popescu31002712010-02-23 13:46:05 +00006356}
6357
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006358
Andrei Popescu31002712010-02-23 13:46:05 +00006359THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006360 v8::Isolate* isolate = CcTest::isolate();
6361 v8::HandleScope scope(isolate);
6362 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Andrei Popescu31002712010-02-23 13:46:05 +00006363 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
6364 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006365 CHECK(context->Global()
6366 ->Set(context.local(), v8_str("obj"),
6367 templ->NewInstance(context.local()).ToLocalChecked())
6368 .FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +00006369
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006370 Local<Script> script_desc = v8_compile(
6371 "var prop ="
6372 "Object.getOwnPropertyDescriptor( "
6373 "obj, 'x');"
6374 "prop.configurable;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006375 Local<Value> result = script_desc->Run(context.local()).ToLocalChecked();
6376 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), true);
Andrei Popescu31002712010-02-23 13:46:05 +00006377
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006378 Local<Script> script_define = v8_compile(
6379 "var desc = {get: function(){return 42; },"
6380 " configurable: true };"
6381 "Object.defineProperty(obj, 'x', desc);"
6382 "obj.x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006383 result = script_define->Run(context.local()).ToLocalChecked();
6384 CHECK(result->Equals(context.local(), v8_num(42)).FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +00006385
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006386 result = script_desc->Run(context.local()).ToLocalChecked();
6387 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), true);
Andrei Popescu31002712010-02-23 13:46:05 +00006388
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006389 script_define = v8_compile(
6390 "var desc = {get: function(){return 43; },"
6391 " configurable: false };"
6392 "Object.defineProperty(obj, 'x', desc);"
6393 "obj.x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006394 result = script_define->Run(context.local()).ToLocalChecked();
6395 CHECK(result->Equals(context.local(), v8_num(43)).FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +00006396
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006397 result = script_desc->Run(context.local()).ToLocalChecked();
6398 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), false);
Andrei Popescu31002712010-02-23 13:46:05 +00006399
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006400 v8::TryCatch try_catch(isolate);
6401 CHECK(script_define->Run(context.local()).IsEmpty());
Andrei Popescu31002712010-02-23 13:46:05 +00006402 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006403 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006404 CHECK_EQ(0,
6405 strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
Andrei Popescu31002712010-02-23 13:46:05 +00006406}
6407
6408
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006409static v8::Local<v8::Object> GetGlobalProperty(LocalContext* context,
6410 char const* name) {
6411 return v8::Local<v8::Object>::Cast(
6412 (*context)
6413 ->Global()
6414 ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(name))
6415 .ToLocalChecked());
Leon Clarkef7060e22010-06-03 12:02:55 +01006416}
Andrei Popescu31002712010-02-23 13:46:05 +00006417
6418
Leon Clarkef7060e22010-06-03 12:02:55 +01006419THREADED_TEST(DefineAPIAccessorOnObject) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006420 v8::Isolate* isolate = CcTest::isolate();
6421 v8::HandleScope scope(isolate);
6422 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Leon Clarkef7060e22010-06-03 12:02:55 +01006423 LocalContext context;
6424
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006425 CHECK(context->Global()
6426 ->Set(context.local(), v8_str("obj1"),
6427 templ->NewInstance(context.local()).ToLocalChecked())
6428 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006429 CompileRun("var obj2 = {};");
6430
6431 CHECK(CompileRun("obj1.x")->IsUndefined());
6432 CHECK(CompileRun("obj2.x")->IsUndefined());
6433
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006434 CHECK(GetGlobalProperty(&context, "obj1")
6435 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6436 v8_str("donut"))
6437 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006438
6439 ExpectString("obj1.x", "x");
6440 CHECK(CompileRun("obj2.x")->IsUndefined());
6441
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006442 CHECK(GetGlobalProperty(&context, "obj2")
6443 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6444 v8_str("donut"))
6445 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006446
6447 ExpectString("obj1.x", "x");
6448 ExpectString("obj2.x", "x");
6449
6450 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
6451 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
6452
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006453 CompileRun(
6454 "Object.defineProperty(obj1, 'x',"
6455 "{ get: function() { return 'y'; }, configurable: true })");
Leon Clarkef7060e22010-06-03 12:02:55 +01006456
6457 ExpectString("obj1.x", "y");
6458 ExpectString("obj2.x", "x");
6459
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006460 CompileRun(
6461 "Object.defineProperty(obj2, 'x',"
6462 "{ get: function() { return 'y'; }, configurable: true })");
Leon Clarkef7060e22010-06-03 12:02:55 +01006463
6464 ExpectString("obj1.x", "y");
6465 ExpectString("obj2.x", "y");
6466
6467 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
6468 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
6469
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006470 CHECK(GetGlobalProperty(&context, "obj1")
6471 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6472 v8_str("donut"))
6473 .FromJust());
6474 CHECK(GetGlobalProperty(&context, "obj2")
6475 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6476 v8_str("donut"))
6477 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006478
6479 ExpectString("obj1.x", "x");
6480 ExpectString("obj2.x", "x");
6481
6482 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
6483 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
6484
6485 // Define getters/setters, but now make them not configurable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006486 CompileRun(
6487 "Object.defineProperty(obj1, 'x',"
6488 "{ get: function() { return 'z'; }, configurable: false })");
6489 CompileRun(
6490 "Object.defineProperty(obj2, 'x',"
6491 "{ get: function() { return 'z'; }, configurable: false })");
Leon Clarkef7060e22010-06-03 12:02:55 +01006492 ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
6493 ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
6494
6495 ExpectString("obj1.x", "z");
6496 ExpectString("obj2.x", "z");
6497
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006498 CHECK(GetGlobalProperty(&context, "obj1")
6499 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6500 v8_str("donut"))
6501 .IsNothing());
6502 CHECK(GetGlobalProperty(&context, "obj2")
6503 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6504 v8_str("donut"))
6505 .IsNothing());
Leon Clarkef7060e22010-06-03 12:02:55 +01006506
6507 ExpectString("obj1.x", "z");
6508 ExpectString("obj2.x", "z");
6509}
6510
6511
6512THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006513 v8::Isolate* isolate = CcTest::isolate();
6514 v8::HandleScope scope(isolate);
6515 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Leon Clarkef7060e22010-06-03 12:02:55 +01006516 LocalContext context;
6517
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006518 CHECK(context->Global()
6519 ->Set(context.local(), v8_str("obj1"),
6520 templ->NewInstance(context.local()).ToLocalChecked())
6521 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006522 CompileRun("var obj2 = {};");
6523
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006524 CHECK(GetGlobalProperty(&context, "obj1")
6525 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6526 v8_str("donut"), v8::DEFAULT, v8::DontDelete)
6527 .FromJust());
6528 CHECK(GetGlobalProperty(&context, "obj2")
6529 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6530 v8_str("donut"), v8::DEFAULT, v8::DontDelete)
6531 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006532
6533 ExpectString("obj1.x", "x");
6534 ExpectString("obj2.x", "x");
6535
6536 ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
6537 ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
6538
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006539 CHECK(GetGlobalProperty(&context, "obj1")
6540 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6541 v8_str("donut"))
6542 .IsNothing());
6543 CHECK(GetGlobalProperty(&context, "obj2")
6544 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6545 v8_str("donut"))
6546 .IsNothing());
Leon Clarkef7060e22010-06-03 12:02:55 +01006547
6548 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006549 v8::TryCatch try_catch(isolate);
6550 CompileRun(
6551 "Object.defineProperty(obj1, 'x',"
Leon Clarkef7060e22010-06-03 12:02:55 +01006552 "{get: function() { return 'func'; }})");
6553 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006554 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006555 CHECK_EQ(
6556 0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
Leon Clarkef7060e22010-06-03 12:02:55 +01006557 }
6558 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006559 v8::TryCatch try_catch(isolate);
6560 CompileRun(
6561 "Object.defineProperty(obj2, 'x',"
Leon Clarkef7060e22010-06-03 12:02:55 +01006562 "{get: function() { return 'func'; }})");
6563 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006564 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006565 CHECK_EQ(
6566 0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
Leon Clarkef7060e22010-06-03 12:02:55 +01006567 }
6568}
6569
6570
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006571static void Get239Value(Local<Name> name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006572 const v8::PropertyCallbackInfo<v8::Value>& info) {
Leon Clarkef7060e22010-06-03 12:02:55 +01006573 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006574 CHECK(info.Data()
6575 ->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("donut"))
6576 .FromJust());
6577 CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("239"))
6578 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006579 info.GetReturnValue().Set(name);
Leon Clarkef7060e22010-06-03 12:02:55 +01006580}
6581
6582
6583THREADED_TEST(ElementAPIAccessor) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006584 v8::Isolate* isolate = CcTest::isolate();
6585 v8::HandleScope scope(isolate);
6586 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Leon Clarkef7060e22010-06-03 12:02:55 +01006587 LocalContext context;
6588
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006589 CHECK(context->Global()
6590 ->Set(context.local(), v8_str("obj1"),
6591 templ->NewInstance(context.local()).ToLocalChecked())
6592 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006593 CompileRun("var obj2 = {};");
6594
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006595 CHECK(GetGlobalProperty(&context, "obj1")
6596 ->SetAccessor(context.local(), v8_str("239"), Get239Value, NULL,
6597 v8_str("donut"))
6598 .FromJust());
6599 CHECK(GetGlobalProperty(&context, "obj2")
6600 ->SetAccessor(context.local(), v8_str("239"), Get239Value, NULL,
6601 v8_str("donut"))
6602 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006603
6604 ExpectString("obj1[239]", "239");
6605 ExpectString("obj2[239]", "239");
6606 ExpectString("obj1['239']", "239");
6607 ExpectString("obj2['239']", "239");
6608}
6609
Steve Blocka7e24c12009-10-30 11:49:00 +00006610
6611v8::Persistent<Value> xValue;
6612
6613
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006614static void SetXValue(Local<Name> name, Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006615 const v8::PropertyCallbackInfo<void>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006616 Local<Context> context = info.GetIsolate()->GetCurrentContext();
6617 CHECK(value->Equals(context, v8_num(4)).FromJust());
6618 CHECK(info.Data()->Equals(context, v8_str("donut")).FromJust());
6619 CHECK(name->Equals(context, v8_str("x")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006620 CHECK(xValue.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006621 xValue.Reset(info.GetIsolate(), value);
Steve Blocka7e24c12009-10-30 11:49:00 +00006622}
6623
6624
6625THREADED_TEST(SimplePropertyWrite) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006626 v8::Isolate* isolate = CcTest::isolate();
6627 v8::HandleScope scope(isolate);
6628 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00006629 templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
6630 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006631 CHECK(context->Global()
6632 ->Set(context.local(), v8_str("obj"),
6633 templ->NewInstance(context.local()).ToLocalChecked())
6634 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006635 Local<Script> script = v8_compile("obj.x = 4");
Steve Blocka7e24c12009-10-30 11:49:00 +00006636 for (int i = 0; i < 10; i++) {
6637 CHECK(xValue.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006638 script->Run(context.local()).ToLocalChecked();
6639 CHECK(v8_num(4)
6640 ->Equals(context.local(),
6641 Local<Value>::New(CcTest::isolate(), xValue))
6642 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006643 xValue.Reset();
Steve Blocka7e24c12009-10-30 11:49:00 +00006644 }
6645}
6646
6647
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006648THREADED_TEST(SetterOnly) {
6649 v8::Isolate* isolate = CcTest::isolate();
6650 v8::HandleScope scope(isolate);
6651 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6652 templ->SetAccessor(v8_str("x"), NULL, SetXValue, v8_str("donut"));
6653 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006654 CHECK(context->Global()
6655 ->Set(context.local(), v8_str("obj"),
6656 templ->NewInstance(context.local()).ToLocalChecked())
6657 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006658 Local<Script> script = v8_compile("obj.x = 4; obj.x");
6659 for (int i = 0; i < 10; i++) {
6660 CHECK(xValue.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006661 script->Run(context.local()).ToLocalChecked();
6662 CHECK(v8_num(4)
6663 ->Equals(context.local(),
6664 Local<Value>::New(CcTest::isolate(), xValue))
6665 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006666 xValue.Reset();
6667 }
6668}
6669
6670
6671THREADED_TEST(NoAccessors) {
6672 v8::Isolate* isolate = CcTest::isolate();
6673 v8::HandleScope scope(isolate);
6674 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006675 templ->SetAccessor(v8_str("x"), static_cast<v8::AccessorGetterCallback>(NULL),
6676 NULL, v8_str("donut"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006677 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006678 CHECK(context->Global()
6679 ->Set(context.local(), v8_str("obj"),
6680 templ->NewInstance(context.local()).ToLocalChecked())
6681 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006682 Local<Script> script = v8_compile("obj.x = 4; obj.x");
6683 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006684 script->Run(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006685 }
6686}
6687
6688
Steve Blocka7e24c12009-10-30 11:49:00 +00006689THREADED_TEST(MultiContexts) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006690 v8::Isolate* isolate = CcTest::isolate();
6691 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006692 v8::Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6693 templ->Set(v8_str("dummy"),
6694 v8::FunctionTemplate::New(isolate, DummyCallHandler));
Steve Blocka7e24c12009-10-30 11:49:00 +00006695
6696 Local<String> password = v8_str("Password");
6697
6698 // Create an environment
6699 LocalContext context0(0, templ);
6700 context0->SetSecurityToken(password);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006701 v8::Local<v8::Object> global0 = context0->Global();
6702 CHECK(global0->Set(context0.local(), v8_str("custom"), v8_num(1234))
6703 .FromJust());
6704 CHECK_EQ(1234, global0->Get(context0.local(), v8_str("custom"))
6705 .ToLocalChecked()
6706 ->Int32Value(context0.local())
6707 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006708
6709 // Create an independent environment
6710 LocalContext context1(0, templ);
6711 context1->SetSecurityToken(password);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006712 v8::Local<v8::Object> global1 = context1->Global();
6713 CHECK(global1->Set(context1.local(), v8_str("custom"), v8_num(1234))
6714 .FromJust());
6715 CHECK(!global0->Equals(context1.local(), global1).FromJust());
6716 CHECK_EQ(1234, global0->Get(context1.local(), v8_str("custom"))
6717 .ToLocalChecked()
6718 ->Int32Value(context0.local())
6719 .FromJust());
6720 CHECK_EQ(1234, global1->Get(context1.local(), v8_str("custom"))
6721 .ToLocalChecked()
6722 ->Int32Value(context1.local())
6723 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006724
6725 // Now create a new context with the old global
6726 LocalContext context2(0, templ, global1);
6727 context2->SetSecurityToken(password);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006728 v8::Local<v8::Object> global2 = context2->Global();
6729 CHECK(global1->Equals(context2.local(), global2).FromJust());
6730 CHECK_EQ(0, global1->Get(context2.local(), v8_str("custom"))
6731 .ToLocalChecked()
6732 ->Int32Value(context1.local())
6733 .FromJust());
6734 CHECK_EQ(0, global2->Get(context2.local(), v8_str("custom"))
6735 .ToLocalChecked()
6736 ->Int32Value(context2.local())
6737 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006738}
6739
6740
6741THREADED_TEST(FunctionPrototypeAcrossContexts) {
6742 // Make sure that functions created by cloning boilerplates cannot
6743 // communicate through their __proto__ field.
6744
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006745 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006746
6747 LocalContext env0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006748 v8::Local<v8::Object> global0 = env0->Global();
6749 v8::Local<v8::Object> object0 = global0->Get(env0.local(), v8_str("Object"))
6750 .ToLocalChecked()
6751 .As<v8::Object>();
6752 v8::Local<v8::Object> tostring0 =
6753 object0->Get(env0.local(), v8_str("toString"))
6754 .ToLocalChecked()
6755 .As<v8::Object>();
6756 v8::Local<v8::Object> proto0 =
6757 tostring0->Get(env0.local(), v8_str("__proto__"))
6758 .ToLocalChecked()
6759 .As<v8::Object>();
6760 CHECK(proto0->Set(env0.local(), v8_str("custom"), v8_num(1234)).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006761
6762 LocalContext env1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006763 v8::Local<v8::Object> global1 = env1->Global();
6764 v8::Local<v8::Object> object1 = global1->Get(env1.local(), v8_str("Object"))
6765 .ToLocalChecked()
6766 .As<v8::Object>();
6767 v8::Local<v8::Object> tostring1 =
6768 object1->Get(env1.local(), v8_str("toString"))
6769 .ToLocalChecked()
6770 .As<v8::Object>();
6771 v8::Local<v8::Object> proto1 =
6772 tostring1->Get(env1.local(), v8_str("__proto__"))
6773 .ToLocalChecked()
6774 .As<v8::Object>();
6775 CHECK(!proto1->Has(env1.local(), v8_str("custom")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006776}
6777
6778
6779THREADED_TEST(Regress892105) {
6780 // Make sure that object and array literals created by cloning
6781 // boilerplates cannot communicate through their __proto__
6782 // field. This is rather difficult to check, but we try to add stuff
6783 // to Object.prototype and Array.prototype and create a new
6784 // environment. This should succeed.
6785
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006786 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006787
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006788 Local<String> source = v8_str(
6789 "Object.prototype.obj = 1234;"
6790 "Array.prototype.arr = 4567;"
6791 "8901");
Steve Blocka7e24c12009-10-30 11:49:00 +00006792
6793 LocalContext env0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006794 Local<Script> script0 = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006795 CHECK_EQ(8901.0, script0->Run(env0.local())
6796 .ToLocalChecked()
6797 ->NumberValue(env0.local())
6798 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006799
6800 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006801 Local<Script> script1 = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006802 CHECK_EQ(8901.0, script1->Run(env1.local())
6803 .ToLocalChecked()
6804 ->NumberValue(env1.local())
6805 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006806}
6807
6808
Steve Blocka7e24c12009-10-30 11:49:00 +00006809THREADED_TEST(UndetectableObject) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006810 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006811 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006812
6813 Local<v8::FunctionTemplate> desc =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006814 v8::FunctionTemplate::New(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006815 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
6816
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006817 Local<v8::Object> obj = desc->GetFunction(env.local())
6818 .ToLocalChecked()
6819 ->NewInstance(env.local())
6820 .ToLocalChecked();
6821 CHECK(
6822 env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006823
6824 ExpectString("undetectable.toString()", "[object Object]");
6825 ExpectString("typeof undetectable", "undefined");
6826 ExpectString("typeof(undetectable)", "undefined");
6827 ExpectBoolean("typeof undetectable == 'undefined'", true);
6828 ExpectBoolean("typeof undetectable == 'object'", false);
6829 ExpectBoolean("if (undetectable) { true; } else { false; }", false);
6830 ExpectBoolean("!undetectable", true);
6831
6832 ExpectObject("true&&undetectable", obj);
6833 ExpectBoolean("false&&undetectable", false);
6834 ExpectBoolean("true||undetectable", true);
6835 ExpectObject("false||undetectable", obj);
6836
6837 ExpectObject("undetectable&&true", obj);
6838 ExpectObject("undetectable&&false", obj);
6839 ExpectBoolean("undetectable||true", true);
6840 ExpectBoolean("undetectable||false", false);
6841
6842 ExpectBoolean("undetectable==null", true);
6843 ExpectBoolean("null==undetectable", true);
6844 ExpectBoolean("undetectable==undefined", true);
6845 ExpectBoolean("undefined==undetectable", true);
6846 ExpectBoolean("undetectable==undetectable", true);
6847
6848
6849 ExpectBoolean("undetectable===null", false);
6850 ExpectBoolean("null===undetectable", false);
6851 ExpectBoolean("undetectable===undefined", false);
6852 ExpectBoolean("undefined===undetectable", false);
6853 ExpectBoolean("undetectable===undetectable", true);
6854}
6855
6856
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006857THREADED_TEST(VoidLiteral) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006858 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006859 v8::Isolate* isolate = env->GetIsolate();
6860 v8::HandleScope scope(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006861
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006862 Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006863 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
6864
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006865 Local<v8::Object> obj = desc->GetFunction(env.local())
6866 .ToLocalChecked()
6867 ->NewInstance(env.local())
6868 .ToLocalChecked();
6869 CHECK(
6870 env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006871
6872 ExpectBoolean("undefined == void 0", true);
6873 ExpectBoolean("undetectable == void 0", true);
6874 ExpectBoolean("null == void 0", true);
6875 ExpectBoolean("undefined === void 0", true);
6876 ExpectBoolean("undetectable === void 0", false);
6877 ExpectBoolean("null === void 0", false);
6878
6879 ExpectBoolean("void 0 == undefined", true);
6880 ExpectBoolean("void 0 == undetectable", true);
6881 ExpectBoolean("void 0 == null", true);
6882 ExpectBoolean("void 0 === undefined", true);
6883 ExpectBoolean("void 0 === undetectable", false);
6884 ExpectBoolean("void 0 === null", false);
6885
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006886 ExpectString(
6887 "(function() {"
6888 " try {"
6889 " return x === void 0;"
6890 " } catch(e) {"
6891 " return e.toString();"
6892 " }"
6893 "})()",
6894 "ReferenceError: x is not defined");
6895 ExpectString(
6896 "(function() {"
6897 " try {"
6898 " return void 0 === x;"
6899 " } catch(e) {"
6900 " return e.toString();"
6901 " }"
6902 "})()",
6903 "ReferenceError: x is not defined");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006904}
6905
Steve Block8defd9f2010-07-08 12:39:36 +01006906
6907THREADED_TEST(ExtensibleOnUndetectable) {
Steve Block8defd9f2010-07-08 12:39:36 +01006908 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006909 v8::Isolate* isolate = env->GetIsolate();
6910 v8::HandleScope scope(isolate);
Steve Block8defd9f2010-07-08 12:39:36 +01006911
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006912 Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
Steve Block8defd9f2010-07-08 12:39:36 +01006913 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
6914
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006915 Local<v8::Object> obj = desc->GetFunction(env.local())
6916 .ToLocalChecked()
6917 ->NewInstance(env.local())
6918 .ToLocalChecked();
6919 CHECK(
6920 env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +01006921
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006922 Local<String> source = v8_str(
6923 "undetectable.x = 42;"
6924 "undetectable.x");
Steve Block8defd9f2010-07-08 12:39:36 +01006925
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006926 Local<Script> script = v8_compile(source);
Steve Block8defd9f2010-07-08 12:39:36 +01006927
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006928 CHECK(v8::Integer::New(isolate, 42)
6929 ->Equals(env.local(), script->Run(env.local()).ToLocalChecked())
6930 .FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +01006931
6932 ExpectBoolean("Object.isExtensible(undetectable)", true);
6933
6934 source = v8_str("Object.preventExtensions(undetectable);");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006935 script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006936 script->Run(env.local()).ToLocalChecked();
Steve Block8defd9f2010-07-08 12:39:36 +01006937 ExpectBoolean("Object.isExtensible(undetectable)", false);
6938
6939 source = v8_str("undetectable.y = 2000;");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006940 script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006941 script->Run(env.local()).ToLocalChecked();
Steve Block44f0eee2011-05-26 01:26:41 +01006942 ExpectBoolean("undetectable.y == undefined", true);
Steve Block8defd9f2010-07-08 12:39:36 +01006943}
6944
6945
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006946// The point of this test is type checking. We run it only so compilers
6947// don't complain about an unused function.
6948TEST(PersistentHandles) {
6949 LocalContext env;
6950 v8::Isolate* isolate = CcTest::isolate();
6951 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00006952 Local<String> str = v8_str("foo");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006953 v8::Persistent<String> p_str(isolate, str);
6954 p_str.Reset();
6955 Local<Script> scr = v8_compile("");
6956 v8::Persistent<Script> p_scr(isolate, scr);
6957 p_scr.Reset();
6958 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6959 v8::Persistent<ObjectTemplate> p_templ(isolate, templ);
6960 p_templ.Reset();
Steve Blocka7e24c12009-10-30 11:49:00 +00006961}
6962
6963
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006964static void HandleLogDelegator(
6965 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006966 ApiTestFuzzer::Fuzz();
Steve Blocka7e24c12009-10-30 11:49:00 +00006967}
6968
6969
6970THREADED_TEST(GlobalObjectTemplate) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006971 v8::Isolate* isolate = CcTest::isolate();
6972 v8::HandleScope handle_scope(isolate);
6973 Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00006974 global_template->Set(v8_str("JSNI_Log"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006975 v8::FunctionTemplate::New(isolate, HandleLogDelegator));
6976 v8::Local<Context> context = Context::New(isolate, 0, global_template);
Steve Blocka7e24c12009-10-30 11:49:00 +00006977 Context::Scope context_scope(context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006978 CompileRun("JSNI_Log('LOG')");
Steve Blocka7e24c12009-10-30 11:49:00 +00006979}
6980
6981
6982static const char* kSimpleExtensionSource =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006983 "function Foo() {"
6984 " return 4;"
6985 "}";
Steve Blocka7e24c12009-10-30 11:49:00 +00006986
6987
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006988TEST(SimpleExtensions) {
6989 v8::HandleScope handle_scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006990 v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006991 const char* extension_names[] = {"simpletest"};
Steve Blocka7e24c12009-10-30 11:49:00 +00006992 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006993 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Steve Blocka7e24c12009-10-30 11:49:00 +00006994 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006995 v8::Local<Value> result = CompileRun("Foo()");
6996 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
6997 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006998}
6999
7000
7001static const char* kStackTraceFromExtensionSource =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007002 "function foo() {"
7003 " throw new Error();"
7004 "}"
7005 "function bar() {"
7006 " foo();"
7007 "}";
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007008
7009
7010TEST(StackTraceInExtension) {
7011 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007012 v8::RegisterExtension(
7013 new Extension("stacktracetest", kStackTraceFromExtensionSource));
7014 const char* extension_names[] = {"stacktracetest"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007015 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007016 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007017 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007018 CompileRun(
7019 "function user() { bar(); }"
7020 "var error;"
7021 "try{ user(); } catch (e) { error = e; }");
7022 CHECK_EQ(-1, v8_run_int32value(v8_compile("error.stack.indexOf('foo')")));
7023 CHECK_EQ(-1, v8_run_int32value(v8_compile("error.stack.indexOf('bar')")));
7024 CHECK_NE(-1, v8_run_int32value(v8_compile("error.stack.indexOf('user')")));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007025}
7026
7027
7028TEST(NullExtensions) {
7029 v8::HandleScope handle_scope(CcTest::isolate());
7030 v8::RegisterExtension(new Extension("nulltest", NULL));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007031 const char* extension_names[] = {"nulltest"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007032 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007033 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007034 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007035 v8::Local<Value> result = CompileRun("1+3");
7036 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
7037 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007038}
7039
7040
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007041static const char* kEmbeddedExtensionSource =
7042 "function Ret54321(){return 54321;}~~@@$"
7043 "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
7044static const int kEmbeddedExtensionSourceValidLen = 34;
7045
7046
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007047TEST(ExtensionMissingSourceLength) {
7048 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007049 v8::RegisterExtension(
7050 new Extension("srclentest_fail", kEmbeddedExtensionSource));
7051 const char* extension_names[] = {"srclentest_fail"};
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007052 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007053 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
7054 CHECK(0 == *context);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007055}
7056
7057
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007058TEST(ExtensionWithSourceLength) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007059 for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
7060 source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007061 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007062 i::ScopedVector<char> extension_name(32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007063 i::SNPrintF(extension_name, "ext #%d", source_len);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007064 v8::RegisterExtension(new Extension(
7065 extension_name.start(), kEmbeddedExtensionSource, 0, 0, source_len));
7066 const char* extension_names[1] = {extension_name.start()};
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007067 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007068 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007069 if (source_len == kEmbeddedExtensionSourceValidLen) {
7070 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007071 v8::Local<Value> result = CompileRun("Ret54321()");
7072 CHECK(v8::Integer::New(CcTest::isolate(), 54321)
7073 ->Equals(context, result)
7074 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007075 } else {
7076 // Anything but exactly the right length should fail to compile.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007077 CHECK(0 == *context);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007078 }
7079 }
7080}
7081
7082
Steve Blocka7e24c12009-10-30 11:49:00 +00007083static const char* kEvalExtensionSource1 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007084 "function UseEval1() {"
7085 " var x = 42;"
7086 " return eval('x');"
7087 "}";
Steve Blocka7e24c12009-10-30 11:49:00 +00007088
7089
7090static const char* kEvalExtensionSource2 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007091 "(function() {"
7092 " var x = 42;"
7093 " function e() {"
7094 " return eval('x');"
7095 " }"
7096 " this.UseEval2 = e;"
7097 "})()";
Steve Blocka7e24c12009-10-30 11:49:00 +00007098
7099
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007100TEST(UseEvalFromExtension) {
7101 v8::HandleScope handle_scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007102 v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
7103 v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007104 const char* extension_names[] = {"evaltest1", "evaltest2"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007105 v8::ExtensionConfiguration extensions(2, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007106 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Steve Blocka7e24c12009-10-30 11:49:00 +00007107 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007108 v8::Local<Value> result = CompileRun("UseEval1()");
7109 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
7110 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007111 result = CompileRun("UseEval2()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007112 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
7113 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007114}
7115
7116
7117static const char* kWithExtensionSource1 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007118 "function UseWith1() {"
7119 " var x = 42;"
7120 " with({x:87}) { return x; }"
7121 "}";
Steve Blocka7e24c12009-10-30 11:49:00 +00007122
7123
7124static const char* kWithExtensionSource2 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007125 "(function() {"
7126 " var x = 42;"
7127 " function e() {"
7128 " with ({x:87}) { return x; }"
7129 " }"
7130 " this.UseWith2 = e;"
7131 "})()";
Steve Blocka7e24c12009-10-30 11:49:00 +00007132
7133
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007134TEST(UseWithFromExtension) {
7135 v8::HandleScope handle_scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007136 v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
7137 v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007138 const char* extension_names[] = {"withtest1", "withtest2"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007139 v8::ExtensionConfiguration extensions(2, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007140 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Steve Blocka7e24c12009-10-30 11:49:00 +00007141 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007142 v8::Local<Value> result = CompileRun("UseWith1()");
7143 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 87))
7144 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007145 result = CompileRun("UseWith2()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007146 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 87))
7147 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007148}
7149
7150
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007151TEST(AutoExtensions) {
7152 v8::HandleScope handle_scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007153 Extension* extension = new Extension("autotest", kSimpleExtensionSource);
7154 extension->set_auto_enable(true);
7155 v8::RegisterExtension(extension);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007156 v8::Local<Context> context = Context::New(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007157 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007158 v8::Local<Value> result = CompileRun("Foo()");
7159 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
7160 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007161}
7162
7163
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007164static const char* kSyntaxErrorInExtensionSource = "[";
Steve Blockd0582a62009-12-15 09:54:21 +00007165
7166
7167// Test that a syntax error in an extension does not cause a fatal
7168// error but results in an empty context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007169TEST(SyntaxErrorExtensions) {
7170 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007171 v8::RegisterExtension(
7172 new Extension("syntaxerror", kSyntaxErrorInExtensionSource));
7173 const char* extension_names[] = {"syntaxerror"};
Steve Blockd0582a62009-12-15 09:54:21 +00007174 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007175 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Steve Blockd0582a62009-12-15 09:54:21 +00007176 CHECK(context.IsEmpty());
7177}
7178
7179
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007180static const char* kExceptionInExtensionSource = "throw 42";
Steve Blockd0582a62009-12-15 09:54:21 +00007181
7182
7183// Test that an exception when installing an extension does not cause
7184// a fatal error but results in an empty context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007185TEST(ExceptionExtensions) {
7186 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007187 v8::RegisterExtension(
7188 new Extension("exception", kExceptionInExtensionSource));
7189 const char* extension_names[] = {"exception"};
Steve Blockd0582a62009-12-15 09:54:21 +00007190 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007191 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Steve Blockd0582a62009-12-15 09:54:21 +00007192 CHECK(context.IsEmpty());
7193}
7194
7195
Iain Merrick9ac36c92010-09-13 15:29:50 +01007196static const char* kNativeCallInExtensionSource =
7197 "function call_runtime_last_index_of(x) {"
7198 " return %StringLastIndexOf(x, 'bob', 10);"
7199 "}";
7200
7201
7202static const char* kNativeCallTest =
7203 "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
7204
7205// Test that a native runtime calls are supported in extensions.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007206TEST(NativeCallInExtensions) {
7207 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007208 v8::RegisterExtension(
7209 new Extension("nativecall", kNativeCallInExtensionSource));
7210 const char* extension_names[] = {"nativecall"};
Iain Merrick9ac36c92010-09-13 15:29:50 +01007211 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007212 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Iain Merrick9ac36c92010-09-13 15:29:50 +01007213 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007214 v8::Local<Value> result = CompileRun(kNativeCallTest);
7215 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 3))
7216 .FromJust());
Iain Merrick9ac36c92010-09-13 15:29:50 +01007217}
7218
7219
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007220class NativeFunctionExtension : public Extension {
7221 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007222 NativeFunctionExtension(const char* name, const char* source,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007223 v8::FunctionCallback fun = &Echo)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007224 : Extension(name, source), function_(fun) {}
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007225
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007226 virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
7227 v8::Isolate* isolate, v8::Local<v8::String> name) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007228 return v8::FunctionTemplate::New(isolate, function_);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007229 }
7230
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007231 static void Echo(const v8::FunctionCallbackInfo<v8::Value>& args) {
7232 if (args.Length() >= 1) args.GetReturnValue().Set(args[0]);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007233 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007234
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007235 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007236 v8::FunctionCallback function_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007237};
7238
7239
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007240TEST(NativeFunctionDeclaration) {
7241 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007242 const char* name = "nativedecl";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007243 v8::RegisterExtension(
7244 new NativeFunctionExtension(name, "native function foo();"));
7245 const char* extension_names[] = {name};
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007246 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007247 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007248 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007249 v8::Local<Value> result = CompileRun("foo(42);");
7250 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
7251 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007252}
7253
7254
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007255TEST(NativeFunctionDeclarationError) {
7256 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007257 const char* name = "nativedeclerr";
7258 // Syntax error in extension code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007259 v8::RegisterExtension(
7260 new NativeFunctionExtension(name, "native\nfunction foo();"));
7261 const char* extension_names[] = {name};
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007262 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007263 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007264 CHECK(context.IsEmpty());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007265}
7266
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007267
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007268TEST(NativeFunctionDeclarationErrorEscape) {
7269 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007270 const char* name = "nativedeclerresc";
7271 // Syntax error in extension code - escape code in "native" means that
7272 // it's not treated as a keyword.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007273 v8::RegisterExtension(
7274 new NativeFunctionExtension(name, "nativ\\u0065 function foo();"));
7275 const char* extension_names[] = {name};
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007276 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007277 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007278 CHECK(context.IsEmpty());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007279}
7280
7281
Steve Blocka7e24c12009-10-30 11:49:00 +00007282static void CheckDependencies(const char* name, const char* expected) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007283 v8::HandleScope handle_scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007284 v8::ExtensionConfiguration config(1, &name);
7285 LocalContext context(&config);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007286 CHECK(
7287 v8_str(expected)
7288 ->Equals(context.local(), context->Global()
7289 ->Get(context.local(), v8_str("loaded"))
7290 .ToLocalChecked())
7291 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007292}
7293
7294
7295/*
7296 * Configuration:
7297 *
7298 * /-- B <--\
7299 * A <- -- D <-- E
7300 * \-- C <--/
7301 */
7302THREADED_TEST(ExtensionDependency) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007303 static const char* kEDeps[] = {"D"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007304 v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007305 static const char* kDDeps[] = {"B", "C"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007306 v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007307 static const char* kBCDeps[] = {"A"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007308 v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
7309 v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
7310 v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
7311 CheckDependencies("A", "undefinedA");
7312 CheckDependencies("B", "undefinedAB");
7313 CheckDependencies("C", "undefinedAC");
7314 CheckDependencies("D", "undefinedABCD");
7315 CheckDependencies("E", "undefinedABCDE");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007316 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007317 static const char* exts[2] = {"C", "E"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007318 v8::ExtensionConfiguration config(2, exts);
7319 LocalContext context(&config);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007320 CHECK(
7321 v8_str("undefinedACBDE")
7322 ->Equals(context.local(), context->Global()
7323 ->Get(context.local(), v8_str("loaded"))
7324 .ToLocalChecked())
7325 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007326}
7327
7328
7329static const char* kExtensionTestScript =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007330 "native function A();"
7331 "native function B();"
7332 "native function C();"
7333 "function Foo(i) {"
7334 " if (i == 0) return A();"
7335 " if (i == 1) return B();"
7336 " if (i == 2) return C();"
7337 "}";
Steve Blocka7e24c12009-10-30 11:49:00 +00007338
7339
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007340static void CallFun(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007341 ApiTestFuzzer::Fuzz();
Leon Clarkee46be812010-01-19 14:06:41 +00007342 if (args.IsConstructCall()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007343 CHECK(args.This()
7344 ->Set(args.GetIsolate()->GetCurrentContext(), v8_str("data"),
7345 args.Data())
7346 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007347 args.GetReturnValue().SetNull();
7348 return;
Leon Clarkee46be812010-01-19 14:06:41 +00007349 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007350 args.GetReturnValue().Set(args.Data());
Steve Blocka7e24c12009-10-30 11:49:00 +00007351}
7352
7353
7354class FunctionExtension : public Extension {
7355 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007356 FunctionExtension() : Extension("functiontest", kExtensionTestScript) {}
7357 virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
7358 v8::Isolate* isolate, v8::Local<String> name);
Steve Blocka7e24c12009-10-30 11:49:00 +00007359};
7360
7361
7362static int lookup_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007363v8::Local<v8::FunctionTemplate> FunctionExtension::GetNativeFunctionTemplate(
7364 v8::Isolate* isolate, v8::Local<String> name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007365 lookup_count++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007366 if (name->Equals(isolate->GetCurrentContext(), v8_str("A")).FromJust()) {
7367 return v8::FunctionTemplate::New(isolate, CallFun,
7368 v8::Integer::New(isolate, 8));
7369 } else if (name->Equals(isolate->GetCurrentContext(), v8_str("B"))
7370 .FromJust()) {
7371 return v8::FunctionTemplate::New(isolate, CallFun,
7372 v8::Integer::New(isolate, 7));
7373 } else if (name->Equals(isolate->GetCurrentContext(), v8_str("C"))
7374 .FromJust()) {
7375 return v8::FunctionTemplate::New(isolate, CallFun,
7376 v8::Integer::New(isolate, 6));
Steve Blocka7e24c12009-10-30 11:49:00 +00007377 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007378 return v8::Local<v8::FunctionTemplate>();
Steve Blocka7e24c12009-10-30 11:49:00 +00007379 }
7380}
7381
7382
7383THREADED_TEST(FunctionLookup) {
7384 v8::RegisterExtension(new FunctionExtension());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007385 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007386 static const char* exts[1] = {"functiontest"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007387 v8::ExtensionConfiguration config(1, exts);
7388 LocalContext context(&config);
7389 CHECK_EQ(3, lookup_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007390 CHECK(v8::Integer::New(CcTest::isolate(), 8)
7391 ->Equals(context.local(), CompileRun("Foo(0)"))
7392 .FromJust());
7393 CHECK(v8::Integer::New(CcTest::isolate(), 7)
7394 ->Equals(context.local(), CompileRun("Foo(1)"))
7395 .FromJust());
7396 CHECK(v8::Integer::New(CcTest::isolate(), 6)
7397 ->Equals(context.local(), CompileRun("Foo(2)"))
7398 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007399}
7400
7401
Leon Clarkee46be812010-01-19 14:06:41 +00007402THREADED_TEST(NativeFunctionConstructCall) {
7403 v8::RegisterExtension(new FunctionExtension());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007404 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007405 static const char* exts[1] = {"functiontest"};
Leon Clarkee46be812010-01-19 14:06:41 +00007406 v8::ExtensionConfiguration config(1, exts);
7407 LocalContext context(&config);
Leon Clarked91b9f72010-01-27 17:25:45 +00007408 for (int i = 0; i < 10; i++) {
7409 // Run a few times to ensure that allocation of objects doesn't
7410 // change behavior of a constructor function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007411 CHECK(v8::Integer::New(CcTest::isolate(), 8)
7412 ->Equals(context.local(), CompileRun("(new A()).data"))
7413 .FromJust());
7414 CHECK(v8::Integer::New(CcTest::isolate(), 7)
7415 ->Equals(context.local(), CompileRun("(new B()).data"))
7416 .FromJust());
7417 CHECK(v8::Integer::New(CcTest::isolate(), 6)
7418 ->Equals(context.local(), CompileRun("(new C()).data"))
7419 .FromJust());
Leon Clarked91b9f72010-01-27 17:25:45 +00007420 }
Leon Clarkee46be812010-01-19 14:06:41 +00007421}
7422
7423
Steve Blocka7e24c12009-10-30 11:49:00 +00007424static const char* last_location;
7425static const char* last_message;
7426void StoringErrorCallback(const char* location, const char* message) {
7427 if (last_location == NULL) {
7428 last_location = location;
7429 last_message = message;
7430 }
7431}
7432
7433
7434// ErrorReporting creates a circular extensions configuration and
7435// tests that the fatal error handler gets called. This renders V8
7436// unusable and therefore this test cannot be run in parallel.
7437TEST(ErrorReporting) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007438 CcTest::isolate()->SetFatalErrorHandler(StoringErrorCallback);
7439 static const char* aDeps[] = {"B"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007440 v8::RegisterExtension(new Extension("A", "", 1, aDeps));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007441 static const char* bDeps[] = {"A"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007442 v8::RegisterExtension(new Extension("B", "", 1, bDeps));
7443 last_location = NULL;
7444 v8::ExtensionConfiguration config(1, bDeps);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007445 v8::Local<Context> context = Context::New(CcTest::isolate(), &config);
Steve Blocka7e24c12009-10-30 11:49:00 +00007446 CHECK(context.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007447 CHECK(last_location);
Steve Blocka7e24c12009-10-30 11:49:00 +00007448}
7449
7450
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007451static void MissingScriptInfoMessageListener(v8::Local<v8::Message> message,
7452 v8::Local<Value> data) {
7453 v8::Isolate* isolate = CcTest::isolate();
7454 Local<Context> context = isolate->GetCurrentContext();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007455 CHECK(message->GetScriptOrigin().ResourceName()->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007456 CHECK(v8::Undefined(isolate)
7457 ->Equals(context, message->GetScriptOrigin().ResourceName())
7458 .FromJust());
7459 message->GetLineNumber(context).FromJust();
7460 message->GetSourceLine(context).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00007461}
7462
7463
7464THREADED_TEST(ErrorWithMissingScriptInfo) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007465 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007466 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007467 context->GetIsolate()->AddMessageListener(MissingScriptInfoMessageListener);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007468 CompileRun("throw Error()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007469 context->GetIsolate()->RemoveMessageListeners(
7470 MissingScriptInfoMessageListener);
Steve Blocka7e24c12009-10-30 11:49:00 +00007471}
7472
7473
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007474struct FlagAndPersistent {
7475 bool flag;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007476 v8::Global<v8::Object> handle;
Steve Blocka7e24c12009-10-30 11:49:00 +00007477};
7478
Steve Blocka7e24c12009-10-30 11:49:00 +00007479
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007480static void SetFlag(const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007481 data.GetParameter()->flag = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007482 data.GetParameter()->handle.Reset();
Steve Blockd0582a62009-12-15 09:54:21 +00007483}
7484
Steve Blockd0582a62009-12-15 09:54:21 +00007485
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007486static void IndependentWeakHandle(bool global_gc, bool interlinked) {
7487 v8::Isolate* iso = CcTest::isolate();
7488 v8::HandleScope scope(iso);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007489 v8::Local<Context> context = Context::New(iso);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007490 Context::Scope context_scope(context);
7491
7492 FlagAndPersistent object_a, object_b;
7493
7494 intptr_t big_heap_size;
7495
7496 {
7497 v8::HandleScope handle_scope(iso);
7498 Local<Object> a(v8::Object::New(iso));
7499 Local<Object> b(v8::Object::New(iso));
7500 object_a.handle.Reset(iso, a);
7501 object_b.handle.Reset(iso, b);
7502 if (interlinked) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007503 a->Set(context, v8_str("x"), b).FromJust();
7504 b->Set(context, v8_str("x"), a).FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007505 }
7506 if (global_gc) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007507 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007508 } else {
7509 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
7510 }
7511 // We are relying on this creating a big flag array and reserving the space
7512 // up front.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007513 v8::Local<Value> big_array = CompileRun("new Array(5000)");
7514 a->Set(context, v8_str("y"), big_array).FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007515 big_heap_size = CcTest::heap()->SizeOfObjects();
7516 }
7517
7518 object_a.flag = false;
7519 object_b.flag = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007520 object_a.handle.SetWeak(&object_a, &SetFlag,
7521 v8::WeakCallbackType::kParameter);
7522 object_b.handle.SetWeak(&object_b, &SetFlag,
7523 v8::WeakCallbackType::kParameter);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007524 CHECK(!object_b.handle.IsIndependent());
7525 object_a.handle.MarkIndependent();
7526 object_b.handle.MarkIndependent();
7527 CHECK(object_b.handle.IsIndependent());
7528 if (global_gc) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007529 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007530 } else {
7531 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
7532 }
7533 // A single GC should be enough to reclaim the memory, since we are using
7534 // phantom handles.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007535 CHECK_LT(CcTest::heap()->SizeOfObjects(), big_heap_size - 20000);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007536 CHECK(object_a.flag);
7537 CHECK(object_b.flag);
7538}
7539
7540
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007541TEST(IndependentWeakHandle) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007542 IndependentWeakHandle(false, false);
7543 IndependentWeakHandle(false, true);
7544 IndependentWeakHandle(true, false);
7545 IndependentWeakHandle(true, true);
7546}
7547
7548
7549class Trivial {
7550 public:
7551 explicit Trivial(int x) : x_(x) {}
7552
7553 int x() { return x_; }
7554 void set_x(int x) { x_ = x; }
7555
7556 private:
7557 int x_;
7558};
7559
7560
7561class Trivial2 {
7562 public:
7563 Trivial2(int x, int y) : y_(y), x_(x) {}
7564
7565 int x() { return x_; }
7566 void set_x(int x) { x_ = x; }
7567
7568 int y() { return y_; }
7569 void set_y(int y) { y_ = y; }
7570
7571 private:
7572 int y_;
7573 int x_;
7574};
7575
7576
7577void CheckInternalFields(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007578 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
7579 v8::Persistent<v8::Object>* handle = data.GetParameter();
7580 handle->Reset();
7581 Trivial* t1 = reinterpret_cast<Trivial*>(data.GetInternalField(0));
7582 Trivial2* t2 = reinterpret_cast<Trivial2*>(data.GetInternalField(1));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007583 CHECK_EQ(42, t1->x());
7584 CHECK_EQ(103, t2->x());
7585 t1->set_x(1729);
7586 t2->set_x(33550336);
7587}
7588
7589
7590void InternalFieldCallback(bool global_gc) {
7591 LocalContext env;
7592 v8::Isolate* isolate = env->GetIsolate();
7593 v8::HandleScope scope(isolate);
7594
7595 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
7596 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
7597 Trivial* t1;
7598 Trivial2* t2;
7599 instance_templ->SetInternalFieldCount(2);
7600 {
7601 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007602 Local<v8::Object> obj = templ->GetFunction(env.local())
7603 .ToLocalChecked()
7604 ->NewInstance(env.local())
7605 .ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007606 v8::Persistent<v8::Object> handle(isolate, obj);
7607 CHECK_EQ(2, obj->InternalFieldCount());
7608 CHECK(obj->GetInternalField(0)->IsUndefined());
7609 t1 = new Trivial(42);
7610 t2 = new Trivial2(103, 9);
7611
7612 obj->SetAlignedPointerInInternalField(0, t1);
7613 t1 = reinterpret_cast<Trivial*>(obj->GetAlignedPointerFromInternalField(0));
7614 CHECK_EQ(42, t1->x());
7615
7616 obj->SetAlignedPointerInInternalField(1, t2);
7617 t2 =
7618 reinterpret_cast<Trivial2*>(obj->GetAlignedPointerFromInternalField(1));
7619 CHECK_EQ(103, t2->x());
7620
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007621 handle.SetWeak<v8::Persistent<v8::Object>>(
7622 &handle, CheckInternalFields, v8::WeakCallbackType::kInternalFields);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007623 if (!global_gc) {
7624 handle.MarkIndependent();
7625 }
7626 }
7627 if (global_gc) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007628 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007629 } else {
7630 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
7631 }
7632
7633 CHECK_EQ(1729, t1->x());
7634 CHECK_EQ(33550336, t2->x());
7635
7636 delete t1;
7637 delete t2;
7638}
7639
7640
7641THREADED_TEST(InternalFieldCallback) {
7642 InternalFieldCallback(false);
7643 InternalFieldCallback(true);
7644}
7645
7646
7647static void ResetUseValueAndSetFlag(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007648 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007649 // Blink will reset the handle, and then use the other handle, so they
7650 // can't use the same backing slot.
7651 data.GetParameter()->handle.Reset();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007652 data.GetParameter()->flag = true;
7653}
7654
7655
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007656void v8::internal::HeapTester::ResetWeakHandle(bool global_gc) {
7657 using v8::Context;
7658 using v8::Local;
7659 using v8::Object;
7660
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007661 v8::Isolate* iso = CcTest::isolate();
7662 v8::HandleScope scope(iso);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007663 v8::Local<Context> context = Context::New(iso);
Steve Blockd0582a62009-12-15 09:54:21 +00007664 Context::Scope context_scope(context);
7665
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007666 FlagAndPersistent object_a, object_b;
Steve Blockd0582a62009-12-15 09:54:21 +00007667
7668 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007669 v8::HandleScope handle_scope(iso);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007670 Local<Object> a(v8::Object::New(iso));
7671 Local<Object> b(v8::Object::New(iso));
7672 object_a.handle.Reset(iso, a);
7673 object_b.handle.Reset(iso, b);
7674 if (global_gc) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007675 CcTest::heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007676 } else {
7677 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
7678 }
Steve Blockd0582a62009-12-15 09:54:21 +00007679 }
7680
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007681 object_a.flag = false;
7682 object_b.flag = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007683 object_a.handle.SetWeak(&object_a, &ResetUseValueAndSetFlag,
7684 v8::WeakCallbackType::kParameter);
7685 object_b.handle.SetWeak(&object_b, &ResetUseValueAndSetFlag,
7686 v8::WeakCallbackType::kParameter);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007687 if (!global_gc) {
7688 object_a.handle.MarkIndependent();
7689 object_b.handle.MarkIndependent();
7690 CHECK(object_b.handle.IsIndependent());
7691 }
7692 if (global_gc) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007693 CcTest::heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007694 } else {
7695 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
7696 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007697 CHECK(object_a.flag);
7698 CHECK(object_b.flag);
Ben Murdoch257744e2011-11-30 15:57:28 +00007699}
Steve Blockd0582a62009-12-15 09:54:21 +00007700
Ben Murdoch257744e2011-11-30 15:57:28 +00007701
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007702THREADED_HEAP_TEST(ResetWeakHandle) {
7703 v8::internal::HeapTester::ResetWeakHandle(false);
7704 v8::internal::HeapTester::ResetWeakHandle(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007705}
7706
7707
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007708static void InvokeScavenge() { CcTest::heap()->CollectGarbage(i::NEW_SPACE); }
Ben Murdoch257744e2011-11-30 15:57:28 +00007709
7710
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007711static void InvokeMarkSweep() { CcTest::heap()->CollectAllGarbage(); }
Ben Murdoch257744e2011-11-30 15:57:28 +00007712
7713
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007714static void ForceScavenge2(
7715 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007716 data.GetParameter()->flag = true;
Ben Murdoch257744e2011-11-30 15:57:28 +00007717 InvokeScavenge();
7718}
7719
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007720static void ForceScavenge1(
7721 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007722 data.GetParameter()->handle.Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007723 data.SetSecondPassCallback(ForceScavenge2);
7724}
7725
7726
7727static void ForceMarkSweep2(
7728 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007729 data.GetParameter()->flag = true;
Ben Murdoch257744e2011-11-30 15:57:28 +00007730 InvokeMarkSweep();
7731}
7732
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007733static void ForceMarkSweep1(
7734 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
7735 data.GetParameter()->handle.Reset();
7736 data.SetSecondPassCallback(ForceMarkSweep2);
7737}
7738
Ben Murdoch257744e2011-11-30 15:57:28 +00007739
7740THREADED_TEST(GCFromWeakCallbacks) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007741 v8::Isolate* isolate = CcTest::isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007742 v8::Locker locker(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007743 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007744 v8::Local<Context> context = Context::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +00007745 Context::Scope context_scope(context);
7746
7747 static const int kNumberOfGCTypes = 2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007748 typedef v8::WeakCallbackInfo<FlagAndPersistent>::Callback Callback;
7749 Callback gc_forcing_callback[kNumberOfGCTypes] = {&ForceScavenge1,
7750 &ForceMarkSweep1};
Ben Murdoch257744e2011-11-30 15:57:28 +00007751
7752 typedef void (*GCInvoker)();
7753 GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
7754
7755 for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
7756 for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007757 FlagAndPersistent object;
Ben Murdoch257744e2011-11-30 15:57:28 +00007758 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007759 v8::HandleScope handle_scope(isolate);
7760 object.handle.Reset(isolate, v8::Object::New(isolate));
Ben Murdoch257744e2011-11-30 15:57:28 +00007761 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007762 object.flag = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007763 object.handle.SetWeak(&object, gc_forcing_callback[inner_gc],
7764 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007765 object.handle.MarkIndependent();
Ben Murdoch257744e2011-11-30 15:57:28 +00007766 invoke_gc[outer_gc]();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007767 EmptyMessageQueues(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007768 CHECK(object.flag);
Ben Murdoch257744e2011-11-30 15:57:28 +00007769 }
Steve Blockd0582a62009-12-15 09:54:21 +00007770 }
Ben Murdoch257744e2011-11-30 15:57:28 +00007771}
7772
7773
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007774v8::Local<Function> args_fun;
Steve Blocka7e24c12009-10-30 11:49:00 +00007775
7776
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007777static void ArgumentsTestCallback(
7778 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007779 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007780 v8::Isolate* isolate = args.GetIsolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007781 Local<Context> context = isolate->GetCurrentContext();
7782 CHECK(args_fun->Equals(context, args.Callee()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007783 CHECK_EQ(3, args.Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007784 CHECK(v8::Integer::New(isolate, 1)->Equals(context, args[0]).FromJust());
7785 CHECK(v8::Integer::New(isolate, 2)->Equals(context, args[1]).FromJust());
7786 CHECK(v8::Integer::New(isolate, 3)->Equals(context, args[2]).FromJust());
7787 CHECK(v8::Undefined(isolate)->Equals(context, args[3]).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007788 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007789 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +00007790}
7791
7792
7793THREADED_TEST(Arguments) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007794 v8::Isolate* isolate = CcTest::isolate();
7795 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007796 v8::Local<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007797 global->Set(v8_str("f"),
7798 v8::FunctionTemplate::New(isolate, ArgumentsTestCallback));
Steve Blocka7e24c12009-10-30 11:49:00 +00007799 LocalContext context(NULL, global);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007800 args_fun = context->Global()
7801 ->Get(context.local(), v8_str("f"))
7802 .ToLocalChecked()
7803 .As<Function>();
7804 v8_compile("f(1, 2, 3)")->Run(context.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00007805}
7806
7807
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007808static int p_getter_count;
7809static int p_getter_count2;
Steve Blocka7e24c12009-10-30 11:49:00 +00007810
7811
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007812static void PGetter(Local<Name> name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007813 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007814 ApiTestFuzzer::Fuzz();
7815 p_getter_count++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007816 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
7817 v8::Local<v8::Object> global = context->Global();
7818 CHECK(
7819 info.Holder()
7820 ->Equals(context, global->Get(context, v8_str("o1")).ToLocalChecked())
7821 .FromJust());
7822 if (name->Equals(context, v8_str("p1")).FromJust()) {
7823 CHECK(info.This()
7824 ->Equals(context,
7825 global->Get(context, v8_str("o1")).ToLocalChecked())
7826 .FromJust());
7827 } else if (name->Equals(context, v8_str("p2")).FromJust()) {
7828 CHECK(info.This()
7829 ->Equals(context,
7830 global->Get(context, v8_str("o2")).ToLocalChecked())
7831 .FromJust());
7832 } else if (name->Equals(context, v8_str("p3")).FromJust()) {
7833 CHECK(info.This()
7834 ->Equals(context,
7835 global->Get(context, v8_str("o3")).ToLocalChecked())
7836 .FromJust());
7837 } else if (name->Equals(context, v8_str("p4")).FromJust()) {
7838 CHECK(info.This()
7839 ->Equals(context,
7840 global->Get(context, v8_str("o4")).ToLocalChecked())
7841 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007842 }
Steve Blocka7e24c12009-10-30 11:49:00 +00007843}
7844
7845
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007846static void RunHolderTest(v8::Local<v8::ObjectTemplate> obj) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007847 ApiTestFuzzer::Fuzz();
7848 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007849 CHECK(context->Global()
7850 ->Set(context.local(), v8_str("o1"),
7851 obj->NewInstance(context.local()).ToLocalChecked())
7852 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007853 CompileRun(
7854 "o1.__proto__ = { };"
7855 "var o2 = { __proto__: o1 };"
7856 "var o3 = { __proto__: o2 };"
7857 "var o4 = { __proto__: o3 };"
7858 "for (var i = 0; i < 10; i++) o4.p4;"
7859 "for (var i = 0; i < 10; i++) o3.p3;"
7860 "for (var i = 0; i < 10; i++) o2.p2;"
7861 "for (var i = 0; i < 10; i++) o1.p1;");
7862}
7863
7864
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007865static void PGetter2(Local<Name> name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007866 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007867 ApiTestFuzzer::Fuzz();
7868 p_getter_count2++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007869 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
7870 v8::Local<v8::Object> global = context->Global();
7871 CHECK(
7872 info.Holder()
7873 ->Equals(context, global->Get(context, v8_str("o1")).ToLocalChecked())
7874 .FromJust());
7875 if (name->Equals(context, v8_str("p1")).FromJust()) {
7876 CHECK(info.This()
7877 ->Equals(context,
7878 global->Get(context, v8_str("o1")).ToLocalChecked())
7879 .FromJust());
7880 } else if (name->Equals(context, v8_str("p2")).FromJust()) {
7881 CHECK(info.This()
7882 ->Equals(context,
7883 global->Get(context, v8_str("o2")).ToLocalChecked())
7884 .FromJust());
7885 } else if (name->Equals(context, v8_str("p3")).FromJust()) {
7886 CHECK(info.This()
7887 ->Equals(context,
7888 global->Get(context, v8_str("o3")).ToLocalChecked())
7889 .FromJust());
7890 } else if (name->Equals(context, v8_str("p4")).FromJust()) {
7891 CHECK(info.This()
7892 ->Equals(context,
7893 global->Get(context, v8_str("o4")).ToLocalChecked())
7894 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007895 }
Steve Blocka7e24c12009-10-30 11:49:00 +00007896}
7897
7898
7899THREADED_TEST(GetterHolders) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007900 v8::Isolate* isolate = CcTest::isolate();
7901 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007902 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00007903 obj->SetAccessor(v8_str("p1"), PGetter);
7904 obj->SetAccessor(v8_str("p2"), PGetter);
7905 obj->SetAccessor(v8_str("p3"), PGetter);
7906 obj->SetAccessor(v8_str("p4"), PGetter);
7907 p_getter_count = 0;
7908 RunHolderTest(obj);
7909 CHECK_EQ(40, p_getter_count);
7910}
7911
7912
7913THREADED_TEST(PreInterceptorHolders) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007914 v8::Isolate* isolate = CcTest::isolate();
7915 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007916 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007917 obj->SetHandler(v8::NamedPropertyHandlerConfiguration(PGetter2));
Steve Blocka7e24c12009-10-30 11:49:00 +00007918 p_getter_count2 = 0;
7919 RunHolderTest(obj);
7920 CHECK_EQ(40, p_getter_count2);
7921}
7922
7923
7924THREADED_TEST(ObjectInstantiation) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007925 v8::Isolate* isolate = CcTest::isolate();
7926 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007927 v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00007928 templ->SetAccessor(v8_str("t"), PGetter2);
7929 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007930 CHECK(context->Global()
7931 ->Set(context.local(), v8_str("o"),
7932 templ->NewInstance(context.local()).ToLocalChecked())
7933 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007934 for (int i = 0; i < 100; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007935 v8::HandleScope inner_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007936 v8::Local<v8::Object> obj =
7937 templ->NewInstance(context.local()).ToLocalChecked();
7938 CHECK(!obj->Equals(context.local(), context->Global()
7939 ->Get(context.local(), v8_str("o"))
7940 .ToLocalChecked())
7941 .FromJust());
7942 CHECK(
7943 context->Global()->Set(context.local(), v8_str("o2"), obj).FromJust());
7944 v8::Local<Value> value = CompileRun("o.__proto__ === o2.__proto__");
7945 CHECK(v8::True(isolate)->Equals(context.local(), value).FromJust());
7946 CHECK(context->Global()->Set(context.local(), v8_str("o"), obj).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007947 }
7948}
7949
7950
Ben Murdochb0fe1622011-05-05 13:52:32 +01007951static int StrCmp16(uint16_t* a, uint16_t* b) {
7952 while (true) {
7953 if (*a == 0 && *b == 0) return 0;
7954 if (*a != *b) return 0 + *a - *b;
7955 a++;
7956 b++;
7957 }
7958}
7959
7960
7961static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
7962 while (true) {
7963 if (n-- == 0) return 0;
7964 if (*a == 0 && *b == 0) return 0;
7965 if (*a != *b) return 0 + *a - *b;
7966 a++;
7967 b++;
7968 }
7969}
7970
7971
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007972int GetUtf8Length(Local<String> str) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007973 int len = str->Utf8Length();
7974 if (len < 0) {
7975 i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007976 i::String::Flatten(istr);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007977 len = str->Utf8Length();
7978 }
7979 return len;
7980}
7981
7982
Steve Blocka7e24c12009-10-30 11:49:00 +00007983THREADED_TEST(StringWrite) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007984 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007985 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007986 v8::Local<String> str = v8_str("abcde");
Ben Murdochb0fe1622011-05-05 13:52:32 +01007987 // abc<Icelandic eth><Unicode snowman>.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007988 v8::Local<String> str2 = v8_str("abc\303\260\342\230\203");
7989 v8::Local<String> str3 =
7990 v8::String::NewFromUtf8(context->GetIsolate(), "abc\0def",
7991 v8::NewStringType::kNormal, 7)
7992 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007993 // "ab" + lead surrogate + "cd" + trail surrogate + "ef"
7994 uint16_t orphans[8] = { 0x61, 0x62, 0xd800, 0x63, 0x64, 0xdc00, 0x65, 0x66 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007995 v8::Local<String> orphans_str =
7996 v8::String::NewFromTwoByte(context->GetIsolate(), orphans,
7997 v8::NewStringType::kNormal, 8)
7998 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007999 // single lead surrogate
8000 uint16_t lead[1] = { 0xd800 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008001 v8::Local<String> lead_str =
8002 v8::String::NewFromTwoByte(context->GetIsolate(), lead,
8003 v8::NewStringType::kNormal, 1)
8004 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008005 // single trail surrogate
8006 uint16_t trail[1] = { 0xdc00 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008007 v8::Local<String> trail_str =
8008 v8::String::NewFromTwoByte(context->GetIsolate(), trail,
8009 v8::NewStringType::kNormal, 1)
8010 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008011 // surrogate pair
8012 uint16_t pair[2] = { 0xd800, 0xdc00 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008013 v8::Local<String> pair_str =
8014 v8::String::NewFromTwoByte(context->GetIsolate(), pair,
8015 v8::NewStringType::kNormal, 2)
8016 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008017 const int kStride = 4; // Must match stride in for loops in JS below.
8018 CompileRun(
8019 "var left = '';"
8020 "for (var i = 0; i < 0xd800; i += 4) {"
8021 " left = left + String.fromCharCode(i);"
8022 "}");
8023 CompileRun(
8024 "var right = '';"
8025 "for (var i = 0; i < 0xd800; i += 4) {"
8026 " right = String.fromCharCode(i) + right;"
8027 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008028 v8::Local<v8::Object> global = context->Global();
8029 Local<String> left_tree = global->Get(context.local(), v8_str("left"))
8030 .ToLocalChecked()
8031 .As<String>();
8032 Local<String> right_tree = global->Get(context.local(), v8_str("right"))
8033 .ToLocalChecked()
8034 .As<String>();
Ben Murdochb0fe1622011-05-05 13:52:32 +01008035
8036 CHECK_EQ(5, str2->Length());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008037 CHECK_EQ(0xd800 / kStride, left_tree->Length());
8038 CHECK_EQ(0xd800 / kStride, right_tree->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +00008039
8040 char buf[100];
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008041 char utf8buf[0xd800 * 3];
Ben Murdochb0fe1622011-05-05 13:52:32 +01008042 uint16_t wbuf[100];
Steve Blocka7e24c12009-10-30 11:49:00 +00008043 int len;
Ben Murdochb0fe1622011-05-05 13:52:32 +01008044 int charlen;
8045
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008046 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008047 len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008048 CHECK_EQ(9, len);
8049 CHECK_EQ(5, charlen);
8050 CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008051
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008052 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008053 len = str2->WriteUtf8(utf8buf, 8, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008054 CHECK_EQ(8, len);
8055 CHECK_EQ(5, charlen);
8056 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008057
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008058 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008059 len = str2->WriteUtf8(utf8buf, 7, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008060 CHECK_EQ(5, len);
8061 CHECK_EQ(4, charlen);
8062 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008063
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008064 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008065 len = str2->WriteUtf8(utf8buf, 6, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008066 CHECK_EQ(5, len);
8067 CHECK_EQ(4, charlen);
8068 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008069
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008070 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008071 len = str2->WriteUtf8(utf8buf, 5, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008072 CHECK_EQ(5, len);
8073 CHECK_EQ(4, charlen);
8074 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008075
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008076 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008077 len = str2->WriteUtf8(utf8buf, 4, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008078 CHECK_EQ(3, len);
8079 CHECK_EQ(3, charlen);
8080 CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008081
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008082 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008083 len = str2->WriteUtf8(utf8buf, 3, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008084 CHECK_EQ(3, len);
8085 CHECK_EQ(3, charlen);
8086 CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008087
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008088 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008089 len = str2->WriteUtf8(utf8buf, 2, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008090 CHECK_EQ(2, len);
8091 CHECK_EQ(2, charlen);
8092 CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
Steve Blocka7e24c12009-10-30 11:49:00 +00008093
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008094 // allow orphan surrogates by default
8095 memset(utf8buf, 0x1, 1000);
8096 len = orphans_str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
8097 CHECK_EQ(13, len);
8098 CHECK_EQ(8, charlen);
8099 CHECK_EQ(0, strcmp(utf8buf, "ab\355\240\200cd\355\260\200ef"));
8100
8101 // replace orphan surrogates with unicode replacement character
8102 memset(utf8buf, 0x1, 1000);
8103 len = orphans_str->WriteUtf8(utf8buf,
8104 sizeof(utf8buf),
8105 &charlen,
8106 String::REPLACE_INVALID_UTF8);
8107 CHECK_EQ(13, len);
8108 CHECK_EQ(8, charlen);
8109 CHECK_EQ(0, strcmp(utf8buf, "ab\357\277\275cd\357\277\275ef"));
8110
8111 // replace single lead surrogate with unicode replacement character
8112 memset(utf8buf, 0x1, 1000);
8113 len = lead_str->WriteUtf8(utf8buf,
8114 sizeof(utf8buf),
8115 &charlen,
8116 String::REPLACE_INVALID_UTF8);
8117 CHECK_EQ(4, len);
8118 CHECK_EQ(1, charlen);
8119 CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
8120
8121 // replace single trail surrogate with unicode replacement character
8122 memset(utf8buf, 0x1, 1000);
8123 len = trail_str->WriteUtf8(utf8buf,
8124 sizeof(utf8buf),
8125 &charlen,
8126 String::REPLACE_INVALID_UTF8);
8127 CHECK_EQ(4, len);
8128 CHECK_EQ(1, charlen);
8129 CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
8130
8131 // do not replace / write anything if surrogate pair does not fit the buffer
8132 // space
8133 memset(utf8buf, 0x1, 1000);
8134 len = pair_str->WriteUtf8(utf8buf,
8135 3,
8136 &charlen,
8137 String::REPLACE_INVALID_UTF8);
8138 CHECK_EQ(0, len);
8139 CHECK_EQ(0, charlen);
8140
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008141 memset(utf8buf, 0x1, sizeof(utf8buf));
8142 len = GetUtf8Length(left_tree);
8143 int utf8_expected =
8144 (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride;
8145 CHECK_EQ(utf8_expected, len);
8146 len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
8147 CHECK_EQ(utf8_expected, len);
8148 CHECK_EQ(0xd800 / kStride, charlen);
8149 CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
8150 CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
8151 CHECK_EQ(0xc0 - kStride,
8152 static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
8153 CHECK_EQ(1, utf8buf[utf8_expected]);
8154
8155 memset(utf8buf, 0x1, sizeof(utf8buf));
8156 len = GetUtf8Length(right_tree);
8157 CHECK_EQ(utf8_expected, len);
8158 len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
8159 CHECK_EQ(utf8_expected, len);
8160 CHECK_EQ(0xd800 / kStride, charlen);
8161 CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0]));
8162 CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1]));
8163 CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2]));
8164 CHECK_EQ(1, utf8buf[utf8_expected]);
8165
Steve Blocka7e24c12009-10-30 11:49:00 +00008166 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008167 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008168 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
Steve Block44f0eee2011-05-26 01:26:41 +01008169 CHECK_EQ(5, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008170 len = str->Write(wbuf);
Steve Block44f0eee2011-05-26 01:26:41 +01008171 CHECK_EQ(5, len);
8172 CHECK_EQ(0, strcmp("abcde", buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008173 uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
Steve Block44f0eee2011-05-26 01:26:41 +01008174 CHECK_EQ(0, StrCmp16(answer1, wbuf));
Steve Blocka7e24c12009-10-30 11:49:00 +00008175
8176 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008177 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008178 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 4);
Steve Block44f0eee2011-05-26 01:26:41 +01008179 CHECK_EQ(4, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008180 len = str->Write(wbuf, 0, 4);
Steve Block44f0eee2011-05-26 01:26:41 +01008181 CHECK_EQ(4, len);
8182 CHECK_EQ(0, strncmp("abcd\1", buf, 5));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008183 uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
Steve Block44f0eee2011-05-26 01:26:41 +01008184 CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
Steve Blocka7e24c12009-10-30 11:49:00 +00008185
8186 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008187 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008188 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 5);
Steve Block44f0eee2011-05-26 01:26:41 +01008189 CHECK_EQ(5, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008190 len = str->Write(wbuf, 0, 5);
Steve Block44f0eee2011-05-26 01:26:41 +01008191 CHECK_EQ(5, len);
8192 CHECK_EQ(0, strncmp("abcde\1", buf, 6));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008193 uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
Steve Block44f0eee2011-05-26 01:26:41 +01008194 CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
Steve Blocka7e24c12009-10-30 11:49:00 +00008195
8196 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008197 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008198 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 6);
Steve Block44f0eee2011-05-26 01:26:41 +01008199 CHECK_EQ(5, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008200 len = str->Write(wbuf, 0, 6);
Steve Block44f0eee2011-05-26 01:26:41 +01008201 CHECK_EQ(5, len);
8202 CHECK_EQ(0, strcmp("abcde", buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008203 uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
Steve Block44f0eee2011-05-26 01:26:41 +01008204 CHECK_EQ(0, StrCmp16(answer4, wbuf));
Steve Blocka7e24c12009-10-30 11:49:00 +00008205
8206 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008207 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008208 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, -1);
Steve Block44f0eee2011-05-26 01:26:41 +01008209 CHECK_EQ(1, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008210 len = str->Write(wbuf, 4, -1);
Steve Block44f0eee2011-05-26 01:26:41 +01008211 CHECK_EQ(1, len);
8212 CHECK_EQ(0, strcmp("e", buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008213 uint16_t answer5[] = {'e', '\0'};
Steve Block44f0eee2011-05-26 01:26:41 +01008214 CHECK_EQ(0, StrCmp16(answer5, wbuf));
Steve Blocka7e24c12009-10-30 11:49:00 +00008215
8216 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008217 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008218 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 6);
Steve Block44f0eee2011-05-26 01:26:41 +01008219 CHECK_EQ(1, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008220 len = str->Write(wbuf, 4, 6);
Steve Block44f0eee2011-05-26 01:26:41 +01008221 CHECK_EQ(1, len);
8222 CHECK_EQ(0, strcmp("e", buf));
8223 CHECK_EQ(0, StrCmp16(answer5, wbuf));
Steve Blocka7e24c12009-10-30 11:49:00 +00008224
8225 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008226 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008227 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 1);
Steve Block44f0eee2011-05-26 01:26:41 +01008228 CHECK_EQ(1, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008229 len = str->Write(wbuf, 4, 1);
Steve Block44f0eee2011-05-26 01:26:41 +01008230 CHECK_EQ(1, len);
8231 CHECK_EQ(0, strncmp("e\1", buf, 2));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008232 uint16_t answer6[] = {'e', 0x101};
Steve Block44f0eee2011-05-26 01:26:41 +01008233 CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008234
8235 memset(buf, 0x1, sizeof(buf));
8236 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008237 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 3, 1);
Steve Block44f0eee2011-05-26 01:26:41 +01008238 CHECK_EQ(1, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008239 len = str->Write(wbuf, 3, 1);
Steve Block44f0eee2011-05-26 01:26:41 +01008240 CHECK_EQ(1, len);
8241 CHECK_EQ(0, strncmp("d\1", buf, 2));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008242 uint16_t answer7[] = {'d', 0x101};
Steve Block44f0eee2011-05-26 01:26:41 +01008243 CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
Ben Murdoch69a99ed2011-11-30 16:03:39 +00008244
8245 memset(wbuf, 0x1, sizeof(wbuf));
8246 wbuf[5] = 'X';
8247 len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION);
8248 CHECK_EQ(5, len);
8249 CHECK_EQ('X', wbuf[5]);
8250 uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
8251 uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
8252 CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
8253 CHECK_NE(0, StrCmp16(answer8b, wbuf));
8254 wbuf[5] = '\0';
8255 CHECK_EQ(0, StrCmp16(answer8b, wbuf));
8256
8257 memset(buf, 0x1, sizeof(buf));
8258 buf[5] = 'X';
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008259 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf),
8260 0,
8261 6,
8262 String::NO_NULL_TERMINATION);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00008263 CHECK_EQ(5, len);
8264 CHECK_EQ('X', buf[5]);
8265 CHECK_EQ(0, strncmp("abcde", buf, 5));
8266 CHECK_NE(0, strcmp("abcde", buf));
8267 buf[5] = '\0';
8268 CHECK_EQ(0, strcmp("abcde", buf));
8269
8270 memset(utf8buf, 0x1, sizeof(utf8buf));
8271 utf8buf[8] = 'X';
8272 len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
8273 String::NO_NULL_TERMINATION);
8274 CHECK_EQ(8, len);
8275 CHECK_EQ('X', utf8buf[8]);
8276 CHECK_EQ(5, charlen);
8277 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
8278 CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
8279 utf8buf[8] = '\0';
8280 CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008281
8282 memset(utf8buf, 0x1, sizeof(utf8buf));
8283 utf8buf[5] = 'X';
8284 len = str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
8285 String::NO_NULL_TERMINATION);
8286 CHECK_EQ(5, len);
8287 CHECK_EQ('X', utf8buf[5]); // Test that the sixth character is untouched.
8288 CHECK_EQ(5, charlen);
8289 utf8buf[5] = '\0';
8290 CHECK_EQ(0, strcmp(utf8buf, "abcde"));
8291
8292 memset(buf, 0x1, sizeof(buf));
8293 len = str3->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
8294 CHECK_EQ(7, len);
8295 CHECK_EQ(0, strcmp("abc", buf));
8296 CHECK_EQ(0, buf[3]);
8297 CHECK_EQ(0, strcmp("def", buf + 4));
8298
8299 CHECK_EQ(0, str->WriteOneByte(NULL, 0, 0, String::NO_NULL_TERMINATION));
8300 CHECK_EQ(0, str->WriteUtf8(NULL, 0, 0, String::NO_NULL_TERMINATION));
8301 CHECK_EQ(0, str->Write(NULL, 0, 0, String::NO_NULL_TERMINATION));
Steve Blocka7e24c12009-10-30 11:49:00 +00008302}
8303
8304
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008305static void Utf16Helper(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008306 LocalContext& context, // NOLINT
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008307 const char* name,
8308 const char* lengths_name,
8309 int len) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008310 Local<v8::Array> a = Local<v8::Array>::Cast(
8311 context->Global()->Get(context.local(), v8_str(name)).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008312 Local<v8::Array> alens =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008313 Local<v8::Array>::Cast(context->Global()
8314 ->Get(context.local(), v8_str(lengths_name))
8315 .ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008316 for (int i = 0; i < len; i++) {
8317 Local<v8::String> string =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008318 Local<v8::String>::Cast(a->Get(context.local(), i).ToLocalChecked());
8319 Local<v8::Number> expected_len = Local<v8::Number>::Cast(
8320 alens->Get(context.local(), i).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008321 int length = GetUtf8Length(string);
8322 CHECK_EQ(static_cast<int>(expected_len->Value()), length);
8323 }
8324}
8325
8326
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008327THREADED_TEST(Utf16) {
8328 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008329 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008330 CompileRun(
8331 "var pad = '01234567890123456789';"
8332 "var p = [];"
8333 "var plens = [20, 3, 3];"
8334 "p.push('01234567890123456789');"
8335 "var lead = 0xd800;"
8336 "var trail = 0xdc00;"
8337 "p.push(String.fromCharCode(0xd800));"
8338 "p.push(String.fromCharCode(0xdc00));"
8339 "var a = [];"
8340 "var b = [];"
8341 "var c = [];"
8342 "var alens = [];"
8343 "for (var i = 0; i < 3; i++) {"
8344 " p[1] = String.fromCharCode(lead++);"
8345 " for (var j = 0; j < 3; j++) {"
8346 " p[2] = String.fromCharCode(trail++);"
8347 " a.push(p[i] + p[j]);"
8348 " b.push(p[i] + p[j]);"
8349 " c.push(p[i] + p[j]);"
8350 " alens.push(plens[i] + plens[j]);"
8351 " }"
8352 "}"
8353 "alens[5] -= 2;" // Here the surrogate pairs match up.
8354 "var a2 = [];"
8355 "var b2 = [];"
8356 "var c2 = [];"
8357 "var a2lens = [];"
8358 "for (var m = 0; m < 9; m++) {"
8359 " for (var n = 0; n < 9; n++) {"
8360 " a2.push(a[m] + a[n]);"
8361 " b2.push(b[m] + b[n]);"
8362 " var newc = 'x' + c[m] + c[n] + 'y';"
8363 " c2.push(newc.substring(1, newc.length - 1));"
8364 " var utf = alens[m] + alens[n];" // And here.
8365 // The 'n's that start with 0xdc.. are 6-8
8366 // The 'm's that end with 0xd8.. are 1, 4 and 7
8367 " if ((m % 3) == 1 && n >= 6) utf -= 2;"
8368 " a2lens.push(utf);"
8369 " }"
8370 "}");
8371 Utf16Helper(context, "a", "alens", 9);
8372 Utf16Helper(context, "a2", "a2lens", 81);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008373}
8374
8375
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008376static bool SameSymbol(Local<String> s1, Local<String> s2) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008377 i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1));
8378 i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2));
8379 return *is1 == *is2;
8380}
8381
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008382
8383THREADED_TEST(Utf16Symbol) {
8384 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008385 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008386
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008387 Local<String> symbol1 =
8388 v8::String::NewFromUtf8(context->GetIsolate(), "abc",
8389 v8::NewStringType::kInternalized)
8390 .ToLocalChecked();
8391 Local<String> symbol2 =
8392 v8::String::NewFromUtf8(context->GetIsolate(), "abc",
8393 v8::NewStringType::kInternalized)
8394 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008395 CHECK(SameSymbol(symbol1, symbol2));
8396
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008397 CompileRun(
8398 "var sym0 = 'benedictus';"
8399 "var sym0b = 'S\303\270ren';"
8400 "var sym1 = '\355\240\201\355\260\207';"
8401 "var sym2 = '\360\220\220\210';"
8402 "var sym3 = 'x\355\240\201\355\260\207';"
8403 "var sym4 = 'x\360\220\220\210';"
8404 "if (sym1.length != 2) throw sym1;"
8405 "if (sym1.charCodeAt(1) != 0xdc07) throw sym1.charCodeAt(1);"
8406 "if (sym2.length != 2) throw sym2;"
8407 "if (sym2.charCodeAt(1) != 0xdc08) throw sym2.charCodeAt(2);"
8408 "if (sym3.length != 3) throw sym3;"
8409 "if (sym3.charCodeAt(2) != 0xdc07) throw sym1.charCodeAt(2);"
8410 "if (sym4.length != 3) throw sym4;"
8411 "if (sym4.charCodeAt(2) != 0xdc08) throw sym2.charCodeAt(2);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008412 Local<String> sym0 =
8413 v8::String::NewFromUtf8(context->GetIsolate(), "benedictus",
8414 v8::NewStringType::kInternalized)
8415 .ToLocalChecked();
8416 Local<String> sym0b =
8417 v8::String::NewFromUtf8(context->GetIsolate(), "S\303\270ren",
8418 v8::NewStringType::kInternalized)
8419 .ToLocalChecked();
8420 Local<String> sym1 =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008421 v8::String::NewFromUtf8(context->GetIsolate(), "\355\240\201\355\260\207",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008422 v8::NewStringType::kInternalized)
8423 .ToLocalChecked();
8424 Local<String> sym2 =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008425 v8::String::NewFromUtf8(context->GetIsolate(), "\360\220\220\210",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008426 v8::NewStringType::kInternalized)
8427 .ToLocalChecked();
8428 Local<String> sym3 = v8::String::NewFromUtf8(context->GetIsolate(),
8429 "x\355\240\201\355\260\207",
8430 v8::NewStringType::kInternalized)
8431 .ToLocalChecked();
8432 Local<String> sym4 =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008433 v8::String::NewFromUtf8(context->GetIsolate(), "x\360\220\220\210",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008434 v8::NewStringType::kInternalized)
8435 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008436 v8::Local<v8::Object> global = context->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008437 Local<Value> s0 =
8438 global->Get(context.local(), v8_str("sym0")).ToLocalChecked();
8439 Local<Value> s0b =
8440 global->Get(context.local(), v8_str("sym0b")).ToLocalChecked();
8441 Local<Value> s1 =
8442 global->Get(context.local(), v8_str("sym1")).ToLocalChecked();
8443 Local<Value> s2 =
8444 global->Get(context.local(), v8_str("sym2")).ToLocalChecked();
8445 Local<Value> s3 =
8446 global->Get(context.local(), v8_str("sym3")).ToLocalChecked();
8447 Local<Value> s4 =
8448 global->Get(context.local(), v8_str("sym4")).ToLocalChecked();
8449 CHECK(SameSymbol(sym0, Local<String>::Cast(s0)));
8450 CHECK(SameSymbol(sym0b, Local<String>::Cast(s0b)));
8451 CHECK(SameSymbol(sym1, Local<String>::Cast(s1)));
8452 CHECK(SameSymbol(sym2, Local<String>::Cast(s2)));
8453 CHECK(SameSymbol(sym3, Local<String>::Cast(s3)));
8454 CHECK(SameSymbol(sym4, Local<String>::Cast(s4)));
8455}
8456
8457
8458THREADED_TEST(Utf16MissingTrailing) {
8459 LocalContext context;
8460 v8::HandleScope scope(context->GetIsolate());
8461
8462 // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
8463 int size = 1024 * 64;
8464 uint8_t* buffer = new uint8_t[size];
8465 for (int i = 0; i < size; i += 4) {
8466 buffer[i] = 0xf0;
8467 buffer[i + 1] = 0x9d;
8468 buffer[i + 2] = 0x80;
8469 buffer[i + 3] = 0x9e;
8470 }
8471
8472 // Now invoke the decoder without last 3 bytes
8473 v8::Local<v8::String> str =
8474 v8::String::NewFromUtf8(
8475 context->GetIsolate(), reinterpret_cast<char*>(buffer),
8476 v8::NewStringType::kNormal, size - 3).ToLocalChecked();
8477 USE(str);
8478 delete[] buffer;
8479}
8480
8481
8482THREADED_TEST(Utf16Trailing3Byte) {
8483 LocalContext context;
8484 v8::HandleScope scope(context->GetIsolate());
8485
8486 // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
8487 int size = 1024 * 63;
8488 uint8_t* buffer = new uint8_t[size];
8489 for (int i = 0; i < size; i += 3) {
8490 buffer[i] = 0xe2;
8491 buffer[i + 1] = 0x80;
8492 buffer[i + 2] = 0xa6;
8493 }
8494
8495 // Now invoke the decoder without last 3 bytes
8496 v8::Local<v8::String> str =
8497 v8::String::NewFromUtf8(
8498 context->GetIsolate(), reinterpret_cast<char*>(buffer),
8499 v8::NewStringType::kNormal, size).ToLocalChecked();
8500
8501 v8::String::Value value(str);
8502 CHECK_EQ(value.length(), size / 3);
8503 CHECK_EQ((*value)[value.length() - 1], 0x2026);
8504
8505 delete[] buffer;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008506}
8507
8508
Steve Blocka7e24c12009-10-30 11:49:00 +00008509THREADED_TEST(ToArrayIndex) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008510 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008511 v8::Isolate* isolate = context->GetIsolate();
8512 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00008513
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008514 v8::Local<String> str = v8_str("42");
8515 v8::MaybeLocal<v8::Uint32> index = str->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008516 CHECK(!index.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008517 CHECK_EQ(42.0,
8518 index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008519 str = v8_str("42asdf");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008520 index = str->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008521 CHECK(index.IsEmpty());
8522 str = v8_str("-42");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008523 index = str->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008524 CHECK(index.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008525 str = v8_str("4294967294");
8526 index = str->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008527 CHECK(!index.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008528 CHECK_EQ(4294967294.0,
8529 index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
8530 v8::Local<v8::Number> num = v8::Number::New(isolate, 1);
8531 index = num->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008532 CHECK(!index.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008533 CHECK_EQ(1.0,
8534 index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008535 num = v8::Number::New(isolate, -1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008536 index = num->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008537 CHECK(index.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008538 v8::Local<v8::Object> obj = v8::Object::New(isolate);
8539 index = obj->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008540 CHECK(index.IsEmpty());
8541}
8542
8543
8544THREADED_TEST(ErrorConstruction) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008545 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008546 v8::HandleScope scope(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00008547
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008548 v8::Local<String> foo = v8_str("foo");
8549 v8::Local<String> message = v8_str("message");
8550 v8::Local<Value> range_error = v8::Exception::RangeError(foo);
Steve Blocka7e24c12009-10-30 11:49:00 +00008551 CHECK(range_error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008552 CHECK(range_error.As<v8::Object>()
8553 ->Get(context.local(), message)
8554 .ToLocalChecked()
8555 ->Equals(context.local(), foo)
8556 .FromJust());
8557 v8::Local<Value> reference_error = v8::Exception::ReferenceError(foo);
Steve Blocka7e24c12009-10-30 11:49:00 +00008558 CHECK(reference_error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008559 CHECK(reference_error.As<v8::Object>()
8560 ->Get(context.local(), message)
8561 .ToLocalChecked()
8562 ->Equals(context.local(), foo)
8563 .FromJust());
8564 v8::Local<Value> syntax_error = v8::Exception::SyntaxError(foo);
Steve Blocka7e24c12009-10-30 11:49:00 +00008565 CHECK(syntax_error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008566 CHECK(syntax_error.As<v8::Object>()
8567 ->Get(context.local(), message)
8568 .ToLocalChecked()
8569 ->Equals(context.local(), foo)
8570 .FromJust());
8571 v8::Local<Value> type_error = v8::Exception::TypeError(foo);
Steve Blocka7e24c12009-10-30 11:49:00 +00008572 CHECK(type_error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008573 CHECK(type_error.As<v8::Object>()
8574 ->Get(context.local(), message)
8575 .ToLocalChecked()
8576 ->Equals(context.local(), foo)
8577 .FromJust());
8578 v8::Local<Value> error = v8::Exception::Error(foo);
Steve Blocka7e24c12009-10-30 11:49:00 +00008579 CHECK(error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008580 CHECK(error.As<v8::Object>()
8581 ->Get(context.local(), message)
8582 .ToLocalChecked()
8583 ->Equals(context.local(), foo)
8584 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008585}
8586
8587
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008588static void ThrowV8Exception(const v8::FunctionCallbackInfo<v8::Value>& info) {
8589 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008590 v8::Local<String> foo = v8_str("foo");
8591 v8::Local<String> message = v8_str("message");
8592 v8::Local<Value> error = v8::Exception::Error(foo);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008593 CHECK(error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008594 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
8595 CHECK(error.As<v8::Object>()
8596 ->Get(context, message)
8597 .ToLocalChecked()
8598 ->Equals(context, foo)
8599 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008600 info.GetIsolate()->ThrowException(error);
8601 info.GetReturnValue().SetUndefined();
8602}
8603
8604
8605THREADED_TEST(ExceptionCreateMessage) {
8606 LocalContext context;
8607 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008608 v8::Local<String> foo_str = v8_str("foo");
8609 v8::Local<String> message_str = v8_str("message");
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008610
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008611 context->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008612
8613 Local<v8::FunctionTemplate> fun =
8614 v8::FunctionTemplate::New(context->GetIsolate(), ThrowV8Exception);
8615 v8::Local<v8::Object> global = context->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008616 CHECK(global->Set(context.local(), v8_str("throwV8Exception"),
8617 fun->GetFunction(context.local()).ToLocalChecked())
8618 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008619
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008620 TryCatch try_catch(context->GetIsolate());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008621 CompileRun(
8622 "function f1() {\n"
8623 " throwV8Exception();\n"
8624 "};\n"
8625 "f1();");
8626 CHECK(try_catch.HasCaught());
8627
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008628 v8::Local<v8::Value> error = try_catch.Exception();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008629 CHECK(error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008630 CHECK(error.As<v8::Object>()
8631 ->Get(context.local(), message_str)
8632 .ToLocalChecked()
8633 ->Equals(context.local(), foo_str)
8634 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008635
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008636 v8::Local<v8::Message> message =
8637 v8::Exception::CreateMessage(context->GetIsolate(), error);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008638 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008639 CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
8640 CHECK_EQ(2, message->GetStartColumn(context.local()).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008641
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008642 v8::Local<v8::StackTrace> stackTrace = message->GetStackTrace();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008643 CHECK(!stackTrace.IsEmpty());
8644 CHECK_EQ(2, stackTrace->GetFrameCount());
8645
8646 stackTrace = v8::Exception::GetStackTrace(error);
8647 CHECK(!stackTrace.IsEmpty());
8648 CHECK_EQ(2, stackTrace->GetFrameCount());
8649
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008650 context->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(false);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008651
8652 // Now check message location when SetCaptureStackTraceForUncaughtExceptions
8653 // is false.
8654 try_catch.Reset();
8655
8656 CompileRun(
8657 "function f2() {\n"
8658 " return throwV8Exception();\n"
8659 "};\n"
8660 "f2();");
8661 CHECK(try_catch.HasCaught());
8662
8663 error = try_catch.Exception();
8664 CHECK(error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008665 CHECK(error.As<v8::Object>()
8666 ->Get(context.local(), message_str)
8667 .ToLocalChecked()
8668 ->Equals(context.local(), foo_str)
8669 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008670
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008671 message = v8::Exception::CreateMessage(context->GetIsolate(), error);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008672 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008673 CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
8674 CHECK_EQ(9, message->GetStartColumn(context.local()).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008675
8676 // Should be empty stack trace.
8677 stackTrace = message->GetStackTrace();
8678 CHECK(stackTrace.IsEmpty());
8679 CHECK(v8::Exception::GetStackTrace(error).IsEmpty());
8680}
8681
8682
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008683THREADED_TEST(ExceptionCreateMessageLength) {
8684 LocalContext context;
8685 v8::HandleScope scope(context->GetIsolate());
8686
8687 // Test that the message is not truncated.
8688 TryCatch try_catch(context->GetIsolate());
8689 CompileRun(
8690 "var message = 'm';"
8691 "while (message.length < 1000) message += message;"
8692 "throw message;");
8693 CHECK(try_catch.HasCaught());
8694
8695 CHECK_LT(1000, try_catch.Message()->Get()->Length());
8696}
8697
8698
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008699static void YGetter(Local<String> name,
8700 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008701 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008702 info.GetReturnValue().Set(v8_num(10));
Steve Blocka7e24c12009-10-30 11:49:00 +00008703}
8704
8705
8706static void YSetter(Local<String> name,
8707 Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008708 const v8::PropertyCallbackInfo<void>& info) {
8709 Local<Object> this_obj = Local<Object>::Cast(info.This());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008710 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
8711 if (this_obj->Has(context, name).FromJust())
8712 this_obj->Delete(context, name).FromJust();
8713 CHECK(this_obj->Set(context, name, value).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008714}
8715
8716
8717THREADED_TEST(DeleteAccessor) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008718 v8::Isolate* isolate = CcTest::isolate();
8719 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008720 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00008721 obj->SetAccessor(v8_str("y"), YGetter, YSetter);
8722 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008723 v8::Local<v8::Object> holder =
8724 obj->NewInstance(context.local()).ToLocalChecked();
8725 CHECK(context->Global()
8726 ->Set(context.local(), v8_str("holder"), holder)
8727 .FromJust());
8728 v8::Local<Value> result =
8729 CompileRun("holder.y = 11; holder.y = 12; holder.y");
8730 CHECK_EQ(12u, result->Uint32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008731}
8732
8733
Steve Blocka7e24c12009-10-30 11:49:00 +00008734static int trouble_nesting = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008735static void TroubleCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008736 ApiTestFuzzer::Fuzz();
8737 trouble_nesting++;
8738
8739 // Call a JS function that throws an uncaught exception.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008740 Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
8741 Local<v8::Object> arg_this = context->Global();
8742 Local<Value> trouble_callee =
8743 (trouble_nesting == 3)
8744 ? arg_this->Get(context, v8_str("trouble_callee")).ToLocalChecked()
8745 : arg_this->Get(context, v8_str("trouble_caller")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00008746 CHECK(trouble_callee->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008747 args.GetReturnValue().Set(Function::Cast(*trouble_callee)
8748 ->Call(context, arg_this, 0, NULL)
8749 .FromMaybe(v8::Local<v8::Value>()));
Steve Blocka7e24c12009-10-30 11:49:00 +00008750}
8751
8752
8753static int report_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008754static void ApiUncaughtExceptionTestListener(v8::Local<v8::Message>,
8755 v8::Local<Value>) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008756 report_count++;
8757}
8758
8759
8760// Counts uncaught exceptions, but other tests running in parallel
8761// also have uncaught exceptions.
8762TEST(ApiUncaughtException) {
8763 report_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00008764 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008765 v8::Isolate* isolate = env->GetIsolate();
8766 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008767 isolate->AddMessageListener(ApiUncaughtExceptionTestListener);
Steve Blocka7e24c12009-10-30 11:49:00 +00008768
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008769 Local<v8::FunctionTemplate> fun =
8770 v8::FunctionTemplate::New(isolate, TroubleCallback);
Steve Blocka7e24c12009-10-30 11:49:00 +00008771 v8::Local<v8::Object> global = env->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008772 CHECK(global->Set(env.local(), v8_str("trouble"),
8773 fun->GetFunction(env.local()).ToLocalChecked())
8774 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008775
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008776 CompileRun(
8777 "function trouble_callee() {"
8778 " var x = null;"
8779 " return x.foo;"
8780 "};"
8781 "function trouble_caller() {"
8782 " trouble();"
8783 "};");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008784 Local<Value> trouble =
8785 global->Get(env.local(), v8_str("trouble")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00008786 CHECK(trouble->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008787 Local<Value> trouble_callee =
8788 global->Get(env.local(), v8_str("trouble_callee")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00008789 CHECK(trouble_callee->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008790 Local<Value> trouble_caller =
8791 global->Get(env.local(), v8_str("trouble_caller")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00008792 CHECK(trouble_caller->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008793 Function::Cast(*trouble_caller)
8794 ->Call(env.local(), global, 0, NULL)
8795 .FromMaybe(v8::Local<v8::Value>());
Steve Blocka7e24c12009-10-30 11:49:00 +00008796 CHECK_EQ(1, report_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008797 isolate->RemoveMessageListeners(ApiUncaughtExceptionTestListener);
Steve Blocka7e24c12009-10-30 11:49:00 +00008798}
8799
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008800
8801TEST(ApiUncaughtExceptionInObjectObserve) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008802 v8::internal::FLAG_harmony_object_observe = true;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008803 v8::internal::FLAG_stack_size = 150;
8804 report_count = 0;
8805 LocalContext env;
8806 v8::Isolate* isolate = env->GetIsolate();
8807 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008808 isolate->AddMessageListener(ApiUncaughtExceptionTestListener);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008809 CompileRun(
8810 "var obj = {};"
8811 "var observe_count = 0;"
8812 "function observer1() { ++observe_count; };"
8813 "function observer2() { ++observe_count; };"
8814 "function observer_throws() { throw new Error(); };"
8815 "function stack_overflow() { return (function f(x) { f(x+1); })(0); };"
8816 "Object.observe(obj, observer_throws.bind());"
8817 "Object.observe(obj, observer1);"
8818 "Object.observe(obj, stack_overflow);"
8819 "Object.observe(obj, observer2);"
8820 "Object.observe(obj, observer_throws.bind());"
8821 "obj.foo = 'bar';");
8822 CHECK_EQ(3, report_count);
8823 ExpectInt32("observe_count", 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008824 isolate->RemoveMessageListeners(ApiUncaughtExceptionTestListener);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008825}
8826
8827
Leon Clarke4515c472010-02-03 11:58:03 +00008828static const char* script_resource_name = "ExceptionInNativeScript.js";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008829static void ExceptionInNativeScriptTestListener(v8::Local<v8::Message> message,
8830 v8::Local<Value>) {
8831 v8::Local<v8::Value> name_val = message->GetScriptOrigin().ResourceName();
Leon Clarke4515c472010-02-03 11:58:03 +00008832 CHECK(!name_val.IsEmpty() && name_val->IsString());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008833 v8::String::Utf8Value name(message->GetScriptOrigin().ResourceName());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008834 CHECK_EQ(0, strcmp(script_resource_name, *name));
8835 v8::Local<v8::Context> context =
8836 v8::Isolate::GetCurrent()->GetCurrentContext();
8837 CHECK_EQ(3, message->GetLineNumber(context).FromJust());
8838 v8::String::Utf8Value source_line(
8839 message->GetSourceLine(context).ToLocalChecked());
8840 CHECK_EQ(0, strcmp(" new o.foo();", *source_line));
Leon Clarke4515c472010-02-03 11:58:03 +00008841}
8842
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008843
Leon Clarke4515c472010-02-03 11:58:03 +00008844TEST(ExceptionInNativeScript) {
Leon Clarke4515c472010-02-03 11:58:03 +00008845 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008846 v8::Isolate* isolate = env->GetIsolate();
8847 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008848 isolate->AddMessageListener(ExceptionInNativeScriptTestListener);
Leon Clarke4515c472010-02-03 11:58:03 +00008849
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008850 Local<v8::FunctionTemplate> fun =
8851 v8::FunctionTemplate::New(isolate, TroubleCallback);
Leon Clarke4515c472010-02-03 11:58:03 +00008852 v8::Local<v8::Object> global = env->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008853 CHECK(global->Set(env.local(), v8_str("trouble"),
8854 fun->GetFunction(env.local()).ToLocalChecked())
8855 .FromJust());
Leon Clarke4515c472010-02-03 11:58:03 +00008856
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008857 CompileRunWithOrigin(
8858 "function trouble() {\n"
8859 " var o = {};\n"
8860 " new o.foo();\n"
8861 "};",
8862 script_resource_name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008863 Local<Value> trouble =
8864 global->Get(env.local(), v8_str("trouble")).ToLocalChecked();
Leon Clarke4515c472010-02-03 11:58:03 +00008865 CHECK(trouble->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008866 CHECK(Function::Cast(*trouble)->Call(env.local(), global, 0, NULL).IsEmpty());
8867 isolate->RemoveMessageListeners(ExceptionInNativeScriptTestListener);
Leon Clarke4515c472010-02-03 11:58:03 +00008868}
8869
Steve Blocka7e24c12009-10-30 11:49:00 +00008870
8871TEST(CompilationErrorUsingTryCatchHandler) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008872 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008873 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008874 v8::TryCatch try_catch(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008875 v8_compile("This doesn't &*&@#$&*^ compile.");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008876 CHECK(*try_catch.Exception());
Steve Blocka7e24c12009-10-30 11:49:00 +00008877 CHECK(try_catch.HasCaught());
8878}
8879
8880
8881TEST(TryCatchFinallyUsingTryCatchHandler) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008882 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008883 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008884 v8::TryCatch try_catch(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008885 CompileRun("try { throw ''; } catch (e) {}");
Steve Blocka7e24c12009-10-30 11:49:00 +00008886 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008887 CompileRun("try { throw ''; } finally {}");
Steve Blocka7e24c12009-10-30 11:49:00 +00008888 CHECK(try_catch.HasCaught());
8889 try_catch.Reset();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008890 CompileRun(
8891 "(function() {"
8892 "try { throw ''; } finally { return; }"
8893 "})()");
Steve Blocka7e24c12009-10-30 11:49:00 +00008894 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008895 CompileRun(
8896 "(function()"
8897 " { try { throw ''; } finally { throw 0; }"
8898 "})()");
Steve Blocka7e24c12009-10-30 11:49:00 +00008899 CHECK(try_catch.HasCaught());
8900}
8901
8902
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008903void CEvaluate(const v8::FunctionCallbackInfo<v8::Value>& args) {
8904 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008905 CompileRun(args[0]
8906 ->ToString(args.GetIsolate()->GetCurrentContext())
8907 .ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008908}
8909
8910
8911TEST(TryCatchFinallyStoresMessageUsingTryCatchHandler) {
8912 v8::Isolate* isolate = CcTest::isolate();
8913 v8::HandleScope scope(isolate);
8914 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
8915 templ->Set(v8_str("CEvaluate"),
8916 v8::FunctionTemplate::New(isolate, CEvaluate));
8917 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008918 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008919 CompileRun("try {"
8920 " CEvaluate('throw 1;');"
8921 "} finally {"
8922 "}");
8923 CHECK(try_catch.HasCaught());
8924 CHECK(!try_catch.Message().IsEmpty());
8925 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008926 CHECK_EQ(0, strcmp(*exception_value, "1"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008927 try_catch.Reset();
8928 CompileRun("try {"
8929 " CEvaluate('throw 1;');"
8930 "} finally {"
8931 " throw 2;"
8932 "}");
8933 CHECK(try_catch.HasCaught());
8934 CHECK(!try_catch.Message().IsEmpty());
8935 String::Utf8Value finally_exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008936 CHECK_EQ(0, strcmp(*finally_exception_value, "2"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008937}
8938
8939
8940// For use within the TestSecurityHandler() test.
8941static bool g_security_callback_result = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008942static bool SecurityTestCallback(Local<v8::Context> accessing_context,
8943 Local<v8::Object> accessed_object) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008944 printf("a\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008945 return g_security_callback_result;
8946}
8947
8948
Steve Blocka7e24c12009-10-30 11:49:00 +00008949// SecurityHandler can't be run twice
8950TEST(SecurityHandler) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008951 v8::Isolate* isolate = CcTest::isolate();
8952 v8::HandleScope scope0(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008953 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008954 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008955 global_template->SetAccessCheckCallback(SecurityTestCallback);
Steve Blocka7e24c12009-10-30 11:49:00 +00008956 // Create an environment
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008957 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
Steve Blocka7e24c12009-10-30 11:49:00 +00008958 context0->Enter();
8959
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008960 v8::Local<v8::Object> global0 = context0->Global();
8961 v8::Local<Script> script0 = v8_compile("foo = 111");
8962 script0->Run(context0).ToLocalChecked();
8963 CHECK(global0->Set(context0, v8_str("0"), v8_num(999)).FromJust());
8964 v8::Local<Value> foo0 =
8965 global0->Get(context0, v8_str("foo")).ToLocalChecked();
8966 CHECK_EQ(111, foo0->Int32Value(context0).FromJust());
8967 v8::Local<Value> z0 = global0->Get(context0, v8_str("0")).ToLocalChecked();
8968 CHECK_EQ(999, z0->Int32Value(context0).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008969
8970 // Create another environment, should fail security checks.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008971 v8::HandleScope scope1(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00008972
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008973 v8::Local<Context> context1 = Context::New(isolate, NULL, global_template);
Steve Blocka7e24c12009-10-30 11:49:00 +00008974 context1->Enter();
8975
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008976 v8::Local<v8::Object> global1 = context1->Global();
8977 global1->Set(context1, v8_str("othercontext"), global0).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00008978 // This set will fail the security check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008979 v8::Local<Script> script1 =
8980 v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
8981 CHECK(script1->Run(context1).IsEmpty());
8982 g_security_callback_result = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00008983 // This read will pass the security check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008984 v8::Local<Value> foo1 =
8985 global0->Get(context1, v8_str("foo")).ToLocalChecked();
8986 CHECK_EQ(111, foo1->Int32Value(context0).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008987 // This read will pass the security check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008988 v8::Local<Value> z1 = global0->Get(context1, v8_str("0")).ToLocalChecked();
8989 CHECK_EQ(999, z1->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008990
8991 // Create another environment, should pass security checks.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008992 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008993 v8::HandleScope scope2(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00008994 LocalContext context2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008995 v8::Local<v8::Object> global2 = context2->Global();
8996 CHECK(global2->Set(context2.local(), v8_str("othercontext"), global0)
8997 .FromJust());
8998 v8::Local<Script> script2 =
Steve Blocka7e24c12009-10-30 11:49:00 +00008999 v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009000 script2->Run(context2.local()).ToLocalChecked();
9001 v8::Local<Value> foo2 =
9002 global0->Get(context2.local(), v8_str("foo")).ToLocalChecked();
9003 CHECK_EQ(333, foo2->Int32Value(context2.local()).FromJust());
9004 v8::Local<Value> z2 =
9005 global0->Get(context2.local(), v8_str("0")).ToLocalChecked();
9006 CHECK_EQ(888, z2->Int32Value(context2.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009007 }
9008
9009 context1->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +00009010 context0->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +00009011}
9012
9013
9014THREADED_TEST(SecurityChecks) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009015 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009016 v8::HandleScope handle_scope(env1->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009017 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009018
9019 Local<Value> foo = v8_str("foo");
9020 Local<Value> bar = v8_str("bar");
9021
9022 // Set to the same domain.
9023 env1->SetSecurityToken(foo);
9024
9025 // Create a function in env1.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009026 CompileRun("spy=function(){return spy;}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009027 Local<Value> spy =
9028 env1->Global()->Get(env1.local(), v8_str("spy")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009029 CHECK(spy->IsFunction());
9030
9031 // Create another function accessing global objects.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009032 CompileRun("spy2=function(){return new this.Array();}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009033 Local<Value> spy2 =
9034 env1->Global()->Get(env1.local(), v8_str("spy2")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009035 CHECK(spy2->IsFunction());
9036
9037 // Switch to env2 in the same domain and invoke spy on env2.
9038 {
9039 env2->SetSecurityToken(foo);
9040 // Enter env2
9041 Context::Scope scope_env2(env2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009042 Local<Value> result = Function::Cast(*spy)
9043 ->Call(env2, env2->Global(), 0, NULL)
9044 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009045 CHECK(result->IsFunction());
9046 }
9047
9048 {
9049 env2->SetSecurityToken(bar);
9050 Context::Scope scope_env2(env2);
9051
9052 // Call cross_domain_call, it should throw an exception
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009053 v8::TryCatch try_catch(env1->GetIsolate());
9054 CHECK(Function::Cast(*spy2)->Call(env2, env2->Global(), 0, NULL).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009055 CHECK(try_catch.HasCaught());
9056 }
Steve Blocka7e24c12009-10-30 11:49:00 +00009057}
9058
9059
9060// Regression test case for issue 1183439.
9061THREADED_TEST(SecurityChecksForPrototypeChain) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009062 LocalContext current;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009063 v8::HandleScope scope(current->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009064 v8::Local<Context> other = Context::New(current->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009065
9066 // Change context to be able to get to the Object function in the
9067 // other context without hitting the security checks.
9068 v8::Local<Value> other_object;
9069 { Context::Scope scope(other);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009070 other_object =
9071 other->Global()->Get(other, v8_str("Object")).ToLocalChecked();
9072 CHECK(other->Global()->Set(other, v8_num(42), v8_num(87)).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009073 }
9074
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009075 CHECK(current->Global()
9076 ->Set(current.local(), v8_str("other"), other->Global())
9077 .FromJust());
9078 CHECK(v8_compile("other")
9079 ->Run(current.local())
9080 .ToLocalChecked()
9081 ->Equals(current.local(), other->Global())
9082 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009083
9084 // Make sure the security check fails here and we get an undefined
9085 // result instead of getting the Object function. Repeat in a loop
9086 // to make sure to exercise the IC code.
9087 v8::Local<Script> access_other0 = v8_compile("other.Object");
9088 v8::Local<Script> access_other1 = v8_compile("other[42]");
9089 for (int i = 0; i < 5; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009090 CHECK(access_other0->Run(current.local()).IsEmpty());
9091 CHECK(access_other1->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009092 }
9093
9094 // Create an object that has 'other' in its prototype chain and make
9095 // sure we cannot access the Object function indirectly through
9096 // that. Repeat in a loop to make sure to exercise the IC code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009097 v8_compile(
9098 "function F() { };"
9099 "F.prototype = other;"
9100 "var f = new F();")
9101 ->Run(current.local())
9102 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009103 v8::Local<Script> access_f0 = v8_compile("f.Object");
9104 v8::Local<Script> access_f1 = v8_compile("f[42]");
9105 for (int j = 0; j < 5; j++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009106 CHECK(access_f0->Run(current.local()).IsEmpty());
9107 CHECK(access_f1->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009108 }
9109
9110 // Now it gets hairy: Set the prototype for the other global object
9111 // to be the current global object. The prototype chain for 'f' now
9112 // goes through 'other' but ends up in the current global object.
9113 { Context::Scope scope(other);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009114 CHECK(other->Global()
9115 ->Set(other, v8_str("__proto__"), current->Global())
9116 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009117 }
9118 // Set a named and an index property on the current global
9119 // object. To force the lookup to go through the other global object,
9120 // the properties must not exist in the other global object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009121 CHECK(current->Global()
9122 ->Set(current.local(), v8_str("foo"), v8_num(100))
9123 .FromJust());
9124 CHECK(current->Global()
9125 ->Set(current.local(), v8_num(99), v8_num(101))
9126 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009127 // Try to read the properties from f and make sure that the access
9128 // gets stopped by the security checks on the other global object.
9129 Local<Script> access_f2 = v8_compile("f.foo");
9130 Local<Script> access_f3 = v8_compile("f[99]");
9131 for (int k = 0; k < 5; k++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009132 CHECK(access_f2->Run(current.local()).IsEmpty());
9133 CHECK(access_f3->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009134 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009135}
9136
9137
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009138static bool security_check_with_gc_called;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009139
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009140static bool SecurityTestCallbackWithGC(Local<v8::Context> accessing_context,
9141 Local<v8::Object> accessed_object) {
9142 CcTest::heap()->CollectAllGarbage();
9143 security_check_with_gc_called = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009144 return true;
9145}
9146
9147
9148TEST(SecurityTestGCAllowed) {
9149 v8::Isolate* isolate = CcTest::isolate();
9150 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009151 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009152 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009153 object_template->SetAccessCheckCallback(SecurityTestCallbackWithGC);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009154
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009155 v8::Local<Context> context = Context::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009156 v8::Context::Scope context_scope(context);
9157
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009158 CHECK(context->Global()
9159 ->Set(context, v8_str("obj"),
9160 object_template->NewInstance(context).ToLocalChecked())
9161 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009162
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009163 security_check_with_gc_called = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009164 CompileRun("obj[0] = new String(1002);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009165 CHECK(security_check_with_gc_called);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009166
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009167 security_check_with_gc_called = false;
9168 CHECK(CompileRun("obj[0]")
9169 ->ToString(context)
9170 .ToLocalChecked()
9171 ->Equals(context, v8_str("1002"))
9172 .FromJust());
9173 CHECK(security_check_with_gc_called);
Steve Blocka7e24c12009-10-30 11:49:00 +00009174}
9175
9176
9177THREADED_TEST(CrossDomainDelete) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009178 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009179 v8::HandleScope handle_scope(env1->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009180 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009181
9182 Local<Value> foo = v8_str("foo");
9183 Local<Value> bar = v8_str("bar");
9184
9185 // Set to the same domain.
9186 env1->SetSecurityToken(foo);
9187 env2->SetSecurityToken(foo);
9188
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009189 CHECK(
9190 env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
9191 CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009192
9193 // Change env2 to a different domain and delete env1.prop.
9194 env2->SetSecurityToken(bar);
9195 {
9196 Context::Scope scope_env2(env2);
9197 Local<Value> result =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009198 CompileRun("delete env1.prop");
9199 CHECK(result.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009200 }
9201
9202 // Check that env1.prop still exists.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009203 Local<Value> v =
9204 env1->Global()->Get(env1.local(), v8_str("prop")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009205 CHECK(v->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009206 CHECK_EQ(3, v->Int32Value(env1.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009207}
9208
9209
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009210THREADED_TEST(CrossDomainPropertyIsEnumerable) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009211 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009212 v8::HandleScope handle_scope(env1->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009213 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009214
9215 Local<Value> foo = v8_str("foo");
9216 Local<Value> bar = v8_str("bar");
9217
9218 // Set to the same domain.
9219 env1->SetSecurityToken(foo);
9220 env2->SetSecurityToken(foo);
9221
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009222 CHECK(
9223 env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
9224 CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009225
9226 // env1.prop is enumerable in env2.
9227 Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
9228 {
9229 Context::Scope scope_env2(env2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009230 Local<Value> result = CompileRun(test);
Steve Blocka7e24c12009-10-30 11:49:00 +00009231 CHECK(result->IsTrue());
9232 }
9233
9234 // Change env2 to a different domain and test again.
9235 env2->SetSecurityToken(bar);
9236 {
9237 Context::Scope scope_env2(env2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009238 Local<Value> result = CompileRun(test);
9239 CHECK(result.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009240 }
Steve Blocka7e24c12009-10-30 11:49:00 +00009241}
9242
9243
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009244THREADED_TEST(CrossDomainFor) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009245 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009246 v8::HandleScope handle_scope(env1->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009247 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009248
9249 Local<Value> foo = v8_str("foo");
9250 Local<Value> bar = v8_str("bar");
9251
9252 // Set to the same domain.
9253 env1->SetSecurityToken(foo);
9254 env2->SetSecurityToken(foo);
9255
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009256 CHECK(
9257 env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
9258 CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
9259
9260 // Change env2 to a different domain and set env1's global object
9261 // as the __proto__ of an object in env2 and enumerate properties
9262 // in for-in. It shouldn't enumerate properties on env1's global
9263 // object. It shouldn't throw either, just silently ignore them.
9264 env2->SetSecurityToken(bar);
9265 {
9266 Context::Scope scope_env2(env2);
9267 Local<Value> result = CompileRun(
9268 "(function() {"
9269 " try {"
9270 " for (var p in env1) {"
9271 " if (p == 'prop') return false;"
9272 " }"
9273 " return true;"
9274 " } catch (e) {"
9275 " return false;"
9276 " }"
9277 "})()");
9278 CHECK(result->IsTrue());
9279 }
9280}
9281
9282
9283THREADED_TEST(CrossDomainForInOnPrototype) {
9284 LocalContext env1;
9285 v8::HandleScope handle_scope(env1->GetIsolate());
9286 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
9287
9288 Local<Value> foo = v8_str("foo");
9289 Local<Value> bar = v8_str("bar");
9290
9291 // Set to the same domain.
9292 env1->SetSecurityToken(foo);
9293 env2->SetSecurityToken(foo);
9294
9295 CHECK(
9296 env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
9297 CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009298
9299 // Change env2 to a different domain and set env1's global object
9300 // as the __proto__ of an object in env2 and enumerate properties
9301 // in for-in. It shouldn't enumerate properties on env1's global
9302 // object.
9303 env2->SetSecurityToken(bar);
9304 {
9305 Context::Scope scope_env2(env2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009306 Local<Value> result = CompileRun(
9307 "(function() {"
9308 " var obj = { '__proto__': env1 };"
9309 " try {"
9310 " for (var p in obj) {"
9311 " if (p == 'prop') return false;"
9312 " }"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009313 " return true;"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009314 " } catch (e) {"
9315 " return false;"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009316 " }"
9317 "})()");
Steve Blocka7e24c12009-10-30 11:49:00 +00009318 CHECK(result->IsTrue());
9319 }
Steve Blocka7e24c12009-10-30 11:49:00 +00009320}
9321
9322
9323TEST(ContextDetachGlobal) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009324 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009325 v8::HandleScope handle_scope(env1->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009326 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009327
Steve Blocka7e24c12009-10-30 11:49:00 +00009328
9329 Local<Value> foo = v8_str("foo");
9330
9331 // Set to the same domain.
9332 env1->SetSecurityToken(foo);
9333 env2->SetSecurityToken(foo);
9334
9335 // Enter env2
9336 env2->Enter();
9337
Andrei Popescu74b3c142010-03-29 12:03:09 +01009338 // Create a function in env2 and add a reference to it in env1.
Steve Blocka7e24c12009-10-30 11:49:00 +00009339 Local<v8::Object> global2 = env2->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009340 CHECK(global2->Set(env2, v8_str("prop"),
9341 v8::Integer::New(env2->GetIsolate(), 1))
9342 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009343 CompileRun("function getProp() {return prop;}");
9344
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009345 CHECK(env1->Global()
9346 ->Set(env1.local(), v8_str("getProp"),
9347 global2->Get(env2, v8_str("getProp")).ToLocalChecked())
9348 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009349
Andrei Popescu74b3c142010-03-29 12:03:09 +01009350 // Detach env2's global, and reuse the global object of env2
Steve Blocka7e24c12009-10-30 11:49:00 +00009351 env2->Exit();
9352 env2->DetachGlobal();
Steve Blocka7e24c12009-10-30 11:49:00 +00009353
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009354 v8::Local<Context> env3 = Context::New(
9355 env1->GetIsolate(), 0, v8::Local<v8::ObjectTemplate>(), global2);
Steve Blocka7e24c12009-10-30 11:49:00 +00009356 env3->SetSecurityToken(v8_str("bar"));
Steve Blocka7e24c12009-10-30 11:49:00 +00009357
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009358 env3->Enter();
Steve Blocka7e24c12009-10-30 11:49:00 +00009359 Local<v8::Object> global3 = env3->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009360 CHECK(global2->Equals(env3, global3).FromJust());
9361 CHECK(global3->Get(env3, v8_str("prop")).ToLocalChecked()->IsUndefined());
9362 CHECK(global3->Get(env3, v8_str("getProp")).ToLocalChecked()->IsUndefined());
9363 CHECK(global3->Set(env3, v8_str("prop"),
9364 v8::Integer::New(env3->GetIsolate(), -1))
9365 .FromJust());
9366 CHECK(global3->Set(env3, v8_str("prop2"),
9367 v8::Integer::New(env3->GetIsolate(), 2))
9368 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009369 env3->Exit();
9370
9371 // Call getProp in env1, and it should return the value 1
9372 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009373 Local<v8::Object> global1 = env1->Global();
9374 Local<Value> get_prop =
9375 global1->Get(env1.local(), v8_str("getProp")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009376 CHECK(get_prop->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009377 v8::TryCatch try_catch(env1->GetIsolate());
9378 Local<Value> r = Function::Cast(*get_prop)
9379 ->Call(env1.local(), global1, 0, NULL)
9380 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009381 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009382 CHECK_EQ(1, r->Int32Value(env1.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009383 }
9384
9385 // Check that env3 is not accessible from env1
9386 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009387 v8::MaybeLocal<Value> r = global3->Get(env1.local(), v8_str("prop2"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009388 CHECK(r.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009389 }
Steve Blocka7e24c12009-10-30 11:49:00 +00009390}
9391
9392
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009393TEST(DetachGlobal) {
Andrei Popescu74b3c142010-03-29 12:03:09 +01009394 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009395 v8::HandleScope scope(env1->GetIsolate());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009396
9397 // Create second environment.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009398 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009399
9400 Local<Value> foo = v8_str("foo");
9401
9402 // Set same security token for env1 and env2.
9403 env1->SetSecurityToken(foo);
9404 env2->SetSecurityToken(foo);
9405
9406 // Create a property on the global object in env2.
9407 {
9408 v8::Context::Scope scope(env2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009409 CHECK(env2->Global()
9410 ->Set(env2, v8_str("p"), v8::Integer::New(env2->GetIsolate(), 42))
9411 .FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009412 }
9413
9414 // Create a reference to env2 global from env1 global.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009415 CHECK(env1->Global()
9416 ->Set(env1.local(), v8_str("other"), env2->Global())
9417 .FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009418
9419 // Check that we have access to other.p in env2 from env1.
9420 Local<Value> result = CompileRun("other.p");
9421 CHECK(result->IsInt32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009422 CHECK_EQ(42, result->Int32Value(env1.local()).FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009423
9424 // Hold on to global from env2 and detach global from env2.
9425 Local<v8::Object> global2 = env2->Global();
9426 env2->DetachGlobal();
9427
9428 // Check that the global has been detached. No other.p property can
9429 // be found.
9430 result = CompileRun("other.p");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009431 CHECK(result.IsEmpty());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009432
9433 // Reuse global2 for env3.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009434 v8::Local<Context> env3 = Context::New(
9435 env1->GetIsolate(), 0, v8::Local<v8::ObjectTemplate>(), global2);
9436 CHECK(global2->Equals(env1.local(), env3->Global()).FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009437
9438 // Start by using the same security token for env3 as for env1 and env2.
9439 env3->SetSecurityToken(foo);
9440
9441 // Create a property on the global object in env3.
9442 {
9443 v8::Context::Scope scope(env3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009444 CHECK(env3->Global()
9445 ->Set(env3, v8_str("p"), v8::Integer::New(env3->GetIsolate(), 24))
9446 .FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009447 }
9448
9449 // Check that other.p is now the property in env3 and that we have access.
9450 result = CompileRun("other.p");
9451 CHECK(result->IsInt32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009452 CHECK_EQ(24, result->Int32Value(env3).FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009453
9454 // Change security token for env3 to something different from env1 and env2.
9455 env3->SetSecurityToken(v8_str("bar"));
9456
9457 // Check that we do not have access to other.p in env1. |other| is now
9458 // the global object for env3 which has a different security token,
9459 // so access should be blocked.
9460 result = CompileRun("other.p");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009461 CHECK(result.IsEmpty());
9462}
Andrei Popescu74b3c142010-03-29 12:03:09 +01009463
Andrei Popescu74b3c142010-03-29 12:03:09 +01009464
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009465void GetThisX(const v8::FunctionCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009466 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009467 info.GetReturnValue().Set(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009468 context->Global()->Get(context, v8_str("x")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009469}
Andrei Popescu74b3c142010-03-29 12:03:09 +01009470
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009471
9472TEST(DetachedAccesses) {
9473 LocalContext env1;
9474 v8::HandleScope scope(env1->GetIsolate());
9475
9476 // Create second environment.
9477 Local<ObjectTemplate> inner_global_template =
9478 FunctionTemplate::New(env1->GetIsolate())->InstanceTemplate();
9479 inner_global_template ->SetAccessorProperty(
9480 v8_str("this_x"), FunctionTemplate::New(env1->GetIsolate(), GetThisX));
9481 v8::Local<Context> env2 =
9482 Context::New(env1->GetIsolate(), NULL, inner_global_template);
9483
9484 Local<Value> foo = v8_str("foo");
9485
9486 // Set same security token for env1 and env2.
9487 env1->SetSecurityToken(foo);
9488 env2->SetSecurityToken(foo);
9489
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009490 CHECK(env1->Global()
9491 ->Set(env1.local(), v8_str("x"), v8_str("env1_x"))
9492 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009493
9494 {
9495 v8::Context::Scope scope(env2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009496 CHECK(env2->Global()->Set(env2, v8_str("x"), v8_str("env2_x")).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009497 CompileRun(
9498 "function bound_x() { return x; }"
9499 "function get_x() { return this.x; }"
9500 "function get_x_w() { return (function() {return this.x;})(); }");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009501 CHECK(env1->Global()
9502 ->Set(env1.local(), v8_str("bound_x"), CompileRun("bound_x"))
9503 .FromJust());
9504 CHECK(env1->Global()
9505 ->Set(env1.local(), v8_str("get_x"), CompileRun("get_x"))
9506 .FromJust());
9507 CHECK(env1->Global()
9508 ->Set(env1.local(), v8_str("get_x_w"), CompileRun("get_x_w"))
9509 .FromJust());
9510 env1->Global()
9511 ->Set(env1.local(), v8_str("this_x"),
9512 CompileRun("Object.getOwnPropertyDescriptor(this, 'this_x').get"))
9513 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009514 }
9515
9516 Local<Object> env2_global = env2->Global();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009517 env2->DetachGlobal();
9518
9519 Local<Value> result;
9520 result = CompileRun("bound_x()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009521 CHECK(v8_str("env2_x")->Equals(env1.local(), result).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009522 result = CompileRun("get_x()");
9523 CHECK(result.IsEmpty());
9524 result = CompileRun("get_x_w()");
9525 CHECK(result.IsEmpty());
9526 result = CompileRun("this_x()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009527 CHECK(v8_str("env2_x")->Equals(env1.local(), result).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009528
9529 // Reattach env2's proxy
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009530 env2 = Context::New(env1->GetIsolate(), 0, v8::Local<v8::ObjectTemplate>(),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009531 env2_global);
9532 env2->SetSecurityToken(foo);
9533 {
9534 v8::Context::Scope scope(env2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009535 CHECK(env2->Global()->Set(env2, v8_str("x"), v8_str("env3_x")).FromJust());
9536 CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009537 result = CompileRun(
9538 "results = [];"
9539 "for (var i = 0; i < 4; i++ ) {"
9540 " results.push(env1.bound_x());"
9541 " results.push(env1.get_x());"
9542 " results.push(env1.get_x_w());"
9543 " results.push(env1.this_x());"
9544 "}"
9545 "results");
9546 Local<v8::Array> results = Local<v8::Array>::Cast(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009547 CHECK_EQ(16u, results->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009548 for (int i = 0; i < 16; i += 4) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009549 CHECK(v8_str("env2_x")
9550 ->Equals(env2, results->Get(env2, i + 0).ToLocalChecked())
9551 .FromJust());
9552 CHECK(v8_str("env1_x")
9553 ->Equals(env2, results->Get(env2, i + 1).ToLocalChecked())
9554 .FromJust());
9555 CHECK(v8_str("env3_x")
9556 ->Equals(env2, results->Get(env2, i + 2).ToLocalChecked())
9557 .FromJust());
9558 CHECK(v8_str("env2_x")
9559 ->Equals(env2, results->Get(env2, i + 3).ToLocalChecked())
9560 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009561 }
9562 }
9563
9564 result = CompileRun(
9565 "results = [];"
9566 "for (var i = 0; i < 4; i++ ) {"
9567 " results.push(bound_x());"
9568 " results.push(get_x());"
9569 " results.push(get_x_w());"
9570 " results.push(this_x());"
9571 "}"
9572 "results");
9573 Local<v8::Array> results = Local<v8::Array>::Cast(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009574 CHECK_EQ(16u, results->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009575 for (int i = 0; i < 16; i += 4) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009576 CHECK(v8_str("env2_x")
9577 ->Equals(env1.local(),
9578 results->Get(env1.local(), i + 0).ToLocalChecked())
9579 .FromJust());
9580 CHECK(v8_str("env3_x")
9581 ->Equals(env1.local(),
9582 results->Get(env1.local(), i + 1).ToLocalChecked())
9583 .FromJust());
9584 CHECK(v8_str("env3_x")
9585 ->Equals(env1.local(),
9586 results->Get(env1.local(), i + 2).ToLocalChecked())
9587 .FromJust());
9588 CHECK(v8_str("env2_x")
9589 ->Equals(env1.local(),
9590 results->Get(env1.local(), i + 3).ToLocalChecked())
9591 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009592 }
9593
9594 result = CompileRun(
9595 "results = [];"
9596 "for (var i = 0; i < 4; i++ ) {"
9597 " results.push(this.bound_x());"
9598 " results.push(this.get_x());"
9599 " results.push(this.get_x_w());"
9600 " results.push(this.this_x());"
9601 "}"
9602 "results");
9603 results = Local<v8::Array>::Cast(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009604 CHECK_EQ(16u, results->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009605 for (int i = 0; i < 16; i += 4) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009606 CHECK(v8_str("env2_x")
9607 ->Equals(env1.local(),
9608 results->Get(env1.local(), i + 0).ToLocalChecked())
9609 .FromJust());
9610 CHECK(v8_str("env1_x")
9611 ->Equals(env1.local(),
9612 results->Get(env1.local(), i + 1).ToLocalChecked())
9613 .FromJust());
9614 CHECK(v8_str("env3_x")
9615 ->Equals(env1.local(),
9616 results->Get(env1.local(), i + 2).ToLocalChecked())
9617 .FromJust());
9618 CHECK(v8_str("env2_x")
9619 ->Equals(env1.local(),
9620 results->Get(env1.local(), i + 3).ToLocalChecked())
9621 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009622 }
Andrei Popescu74b3c142010-03-29 12:03:09 +01009623}
9624
9625
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009626static bool allowed_access = false;
9627static bool AccessBlocker(Local<v8::Context> accessing_context,
9628 Local<v8::Object> accessed_object) {
9629 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
9630 return context->Global()->Equals(context, accessed_object).FromJust() ||
9631 allowed_access;
Steve Blocka7e24c12009-10-30 11:49:00 +00009632}
9633
9634
9635static int g_echo_value = -1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009636
9637
9638static void EchoGetter(
9639 Local<String> name,
9640 const v8::PropertyCallbackInfo<v8::Value>& info) {
9641 info.GetReturnValue().Set(v8_num(g_echo_value));
Steve Blocka7e24c12009-10-30 11:49:00 +00009642}
9643
9644
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009645static void EchoSetter(Local<String> name, Local<Value> value,
9646 const v8::PropertyCallbackInfo<void>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009647 if (value->IsNumber())
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009648 g_echo_value =
9649 value->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00009650}
9651
9652
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009653static void UnreachableGetter(
9654 Local<String> name,
9655 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009656 CHECK(false); // This function should not be called..
Steve Blocka7e24c12009-10-30 11:49:00 +00009657}
9658
9659
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009660static void UnreachableSetter(Local<String>,
9661 Local<Value>,
9662 const v8::PropertyCallbackInfo<void>&) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009663 CHECK(false); // This function should nto be called.
9664}
9665
9666
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009667static void UnreachableFunction(
9668 const v8::FunctionCallbackInfo<v8::Value>& info) {
9669 CHECK(false); // This function should not be called..
9670}
9671
9672
Steve Block1e0659c2011-05-24 12:43:12 +01009673TEST(AccessControl) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009674 v8::Isolate* isolate = CcTest::isolate();
9675 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009676 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009677 v8::ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00009678
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009679 global_template->SetAccessCheckCallback(AccessBlocker);
Steve Blocka7e24c12009-10-30 11:49:00 +00009680
9681 // Add an accessor accessible by cross-domain JS code.
9682 global_template->SetAccessor(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009683 v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
Steve Blocka7e24c12009-10-30 11:49:00 +00009684 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
9685
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009686
Steve Blocka7e24c12009-10-30 11:49:00 +00009687 // Add an accessor that is not accessible by cross-domain JS code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009688 global_template->SetAccessor(v8_str("blocked_prop"), UnreachableGetter,
9689 UnreachableSetter, v8::Local<Value>(),
Steve Blocka7e24c12009-10-30 11:49:00 +00009690 v8::DEFAULT);
9691
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009692 global_template->SetAccessorProperty(
9693 v8_str("blocked_js_prop"),
9694 v8::FunctionTemplate::New(isolate, UnreachableFunction),
9695 v8::FunctionTemplate::New(isolate, UnreachableFunction),
9696 v8::None,
9697 v8::DEFAULT);
9698
Steve Blocka7e24c12009-10-30 11:49:00 +00009699 // Create an environment
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009700 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
Steve Blocka7e24c12009-10-30 11:49:00 +00009701 context0->Enter();
9702
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009703 v8::Local<v8::Object> global0 = context0->Global();
Steve Blocka7e24c12009-10-30 11:49:00 +00009704
Steve Block1e0659c2011-05-24 12:43:12 +01009705 // Define a property with JS getter and setter.
9706 CompileRun(
9707 "function getter() { return 'getter'; };\n"
9708 "function setter() { return 'setter'; }\n"
9709 "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
9710
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009711 Local<Value> getter =
9712 global0->Get(context0, v8_str("getter")).ToLocalChecked();
9713 Local<Value> setter =
9714 global0->Get(context0, v8_str("setter")).ToLocalChecked();
Steve Block1e0659c2011-05-24 12:43:12 +01009715
9716 // And define normal element.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009717 CHECK(global0->Set(context0, 239, v8_str("239")).FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +01009718
9719 // Define an element with JS getter and setter.
9720 CompileRun(
9721 "function el_getter() { return 'el_getter'; };\n"
9722 "function el_setter() { return 'el_setter'; };\n"
9723 "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
9724
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009725 Local<Value> el_getter =
9726 global0->Get(context0, v8_str("el_getter")).ToLocalChecked();
9727 Local<Value> el_setter =
9728 global0->Get(context0, v8_str("el_setter")).ToLocalChecked();
Steve Block1e0659c2011-05-24 12:43:12 +01009729
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009730 v8::HandleScope scope1(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00009731
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009732 v8::Local<Context> context1 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00009733 context1->Enter();
9734
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009735 v8::Local<v8::Object> global1 = context1->Global();
9736 CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009737
Steve Block1e0659c2011-05-24 12:43:12 +01009738 // Access blocked property.
9739 CompileRun("other.blocked_prop = 1");
9740
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009741 CHECK(CompileRun("other.blocked_prop").IsEmpty());
9742 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
9743 .IsEmpty());
9744 CHECK(
9745 CompileRun("propertyIsEnumerable.call(other, 'blocked_prop')").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +01009746
9747 // Access blocked element.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009748 CHECK(CompileRun("other[239] = 1").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +01009749
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009750 CHECK(CompileRun("other[239]").IsEmpty());
9751 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '239')").IsEmpty());
9752 CHECK(CompileRun("propertyIsEnumerable.call(other, '239')").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +01009753
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009754 allowed_access = true;
9755 // Now we can enumerate the property.
Steve Block1e0659c2011-05-24 12:43:12 +01009756 ExpectTrue("propertyIsEnumerable.call(other, '239')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009757 allowed_access = false;
Steve Block1e0659c2011-05-24 12:43:12 +01009758
9759 // Access a property with JS accessor.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009760 CHECK(CompileRun("other.js_accessor_p = 2").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +01009761
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009762 CHECK(CompileRun("other.js_accessor_p").IsEmpty());
9763 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'js_accessor_p')")
9764 .IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +01009765
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009766 allowed_access = true;
Steve Block1e0659c2011-05-24 12:43:12 +01009767
9768 ExpectString("other.js_accessor_p", "getter");
9769 ExpectObject(
9770 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
Steve Block1e0659c2011-05-24 12:43:12 +01009771 ExpectObject(
9772 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
9773 ExpectUndefined(
9774 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
9775
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009776 allowed_access = false;
Steve Block1e0659c2011-05-24 12:43:12 +01009777
9778 // Access an element with JS accessor.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009779 CHECK(CompileRun("other[42] = 2").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +01009780
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009781 CHECK(CompileRun("other[42]").IsEmpty());
9782 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '42')").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +01009783
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009784 allowed_access = true;
Steve Block1e0659c2011-05-24 12:43:12 +01009785
9786 ExpectString("other[42]", "el_getter");
9787 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
Steve Block1e0659c2011-05-24 12:43:12 +01009788 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
9789 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
9790
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009791 allowed_access = false;
Steve Block1e0659c2011-05-24 12:43:12 +01009792
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009793 v8::Local<Value> value;
Steve Blocka7e24c12009-10-30 11:49:00 +00009794
Steve Blocka7e24c12009-10-30 11:49:00 +00009795 // Access accessible property
Steve Block1e0659c2011-05-24 12:43:12 +01009796 value = CompileRun("other.accessible_prop = 3");
Steve Blocka7e24c12009-10-30 11:49:00 +00009797 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009798 CHECK_EQ(3, value->Int32Value(context1).FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +00009799 CHECK_EQ(3, g_echo_value);
Steve Blocka7e24c12009-10-30 11:49:00 +00009800
Steve Block1e0659c2011-05-24 12:43:12 +01009801 value = CompileRun("other.accessible_prop");
Steve Blocka7e24c12009-10-30 11:49:00 +00009802 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009803 CHECK_EQ(3, value->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009804
Steve Block1e0659c2011-05-24 12:43:12 +01009805 value = CompileRun(
9806 "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
9807 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009808 CHECK_EQ(3, value->Int32Value(context1).FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +01009809
9810 value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
Steve Blocka7e24c12009-10-30 11:49:00 +00009811 CHECK(value->IsTrue());
9812
9813 // Enumeration doesn't enumerate accessors from inaccessible objects in
9814 // the prototype chain even if the accessors are in themselves accessible.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009815 // Enumeration doesn't throw, it silently ignores what it can't access.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009816 value = CompileRun(
9817 "(function() {"
9818 " var obj = { '__proto__': other };"
9819 " try {"
9820 " for (var p in obj) {"
9821 " if (p == 'accessible_prop' ||"
9822 " p == 'blocked_js_prop' ||"
9823 " p == 'blocked_js_prop') {"
9824 " return false;"
9825 " }"
9826 " }"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009827 " return true;"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009828 " } catch (e) {"
9829 " return false;"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009830 " }"
9831 "})()");
Steve Block1e0659c2011-05-24 12:43:12 +01009832 CHECK(value->IsTrue());
Steve Blocka7e24c12009-10-30 11:49:00 +00009833
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009834 // Test that preventExtensions fails on a non-accessible object even if that
9835 // object is already non-extensible.
9836 CHECK(global1->Set(context1, v8_str("checked_object"),
9837 global_template->NewInstance(context1).ToLocalChecked())
9838 .FromJust());
9839 allowed_access = true;
9840 CompileRun("Object.preventExtensions(checked_object)");
9841 ExpectFalse("Object.isExtensible(checked_object)");
9842 allowed_access = false;
9843 CHECK(CompileRun("Object.preventExtensions(checked_object)").IsEmpty());
9844
Steve Blocka7e24c12009-10-30 11:49:00 +00009845 context1->Exit();
9846 context0->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +00009847}
9848
9849
Ben Murdoche0cee9b2011-05-25 10:26:03 +01009850TEST(AccessControlES5) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009851 v8::Isolate* isolate = CcTest::isolate();
9852 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009853 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009854 v8::ObjectTemplate::New(isolate);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01009855
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009856 global_template->SetAccessCheckCallback(AccessBlocker);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01009857
Steve Block44f0eee2011-05-26 01:26:41 +01009858 // Add accessible accessor.
9859 global_template->SetAccessor(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009860 v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
Steve Block44f0eee2011-05-26 01:26:41 +01009861 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
9862
9863
Ben Murdoche0cee9b2011-05-25 10:26:03 +01009864 // Add an accessor that is not accessible by cross-domain JS code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009865 global_template->SetAccessor(v8_str("blocked_prop"), UnreachableGetter,
9866 UnreachableSetter, v8::Local<Value>(),
Ben Murdoche0cee9b2011-05-25 10:26:03 +01009867 v8::DEFAULT);
9868
9869 // Create an environment
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009870 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01009871 context0->Enter();
9872
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009873 v8::Local<v8::Object> global0 = context0->Global();
Ben Murdoche0cee9b2011-05-25 10:26:03 +01009874
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009875 v8::Local<Context> context1 = Context::New(isolate);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01009876 context1->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009877 v8::Local<v8::Object> global1 = context1->Global();
9878 CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
Ben Murdoche0cee9b2011-05-25 10:26:03 +01009879
9880 // Regression test for issue 1154.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009881 CHECK(CompileRun("Object.keys(other).length == 1")
9882 ->BooleanValue(context1)
9883 .FromJust());
9884 CHECK(CompileRun("Object.keys(other)[0] == 'accessible_prop'")
9885 ->BooleanValue(context1)
9886 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009887 CHECK(CompileRun("other.blocked_prop").IsEmpty());
Ben Murdoche0cee9b2011-05-25 10:26:03 +01009888
9889 // Regression test for issue 1027.
9890 CompileRun("Object.defineProperty(\n"
9891 " other, 'blocked_prop', {configurable: false})");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009892 CHECK(CompileRun("other.blocked_prop").IsEmpty());
9893 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
9894 .IsEmpty());
Ben Murdoche0cee9b2011-05-25 10:26:03 +01009895
9896 // Regression test for issue 1171.
9897 ExpectTrue("Object.isExtensible(other)");
9898 CompileRun("Object.preventExtensions(other)");
9899 ExpectTrue("Object.isExtensible(other)");
9900
9901 // Object.seal and Object.freeze.
9902 CompileRun("Object.freeze(other)");
9903 ExpectTrue("Object.isExtensible(other)");
9904
9905 CompileRun("Object.seal(other)");
9906 ExpectTrue("Object.isExtensible(other)");
Steve Block44f0eee2011-05-26 01:26:41 +01009907
9908 // Regression test for issue 1250.
9909 // Make sure that we can set the accessible accessors value using normal
9910 // assignment.
9911 CompileRun("other.accessible_prop = 42");
9912 CHECK_EQ(42, g_echo_value);
9913
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009914 // [[DefineOwnProperty]] always throws for access-checked objects.
9915 CHECK(
9916 CompileRun("Object.defineProperty(other, 'accessible_prop', {value: 43})")
9917 .IsEmpty());
9918 CHECK(CompileRun("other.accessible_prop == 42")->IsTrue());
9919 CHECK_EQ(42, g_echo_value); // Make sure we didn't call the setter.
Ben Murdoche0cee9b2011-05-25 10:26:03 +01009920}
9921
9922
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009923static bool AccessAlwaysBlocked(Local<v8::Context> accessing_context,
9924 Local<v8::Object> global) {
9925 i::PrintF("Access blocked.\n");
Leon Clarke4515c472010-02-03 11:58:03 +00009926 return false;
9927}
9928
9929
9930THREADED_TEST(AccessControlGetOwnPropertyNames) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009931 v8::Isolate* isolate = CcTest::isolate();
9932 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009933 v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
Leon Clarke4515c472010-02-03 11:58:03 +00009934
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009935 obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009936 obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
9937
9938 // Add an accessor accessible by cross-domain JS code.
9939 obj_template->SetAccessor(
9940 v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
9941 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
Leon Clarke4515c472010-02-03 11:58:03 +00009942
9943 // Create an environment
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009944 v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
Leon Clarke4515c472010-02-03 11:58:03 +00009945 context0->Enter();
9946
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009947 v8::Local<v8::Object> global0 = context0->Global();
Leon Clarke4515c472010-02-03 11:58:03 +00009948
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009949 v8::HandleScope scope1(CcTest::isolate());
Leon Clarke4515c472010-02-03 11:58:03 +00009950
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009951 v8::Local<Context> context1 = Context::New(isolate);
Leon Clarke4515c472010-02-03 11:58:03 +00009952 context1->Enter();
9953
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009954 v8::Local<v8::Object> global1 = context1->Global();
9955 CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
9956 CHECK(global1->Set(context1, v8_str("object"),
9957 obj_template->NewInstance(context1).ToLocalChecked())
9958 .FromJust());
Leon Clarke4515c472010-02-03 11:58:03 +00009959
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009960 v8::Local<Value> value;
Leon Clarke4515c472010-02-03 11:58:03 +00009961
9962 // Attempt to get the property names of the other global object and
9963 // of an object that requires access checks. Accessing the other
9964 // global object should be blocked by access checks on the global
9965 // proxy object. Accessing the object that requires access checks
9966 // is blocked by the access checks on the object itself.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009967 value = CompileRun(
9968 "var names = Object.getOwnPropertyNames(other);"
9969 "names.length == 1 && names[0] == 'accessible_prop';");
9970 CHECK(value->BooleanValue(context1).FromJust());
Leon Clarke4515c472010-02-03 11:58:03 +00009971
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009972 value = CompileRun(
9973 "var names = Object.getOwnPropertyNames(object);"
9974 "names.length == 1 && names[0] == 'accessible_prop';");
9975 CHECK(value->BooleanValue(context1).FromJust());
Leon Clarke4515c472010-02-03 11:58:03 +00009976
9977 context1->Exit();
9978 context0->Exit();
Leon Clarke4515c472010-02-03 11:58:03 +00009979}
9980
9981
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009982TEST(Regress470113) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009983 v8::Isolate* isolate = CcTest::isolate();
9984 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009985 v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
9986 obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009987 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009988 CHECK(env->Global()
9989 ->Set(env.local(), v8_str("prohibited"),
9990 obj_template->NewInstance(env.local()).ToLocalChecked())
9991 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009992
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009993 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009994 v8::TryCatch try_catch(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009995 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009996 "'use strict';\n"
9997 "class C extends Object {\n"
9998 " m() { super.powned = 'Powned!'; }\n"
9999 "}\n"
10000 "let c = new C();\n"
10001 "c.m.call(prohibited)");
10002
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010003 CHECK(try_catch.HasCaught());
10004 }
Steve Block8defd9f2010-07-08 12:39:36 +010010005}
10006
10007
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010008static void ConstTenGetter(Local<String> name,
10009 const v8::PropertyCallbackInfo<v8::Value>& info) {
10010 info.GetReturnValue().Set(v8_num(10));
Steve Blocka7e24c12009-10-30 11:49:00 +000010011}
10012
10013
10014THREADED_TEST(CrossDomainAccessors) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010015 v8::Isolate* isolate = CcTest::isolate();
10016 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010017
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010018 v8::Local<v8::FunctionTemplate> func_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010019 v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010020
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010021 v8::Local<v8::ObjectTemplate> global_template =
Steve Blocka7e24c12009-10-30 11:49:00 +000010022 func_template->InstanceTemplate();
10023
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010024 v8::Local<v8::ObjectTemplate> proto_template =
Steve Blocka7e24c12009-10-30 11:49:00 +000010025 func_template->PrototypeTemplate();
10026
10027 // Add an accessor to proto that's accessible by cross-domain JS code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010028 proto_template->SetAccessor(v8_str("accessible"), ConstTenGetter, 0,
10029 v8::Local<Value>(), v8::ALL_CAN_READ);
Steve Blocka7e24c12009-10-30 11:49:00 +000010030
10031 // Add an accessor that is not accessible by cross-domain JS code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010032 global_template->SetAccessor(v8_str("unreachable"), UnreachableGetter, 0,
10033 v8::Local<Value>(), v8::DEFAULT);
Steve Blocka7e24c12009-10-30 11:49:00 +000010034
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010035 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
Steve Blocka7e24c12009-10-30 11:49:00 +000010036 context0->Enter();
10037
10038 Local<v8::Object> global = context0->Global();
10039 // Add a normal property that shadows 'accessible'
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010040 CHECK(global->Set(context0, v8_str("accessible"), v8_num(11)).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010041
10042 // Enter a new context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010043 v8::HandleScope scope1(CcTest::isolate());
10044 v8::Local<Context> context1 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010045 context1->Enter();
10046
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010047 v8::Local<v8::Object> global1 = context1->Global();
10048 CHECK(global1->Set(context1, v8_str("other"), global).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010049
10050 // Should return 10, instead of 11
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010051 v8::Local<Value> value =
10052 v8_compile("other.accessible")->Run(context1).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000010053 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010054 CHECK_EQ(10, value->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010055
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010056 v8::MaybeLocal<v8::Value> maybe_value =
10057 v8_compile("other.unreachable")->Run(context1);
10058 CHECK(maybe_value.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000010059
10060 context1->Exit();
10061 context0->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +000010062}
10063
10064
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010065static int access_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +000010066
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010067static bool AccessCounter(Local<v8::Context> accessing_context,
10068 Local<v8::Object> accessed_object) {
10069 access_count++;
Steve Blocka7e24c12009-10-30 11:49:00 +000010070 return true;
10071}
10072
10073
10074// This one is too easily disturbed by other tests.
10075TEST(AccessControlIC) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010076 access_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +000010077
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010078 v8::Isolate* isolate = CcTest::isolate();
10079 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010080
10081 // Create an environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010082 v8::Local<Context> context0 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010083 context0->Enter();
10084
10085 // Create an object that requires access-check functions to be
10086 // called for cross-domain access.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010087 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010088 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010089 object_template->SetAccessCheckCallback(AccessCounter);
10090 Local<v8::Object> object =
10091 object_template->NewInstance(context0).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000010092
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010093 v8::HandleScope scope1(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010094
10095 // Create another environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010096 v8::Local<Context> context1 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010097 context1->Enter();
10098
10099 // Make easy access to the object from the other environment.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010100 v8::Local<v8::Object> global1 = context1->Global();
10101 CHECK(global1->Set(context1, v8_str("obj"), object).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010102
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010103 v8::Local<Value> value;
Steve Blocka7e24c12009-10-30 11:49:00 +000010104
10105 // Check that the named access-control function is called every time.
10106 CompileRun("function testProp(obj) {"
10107 " for (var i = 0; i < 10; i++) obj.prop = 1;"
10108 " for (var j = 0; j < 10; j++) obj.prop;"
10109 " return obj.prop"
10110 "}");
10111 value = CompileRun("testProp(obj)");
10112 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010113 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10114 CHECK_EQ(21, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010115
10116 // Check that the named access-control function is called every time.
10117 CompileRun("var p = 'prop';"
10118 "function testKeyed(obj) {"
10119 " for (var i = 0; i < 10; i++) obj[p] = 1;"
10120 " for (var j = 0; j < 10; j++) obj[p];"
10121 " return obj[p];"
10122 "}");
10123 // Use obj which requires access checks. No inline caching is used
10124 // in that case.
10125 value = CompileRun("testKeyed(obj)");
10126 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010127 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10128 CHECK_EQ(42, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010129 // Force the inline caches into generic state and try again.
10130 CompileRun("testKeyed({ a: 0 })");
10131 CompileRun("testKeyed({ b: 0 })");
10132 value = CompileRun("testKeyed(obj)");
10133 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010134 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10135 CHECK_EQ(63, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010136
10137 // Check that the indexed access-control function is called every time.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010138 access_count = 0;
10139
Steve Blocka7e24c12009-10-30 11:49:00 +000010140 CompileRun("function testIndexed(obj) {"
10141 " for (var i = 0; i < 10; i++) obj[0] = 1;"
10142 " for (var j = 0; j < 10; j++) obj[0];"
10143 " return obj[0]"
10144 "}");
10145 value = CompileRun("testIndexed(obj)");
10146 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010147 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10148 CHECK_EQ(21, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010149 // Force the inline caches into generic state.
10150 CompileRun("testIndexed(new Array(1))");
10151 // Test that the indexed access check is called.
10152 value = CompileRun("testIndexed(obj)");
10153 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010154 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10155 CHECK_EQ(42, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010156
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010157 access_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +000010158 // Check that the named access check is called when invoking
10159 // functions on an object that requires access checks.
10160 CompileRun("obj.f = function() {}");
10161 CompileRun("function testCallNormal(obj) {"
10162 " for (var i = 0; i < 10; i++) obj.f();"
10163 "}");
10164 CompileRun("testCallNormal(obj)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010165 printf("%i\n", access_count);
10166 CHECK_EQ(11, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010167
10168 // Force obj into slow case.
10169 value = CompileRun("delete obj.prop");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010170 CHECK(value->BooleanValue(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010171 // Force inline caches into dictionary probing mode.
10172 CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
10173 // Test that the named access check is called.
10174 value = CompileRun("testProp(obj);");
10175 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010176 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10177 CHECK_EQ(33, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010178
10179 // Force the call inline cache into dictionary probing mode.
10180 CompileRun("o.f = function() {}; testCallNormal(o)");
10181 // Test that the named access check is still called for each
10182 // invocation of the function.
10183 value = CompileRun("testCallNormal(obj)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010184 CHECK_EQ(43, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010185
10186 context1->Exit();
10187 context0->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +000010188}
10189
10190
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010191THREADED_TEST(Version) { v8::V8::GetVersion(); }
Steve Blocka7e24c12009-10-30 11:49:00 +000010192
10193
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010194static void InstanceFunctionCallback(
10195 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010196 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010197 args.GetReturnValue().Set(v8_num(12));
Steve Blocka7e24c12009-10-30 11:49:00 +000010198}
10199
10200
10201THREADED_TEST(InstanceProperties) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010202 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010203 v8::Isolate* isolate = context->GetIsolate();
10204 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010205
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010206 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010207 Local<ObjectTemplate> instance = t->InstanceTemplate();
10208
10209 instance->Set(v8_str("x"), v8_num(42));
10210 instance->Set(v8_str("f"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010211 v8::FunctionTemplate::New(isolate, InstanceFunctionCallback));
Steve Blocka7e24c12009-10-30 11:49:00 +000010212
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010213 Local<Value> o = t->GetFunction(context.local())
10214 .ToLocalChecked()
10215 ->NewInstance(context.local())
10216 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000010217
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010218 CHECK(context->Global()->Set(context.local(), v8_str("i"), o).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010219 Local<Value> value = CompileRun("i.x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010220 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010221
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010222 value = CompileRun("i.f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010223 CHECK_EQ(12, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010224}
10225
10226
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010227static void GlobalObjectInstancePropertiesGet(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010228 Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>&) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010229 ApiTestFuzzer::Fuzz();
Steve Blocka7e24c12009-10-30 11:49:00 +000010230}
10231
10232
10233THREADED_TEST(GlobalObjectInstanceProperties) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010234 v8::Isolate* isolate = CcTest::isolate();
10235 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010236
10237 Local<Value> global_object;
10238
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010239 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010240 t->InstanceTemplate()->SetHandler(
10241 v8::NamedPropertyHandlerConfiguration(GlobalObjectInstancePropertiesGet));
Steve Blocka7e24c12009-10-30 11:49:00 +000010242 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10243 instance_template->Set(v8_str("x"), v8_num(42));
10244 instance_template->Set(v8_str("f"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010245 v8::FunctionTemplate::New(isolate,
10246 InstanceFunctionCallback));
Steve Blocka7e24c12009-10-30 11:49:00 +000010247
Ben Murdochb0fe1622011-05-05 13:52:32 +010010248 // The script to check how Crankshaft compiles missing global function
10249 // invocations. function g is not defined and should throw on call.
10250 const char* script =
10251 "function wrapper(call) {"
10252 " var x = 0, y = 1;"
10253 " for (var i = 0; i < 1000; i++) {"
10254 " x += i * 100;"
10255 " y += i * 100;"
10256 " }"
10257 " if (call) g();"
10258 "}"
10259 "for (var i = 0; i < 17; i++) wrapper(false);"
10260 "var thrown = 0;"
10261 "try { wrapper(true); } catch (e) { thrown = 1; };"
10262 "thrown";
10263
Steve Blocka7e24c12009-10-30 11:49:00 +000010264 {
10265 LocalContext env(NULL, instance_template);
10266 // Hold on to the global object so it can be used again in another
10267 // environment initialization.
10268 global_object = env->Global();
10269
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010270 Local<Value> value = CompileRun("x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010271 CHECK_EQ(42, value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010272 value = CompileRun("f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010273 CHECK_EQ(12, value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010274 value = CompileRun(script);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010275 CHECK_EQ(1, value->Int32Value(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010276 }
10277
10278 {
10279 // Create new environment reusing the global object.
10280 LocalContext env(NULL, instance_template, global_object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010281 Local<Value> value = CompileRun("x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010282 CHECK_EQ(42, value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010283 value = CompileRun("f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010284 CHECK_EQ(12, value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010285 value = CompileRun(script);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010286 CHECK_EQ(1, value->Int32Value(env.local()).FromJust());
Ben Murdochb0fe1622011-05-05 13:52:32 +010010287 }
10288}
10289
10290
10291THREADED_TEST(CallKnownGlobalReceiver) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010292 v8::Isolate* isolate = CcTest::isolate();
10293 v8::HandleScope handle_scope(isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +010010294
10295 Local<Value> global_object;
10296
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010297 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +010010298 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10299
10300 // The script to check that we leave global object not
10301 // global object proxy on stack when we deoptimize from inside
10302 // arguments evaluation.
10303 // To provoke error we need to both force deoptimization
10304 // from arguments evaluation and to force CallIC to take
10305 // CallIC_Miss code path that can't cope with global proxy.
10306 const char* script =
10307 "function bar(x, y) { try { } finally { } }"
10308 "function baz(x) { try { } finally { } }"
10309 "function bom(x) { try { } finally { } }"
10310 "function foo(x) { bar([x], bom(2)); }"
10311 "for (var i = 0; i < 10000; i++) foo(1);"
10312 "foo";
10313
10314 Local<Value> foo;
10315 {
10316 LocalContext env(NULL, instance_template);
10317 // Hold on to the global object so it can be used again in another
10318 // environment initialization.
10319 global_object = env->Global();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010320 foo = CompileRun(script);
Ben Murdochb0fe1622011-05-05 13:52:32 +010010321 }
10322
10323 {
10324 // Create new environment reusing the global object.
10325 LocalContext env(NULL, instance_template, global_object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010326 CHECK(env->Global()->Set(env.local(), v8_str("foo"), foo).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010327 CompileRun("foo()");
Steve Blocka7e24c12009-10-30 11:49:00 +000010328 }
10329}
10330
10331
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010332static void ShadowFunctionCallback(
10333 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010334 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010335 args.GetReturnValue().Set(v8_num(42));
Steve Blocka7e24c12009-10-30 11:49:00 +000010336}
10337
10338
10339static int shadow_y;
10340static int shadow_y_setter_call_count;
10341static int shadow_y_getter_call_count;
10342
10343
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010344static void ShadowYSetter(Local<String>,
10345 Local<Value>,
10346 const v8::PropertyCallbackInfo<void>&) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010347 shadow_y_setter_call_count++;
10348 shadow_y = 42;
10349}
10350
10351
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010352static void ShadowYGetter(Local<String> name,
10353 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010354 ApiTestFuzzer::Fuzz();
10355 shadow_y_getter_call_count++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010356 info.GetReturnValue().Set(v8_num(shadow_y));
Steve Blocka7e24c12009-10-30 11:49:00 +000010357}
10358
10359
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010360static void ShadowIndexedGet(uint32_t index,
10361 const v8::PropertyCallbackInfo<v8::Value>&) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010362}
10363
10364
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010365static void ShadowNamedGet(Local<Name> key,
10366 const v8::PropertyCallbackInfo<v8::Value>&) {}
Steve Blocka7e24c12009-10-30 11:49:00 +000010367
10368
10369THREADED_TEST(ShadowObject) {
10370 shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010371 v8::Isolate* isolate = CcTest::isolate();
10372 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010373
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010374 Local<ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010375 LocalContext context(NULL, global_template);
10376
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010377 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010378 t->InstanceTemplate()->SetHandler(
10379 v8::NamedPropertyHandlerConfiguration(ShadowNamedGet));
10380 t->InstanceTemplate()->SetHandler(
10381 v8::IndexedPropertyHandlerConfiguration(ShadowIndexedGet));
Steve Blocka7e24c12009-10-30 11:49:00 +000010382 Local<ObjectTemplate> proto = t->PrototypeTemplate();
10383 Local<ObjectTemplate> instance = t->InstanceTemplate();
10384
Steve Blocka7e24c12009-10-30 11:49:00 +000010385 proto->Set(v8_str("f"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010386 v8::FunctionTemplate::New(isolate,
10387 ShadowFunctionCallback,
10388 Local<Value>()));
Steve Blocka7e24c12009-10-30 11:49:00 +000010389 proto->Set(v8_str("x"), v8_num(12));
10390
10391 instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
10392
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010393 Local<Value> o = t->GetFunction(context.local())
10394 .ToLocalChecked()
10395 ->NewInstance(context.local())
10396 .ToLocalChecked();
10397 CHECK(context->Global()
10398 ->Set(context.local(), v8_str("__proto__"), o)
10399 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010400
10401 Local<Value> value =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010402 CompileRun("this.propertyIsEnumerable(0)");
Steve Blocka7e24c12009-10-30 11:49:00 +000010403 CHECK(value->IsBoolean());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010404 CHECK(!value->BooleanValue(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010405
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010406 value = CompileRun("x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010407 CHECK_EQ(12, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010408
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010409 value = CompileRun("f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010410 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010411
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010412 CompileRun("y = 43");
Steve Blocka7e24c12009-10-30 11:49:00 +000010413 CHECK_EQ(1, shadow_y_setter_call_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010414 value = CompileRun("y");
Steve Blocka7e24c12009-10-30 11:49:00 +000010415 CHECK_EQ(1, shadow_y_getter_call_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010416 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010417}
10418
10419
10420THREADED_TEST(HiddenPrototype) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010421 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010422 v8::Isolate* isolate = context->GetIsolate();
10423 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010424
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010425 Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010426 t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010427 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010428 t1->SetHiddenPrototype(true);
10429 t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010430 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010431 t2->SetHiddenPrototype(true);
10432 t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010433 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010434 t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
10435
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010436 Local<v8::Object> o0 = t0->GetFunction(context.local())
10437 .ToLocalChecked()
10438 ->NewInstance(context.local())
10439 .ToLocalChecked();
10440 Local<v8::Object> o1 = t1->GetFunction(context.local())
10441 .ToLocalChecked()
10442 ->NewInstance(context.local())
10443 .ToLocalChecked();
10444 Local<v8::Object> o2 = t2->GetFunction(context.local())
10445 .ToLocalChecked()
10446 ->NewInstance(context.local())
10447 .ToLocalChecked();
10448 Local<v8::Object> o3 = t3->GetFunction(context.local())
10449 .ToLocalChecked()
10450 ->NewInstance(context.local())
10451 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000010452
10453 // Setting the prototype on an object skips hidden prototypes.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010454 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10455 .ToLocalChecked()
10456 ->Int32Value(context.local())
10457 .FromJust());
10458 CHECK(o0->Set(context.local(), v8_str("__proto__"), o1).FromJust());
10459 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10460 .ToLocalChecked()
10461 ->Int32Value(context.local())
10462 .FromJust());
10463 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10464 .ToLocalChecked()
10465 ->Int32Value(context.local())
10466 .FromJust());
10467 CHECK(o0->Set(context.local(), v8_str("__proto__"), o2).FromJust());
10468 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10469 .ToLocalChecked()
10470 ->Int32Value(context.local())
10471 .FromJust());
10472 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10473 .ToLocalChecked()
10474 ->Int32Value(context.local())
10475 .FromJust());
10476 CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
10477 .ToLocalChecked()
10478 ->Int32Value(context.local())
10479 .FromJust());
10480 CHECK(o0->Set(context.local(), v8_str("__proto__"), o3).FromJust());
10481 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10482 .ToLocalChecked()
10483 ->Int32Value(context.local())
10484 .FromJust());
10485 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10486 .ToLocalChecked()
10487 ->Int32Value(context.local())
10488 .FromJust());
10489 CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
10490 .ToLocalChecked()
10491 ->Int32Value(context.local())
10492 .FromJust());
10493 CHECK_EQ(3, o0->Get(context.local(), v8_str("u"))
10494 .ToLocalChecked()
10495 ->Int32Value(context.local())
10496 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010497
10498 // Getting the prototype of o0 should get the first visible one
10499 // which is o3. Therefore, z should not be defined on the prototype
10500 // object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010501 Local<Value> proto =
10502 o0->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000010503 CHECK(proto->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010504 CHECK(proto.As<v8::Object>()
10505 ->Get(context.local(), v8_str("z"))
10506 .ToLocalChecked()
10507 ->IsUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +000010508}
10509
10510
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010511THREADED_TEST(HiddenPrototypeSet) {
Andrei Popescu402d9372010-02-26 13:31:12 +000010512 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010513 v8::Isolate* isolate = context->GetIsolate();
10514 v8::HandleScope handle_scope(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000010515
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010516 Local<v8::FunctionTemplate> ot = v8::FunctionTemplate::New(isolate);
10517 Local<v8::FunctionTemplate> ht = v8::FunctionTemplate::New(isolate);
10518 ht->SetHiddenPrototype(true);
10519 Local<v8::FunctionTemplate> pt = v8::FunctionTemplate::New(isolate);
10520 ht->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
10521
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010522 Local<v8::Object> o = ot->GetFunction(context.local())
10523 .ToLocalChecked()
10524 ->NewInstance(context.local())
10525 .ToLocalChecked();
10526 Local<v8::Object> h = ht->GetFunction(context.local())
10527 .ToLocalChecked()
10528 ->NewInstance(context.local())
10529 .ToLocalChecked();
10530 Local<v8::Object> p = pt->GetFunction(context.local())
10531 .ToLocalChecked()
10532 ->NewInstance(context.local())
10533 .ToLocalChecked();
10534 CHECK(o->Set(context.local(), v8_str("__proto__"), h).FromJust());
10535 CHECK(h->Set(context.local(), v8_str("__proto__"), p).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010536
10537 // Setting a property that exists on the hidden prototype goes there.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010538 CHECK(o->Set(context.local(), v8_str("x"), v8_num(7)).FromJust());
10539 CHECK_EQ(7, o->Get(context.local(), v8_str("x"))
10540 .ToLocalChecked()
10541 ->Int32Value(context.local())
10542 .FromJust());
10543 CHECK_EQ(7, h->Get(context.local(), v8_str("x"))
10544 .ToLocalChecked()
10545 ->Int32Value(context.local())
10546 .FromJust());
10547 CHECK(p->Get(context.local(), v8_str("x")).ToLocalChecked()->IsUndefined());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010548
10549 // Setting a new property should not be forwarded to the hidden prototype.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010550 CHECK(o->Set(context.local(), v8_str("y"), v8_num(6)).FromJust());
10551 CHECK_EQ(6, o->Get(context.local(), v8_str("y"))
10552 .ToLocalChecked()
10553 ->Int32Value(context.local())
10554 .FromJust());
10555 CHECK(h->Get(context.local(), v8_str("y")).ToLocalChecked()->IsUndefined());
10556 CHECK(p->Get(context.local(), v8_str("y")).ToLocalChecked()->IsUndefined());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010557
10558 // Setting a property that only exists on a prototype of the hidden prototype
10559 // is treated normally again.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010560 CHECK(p->Set(context.local(), v8_str("z"), v8_num(8)).FromJust());
10561 CHECK_EQ(8, o->Get(context.local(), v8_str("z"))
10562 .ToLocalChecked()
10563 ->Int32Value(context.local())
10564 .FromJust());
10565 CHECK_EQ(8, h->Get(context.local(), v8_str("z"))
10566 .ToLocalChecked()
10567 ->Int32Value(context.local())
10568 .FromJust());
10569 CHECK_EQ(8, p->Get(context.local(), v8_str("z"))
10570 .ToLocalChecked()
10571 ->Int32Value(context.local())
10572 .FromJust());
10573 CHECK(o->Set(context.local(), v8_str("z"), v8_num(9)).FromJust());
10574 CHECK_EQ(9, o->Get(context.local(), v8_str("z"))
10575 .ToLocalChecked()
10576 ->Int32Value(context.local())
10577 .FromJust());
10578 CHECK_EQ(8, h->Get(context.local(), v8_str("z"))
10579 .ToLocalChecked()
10580 ->Int32Value(context.local())
10581 .FromJust());
10582 CHECK_EQ(8, p->Get(context.local(), v8_str("z"))
10583 .ToLocalChecked()
10584 ->Int32Value(context.local())
10585 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010586}
10587
10588
10589// Regression test for issue 2457.
10590THREADED_TEST(HiddenPrototypeIdentityHash) {
10591 LocalContext context;
10592 v8::HandleScope handle_scope(context->GetIsolate());
10593
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010594 Local<FunctionTemplate> t = FunctionTemplate::New(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010595 t->SetHiddenPrototype(true);
10596 t->InstanceTemplate()->Set(v8_str("foo"), v8_num(75));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010597 Local<Object> p = t->GetFunction(context.local())
10598 .ToLocalChecked()
10599 ->NewInstance(context.local())
10600 .ToLocalChecked();
10601 Local<Object> o = Object::New(context->GetIsolate());
10602 CHECK(o->SetPrototype(context.local(), p).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010603
10604 int hash = o->GetIdentityHash();
10605 USE(hash);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010606 CHECK(o->Set(context.local(), v8_str("foo"), v8_num(42)).FromJust());
10607 CHECK_EQ(hash, o->GetIdentityHash());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010608}
10609
10610
10611THREADED_TEST(SetPrototype) {
10612 LocalContext context;
10613 v8::Isolate* isolate = context->GetIsolate();
10614 v8::HandleScope handle_scope(isolate);
10615
10616 Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000010617 t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010618 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000010619 t1->SetHiddenPrototype(true);
10620 t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010621 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000010622 t2->SetHiddenPrototype(true);
10623 t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010624 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000010625 t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
10626
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010627 Local<v8::Object> o0 = t0->GetFunction(context.local())
10628 .ToLocalChecked()
10629 ->NewInstance(context.local())
10630 .ToLocalChecked();
10631 Local<v8::Object> o1 = t1->GetFunction(context.local())
10632 .ToLocalChecked()
10633 ->NewInstance(context.local())
10634 .ToLocalChecked();
10635 Local<v8::Object> o2 = t2->GetFunction(context.local())
10636 .ToLocalChecked()
10637 ->NewInstance(context.local())
10638 .ToLocalChecked();
10639 Local<v8::Object> o3 = t3->GetFunction(context.local())
10640 .ToLocalChecked()
10641 ->NewInstance(context.local())
10642 .ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000010643
10644 // Setting the prototype on an object does not skip hidden prototypes.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010645 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10646 .ToLocalChecked()
10647 ->Int32Value(context.local())
10648 .FromJust());
10649 CHECK(o0->SetPrototype(context.local(), o1).FromJust());
10650 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10651 .ToLocalChecked()
10652 ->Int32Value(context.local())
10653 .FromJust());
10654 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10655 .ToLocalChecked()
10656 ->Int32Value(context.local())
10657 .FromJust());
10658 CHECK(o1->SetPrototype(context.local(), o2).FromJust());
10659 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10660 .ToLocalChecked()
10661 ->Int32Value(context.local())
10662 .FromJust());
10663 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10664 .ToLocalChecked()
10665 ->Int32Value(context.local())
10666 .FromJust());
10667 CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
10668 .ToLocalChecked()
10669 ->Int32Value(context.local())
10670 .FromJust());
10671 CHECK(o2->SetPrototype(context.local(), o3).FromJust());
10672 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10673 .ToLocalChecked()
10674 ->Int32Value(context.local())
10675 .FromJust());
10676 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10677 .ToLocalChecked()
10678 ->Int32Value(context.local())
10679 .FromJust());
10680 CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
10681 .ToLocalChecked()
10682 ->Int32Value(context.local())
10683 .FromJust());
10684 CHECK_EQ(3, o0->Get(context.local(), v8_str("u"))
10685 .ToLocalChecked()
10686 ->Int32Value(context.local())
10687 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000010688
10689 // Getting the prototype of o0 should get the first visible one
10690 // which is o3. Therefore, z should not be defined on the prototype
10691 // object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010692 Local<Value> proto =
10693 o0->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000010694 CHECK(proto->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010695 CHECK(proto.As<v8::Object>()->Equals(context.local(), o3).FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000010696
10697 // However, Object::GetPrototype ignores hidden prototype.
10698 Local<Value> proto0 = o0->GetPrototype();
10699 CHECK(proto0->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010700 CHECK(proto0.As<v8::Object>()->Equals(context.local(), o1).FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000010701
10702 Local<Value> proto1 = o1->GetPrototype();
10703 CHECK(proto1->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010704 CHECK(proto1.As<v8::Object>()->Equals(context.local(), o2).FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000010705
10706 Local<Value> proto2 = o2->GetPrototype();
10707 CHECK(proto2->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010708 CHECK(proto2.As<v8::Object>()->Equals(context.local(), o3).FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000010709}
10710
10711
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010712// Getting property names of an object with a prototype chain that
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010713// triggers dictionary elements in GetOwnPropertyNames() shouldn't
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010714// crash the runtime.
10715THREADED_TEST(Regress91517) {
10716 i::FLAG_allow_natives_syntax = true;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010717 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010718 v8::Isolate* isolate = context->GetIsolate();
10719 v8::HandleScope handle_scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010720
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010721 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010722 t1->SetHiddenPrototype(true);
10723 t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010724 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010725 t2->SetHiddenPrototype(true);
10726 t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010727 t2->InstanceTemplate()->Set(v8_str("objects"), v8::Object::New(isolate));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010728 t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010729 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010730 t3->SetHiddenPrototype(true);
10731 t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010732 Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010733 t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
10734
10735 // Force dictionary-based properties.
10736 i::ScopedVector<char> name_buf(1024);
10737 for (int i = 1; i <= 1000; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010738 i::SNPrintF(name_buf, "sdf%d", i);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010739 t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
10740 }
10741
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010742 Local<v8::Object> o1 = t1->GetFunction(context.local())
10743 .ToLocalChecked()
10744 ->NewInstance(context.local())
10745 .ToLocalChecked();
10746 Local<v8::Object> o2 = t2->GetFunction(context.local())
10747 .ToLocalChecked()
10748 ->NewInstance(context.local())
10749 .ToLocalChecked();
10750 Local<v8::Object> o3 = t3->GetFunction(context.local())
10751 .ToLocalChecked()
10752 ->NewInstance(context.local())
10753 .ToLocalChecked();
10754 Local<v8::Object> o4 = t4->GetFunction(context.local())
10755 .ToLocalChecked()
10756 ->NewInstance(context.local())
10757 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010758
10759 // Create prototype chain of hidden prototypes.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010760 CHECK(o4->SetPrototype(context.local(), o3).FromJust());
10761 CHECK(o3->SetPrototype(context.local(), o2).FromJust());
10762 CHECK(o2->SetPrototype(context.local(), o1).FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010763
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010764 // Call the runtime version of GetOwnPropertyNames() on the natively
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010765 // created object through JavaScript.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010766 CHECK(context->Global()->Set(context.local(), v8_str("obj"), o4).FromJust());
10767 // PROPERTY_FILTER_NONE = 0
10768 CompileRun("var names = %GetOwnPropertyKeys(obj, 0);");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010769
10770 ExpectInt32("names.length", 1006);
10771 ExpectTrue("names.indexOf(\"baz\") >= 0");
10772 ExpectTrue("names.indexOf(\"boo\") >= 0");
10773 ExpectTrue("names.indexOf(\"foo\") >= 0");
10774 ExpectTrue("names.indexOf(\"fuz1\") >= 0");
10775 ExpectTrue("names.indexOf(\"fuz2\") >= 0");
10776 ExpectFalse("names[1005] == undefined");
10777}
10778
10779
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010780// Getting property names of an object with a hidden and inherited
10781// prototype should not duplicate the accessor properties inherited.
10782THREADED_TEST(Regress269562) {
10783 i::FLAG_allow_natives_syntax = true;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000010784 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010785 v8::HandleScope handle_scope(context->GetIsolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000010786
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010787 Local<v8::FunctionTemplate> t1 =
10788 v8::FunctionTemplate::New(context->GetIsolate());
10789 t1->SetHiddenPrototype(true);
10790
10791 Local<v8::ObjectTemplate> i1 = t1->InstanceTemplate();
10792 i1->SetAccessor(v8_str("foo"),
10793 SimpleAccessorGetter, SimpleAccessorSetter);
10794 i1->SetAccessor(v8_str("bar"),
10795 SimpleAccessorGetter, SimpleAccessorSetter);
10796 i1->SetAccessor(v8_str("baz"),
10797 SimpleAccessorGetter, SimpleAccessorSetter);
10798 i1->Set(v8_str("n1"), v8_num(1));
10799 i1->Set(v8_str("n2"), v8_num(2));
10800
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010801 Local<v8::Object> o1 = t1->GetFunction(context.local())
10802 .ToLocalChecked()
10803 ->NewInstance(context.local())
10804 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010805 Local<v8::FunctionTemplate> t2 =
10806 v8::FunctionTemplate::New(context->GetIsolate());
10807 t2->SetHiddenPrototype(true);
10808
10809 // Inherit from t1 and mark prototype as hidden.
10810 t2->Inherit(t1);
10811 t2->InstanceTemplate()->Set(v8_str("mine"), v8_num(4));
10812
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010813 Local<v8::Object> o2 = t2->GetFunction(context.local())
10814 .ToLocalChecked()
10815 ->NewInstance(context.local())
10816 .ToLocalChecked();
10817 CHECK(o2->SetPrototype(context.local(), o1).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010818
10819 v8::Local<v8::Symbol> sym =
10820 v8::Symbol::New(context->GetIsolate(), v8_str("s1"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010821 CHECK(o1->Set(context.local(), sym, v8_num(3)).FromJust());
10822 o1->SetPrivate(context.local(),
10823 v8::Private::New(context->GetIsolate(), v8_str("h1")),
10824 v8::Integer::New(context->GetIsolate(), 2013))
10825 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010826
10827 // Call the runtime version of GetOwnPropertyNames() on
10828 // the natively created object through JavaScript.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010829 CHECK(context->Global()->Set(context.local(), v8_str("obj"), o2).FromJust());
10830 CHECK(context->Global()->Set(context.local(), v8_str("sym"), sym).FromJust());
10831 // PROPERTY_FILTER_NONE = 0
10832 CompileRun("var names = %GetOwnPropertyKeys(obj, 0);");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010833
10834 ExpectInt32("names.length", 7);
10835 ExpectTrue("names.indexOf(\"foo\") >= 0");
10836 ExpectTrue("names.indexOf(\"bar\") >= 0");
10837 ExpectTrue("names.indexOf(\"baz\") >= 0");
10838 ExpectTrue("names.indexOf(\"n1\") >= 0");
10839 ExpectTrue("names.indexOf(\"n2\") >= 0");
10840 ExpectTrue("names.indexOf(sym) >= 0");
10841 ExpectTrue("names.indexOf(\"mine\") >= 0");
10842}
10843
10844
10845THREADED_TEST(FunctionReadOnlyPrototype) {
10846 LocalContext context;
10847 v8::Isolate* isolate = context->GetIsolate();
10848 v8::HandleScope handle_scope(isolate);
10849
10850 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
10851 t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
Ben Murdoch69a99ed2011-11-30 16:03:39 +000010852 t1->ReadOnlyPrototype();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010853 CHECK(context->Global()
10854 ->Set(context.local(), v8_str("func1"),
10855 t1->GetFunction(context.local()).ToLocalChecked())
10856 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000010857 // Configured value of ReadOnly flag.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010858 CHECK(
10859 CompileRun(
10860 "(function() {"
10861 " descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
10862 " return (descriptor['writable'] == false);"
10863 "})()")
10864 ->BooleanValue(context.local())
10865 .FromJust());
10866 CHECK_EQ(
10867 42,
10868 CompileRun("func1.prototype.x")->Int32Value(context.local()).FromJust());
10869 CHECK_EQ(42, CompileRun("func1.prototype = {}; func1.prototype.x")
10870 ->Int32Value(context.local())
10871 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000010872
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010873 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
10874 t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010875 CHECK(context->Global()
10876 ->Set(context.local(), v8_str("func2"),
10877 t2->GetFunction(context.local()).ToLocalChecked())
10878 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000010879 // Default value of ReadOnly flag.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010880 CHECK(
10881 CompileRun(
10882 "(function() {"
10883 " descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
10884 " return (descriptor['writable'] == true);"
10885 "})()")
10886 ->BooleanValue(context.local())
10887 .FromJust());
10888 CHECK_EQ(
10889 42,
10890 CompileRun("func2.prototype.x")->Int32Value(context.local()).FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000010891}
10892
10893
Andrei Popescu402d9372010-02-26 13:31:12 +000010894THREADED_TEST(SetPrototypeThrows) {
Andrei Popescu402d9372010-02-26 13:31:12 +000010895 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010896 v8::Isolate* isolate = context->GetIsolate();
10897 v8::HandleScope handle_scope(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000010898
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010899 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000010900
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010901 Local<v8::Object> o0 = t->GetFunction(context.local())
10902 .ToLocalChecked()
10903 ->NewInstance(context.local())
10904 .ToLocalChecked();
10905 Local<v8::Object> o1 = t->GetFunction(context.local())
10906 .ToLocalChecked()
10907 ->NewInstance(context.local())
10908 .ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000010909
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010910 CHECK(o0->SetPrototype(context.local(), o1).FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000010911 // If setting the prototype leads to the cycle, SetPrototype should
10912 // return false and keep VM in sane state.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010913 v8::TryCatch try_catch(isolate);
10914 CHECK(o1->SetPrototype(context.local(), o0).IsNothing());
Andrei Popescu402d9372010-02-26 13:31:12 +000010915 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010916 CHECK(!CcTest::i_isolate()->has_pending_exception());
Andrei Popescu402d9372010-02-26 13:31:12 +000010917
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010918 CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")
10919 ->Int32Value(context.local())
10920 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000010921}
10922
10923
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010924THREADED_TEST(FunctionRemovePrototype) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010925 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010926 v8::Isolate* isolate = context->GetIsolate();
10927 v8::HandleScope handle_scope(isolate);
10928
10929 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
10930 t1->RemovePrototype();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010931 Local<v8::Function> fun = t1->GetFunction(context.local()).ToLocalChecked();
10932 CHECK(context->Global()->Set(context.local(), v8_str("fun"), fun).FromJust());
10933 CHECK(!CompileRun("'prototype' in fun")
10934 ->BooleanValue(context.local())
10935 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010936
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010937 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010938 CompileRun("new fun()");
10939 CHECK(try_catch.HasCaught());
10940
10941 try_catch.Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010942 CHECK(fun->NewInstance(context.local()).IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010943 CHECK(try_catch.HasCaught());
10944}
10945
10946
10947THREADED_TEST(GetterSetterExceptions) {
10948 LocalContext context;
10949 v8::Isolate* isolate = context->GetIsolate();
10950 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010951 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010952 "function Foo() { };"
10953 "function Throw() { throw 5; };"
10954 "var x = { };"
10955 "x.__defineSetter__('set', Throw);"
10956 "x.__defineGetter__('get', Throw);");
10957 Local<v8::Object> x = Local<v8::Object>::Cast(
10958 context->Global()->Get(context.local(), v8_str("x")).ToLocalChecked());
10959 v8::TryCatch try_catch(isolate);
10960 CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
10961 .IsNothing());
10962 CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
10963 CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
10964 .IsNothing());
10965 CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
10966 CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
10967 .IsNothing());
10968 CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
10969 CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
10970 .IsNothing());
10971 CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000010972}
10973
10974
10975THREADED_TEST(Constructor) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010976 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010977 v8::Isolate* isolate = context->GetIsolate();
10978 v8::HandleScope handle_scope(isolate);
10979 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010980 templ->SetClassName(v8_str("Fun"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010981 Local<Function> cons = templ->GetFunction(context.local()).ToLocalChecked();
10982 CHECK(
10983 context->Global()->Set(context.local(), v8_str("Fun"), cons).FromJust());
10984 Local<v8::Object> inst = cons->NewInstance(context.local()).ToLocalChecked();
10985 i::Handle<i::JSReceiver> obj(v8::Utils::OpenHandle(*inst));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010986 CHECK(obj->IsJSObject());
Steve Blocka7e24c12009-10-30 11:49:00 +000010987 Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010988 CHECK(value->BooleanValue(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010989}
10990
Ben Murdoch257744e2011-11-30 15:57:28 +000010991
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010992static void ConstructorCallback(
10993 const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch257744e2011-11-30 15:57:28 +000010994 ApiTestFuzzer::Fuzz();
10995 Local<Object> This;
10996
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010997 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
Ben Murdoch257744e2011-11-30 15:57:28 +000010998 if (args.IsConstructCall()) {
10999 Local<Object> Holder = args.Holder();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011000 This = Object::New(args.GetIsolate());
Ben Murdoch257744e2011-11-30 15:57:28 +000011001 Local<Value> proto = Holder->GetPrototype();
11002 if (proto->IsObject()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011003 This->SetPrototype(context, proto).FromJust();
Ben Murdoch257744e2011-11-30 15:57:28 +000011004 }
11005 } else {
11006 This = args.This();
11007 }
11008
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011009 This->Set(context, v8_str("a"), args[0]).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011010 args.GetReturnValue().Set(This);
Ben Murdoch257744e2011-11-30 15:57:28 +000011011}
11012
11013
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011014static void FakeConstructorCallback(
11015 const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch257744e2011-11-30 15:57:28 +000011016 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011017 args.GetReturnValue().Set(args[0]);
Ben Murdoch257744e2011-11-30 15:57:28 +000011018}
11019
11020
11021THREADED_TEST(ConstructorForObject) {
Ben Murdoch257744e2011-11-30 15:57:28 +000011022 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011023 v8::Isolate* isolate = context->GetIsolate();
11024 v8::HandleScope handle_scope(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011025
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011026 {
11027 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011028 instance_template->SetCallAsFunctionHandler(ConstructorCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011029 Local<Object> instance =
11030 instance_template->NewInstance(context.local()).ToLocalChecked();
11031 CHECK(context->Global()
11032 ->Set(context.local(), v8_str("obj"), instance)
11033 .FromJust());
11034 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011035 Local<Value> value;
11036 CHECK(!try_catch.HasCaught());
11037
11038 // Call the Object's constructor with a 32-bit signed integer.
11039 value = CompileRun("(function() { var o = new obj(28); return o.a; })()");
11040 CHECK(!try_catch.HasCaught());
11041 CHECK(value->IsInt32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011042 CHECK_EQ(28, value->Int32Value(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011043
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011044 Local<Value> args1[] = {v8_num(28)};
11045 Local<Value> value_obj1 =
11046 instance->CallAsConstructor(context.local(), 1, args1).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011047 CHECK(value_obj1->IsObject());
11048 Local<Object> object1 = Local<Object>::Cast(value_obj1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011049 value = object1->Get(context.local(), v8_str("a")).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011050 CHECK(value->IsInt32());
11051 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011052 CHECK_EQ(28, value->Int32Value(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011053
11054 // Call the Object's constructor with a String.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011055 value =
11056 CompileRun("(function() { var o = new obj('tipli'); return o.a; })()");
Ben Murdoch257744e2011-11-30 15:57:28 +000011057 CHECK(!try_catch.HasCaught());
11058 CHECK(value->IsString());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011059 String::Utf8Value string_value1(
11060 value->ToString(context.local()).ToLocalChecked());
11061 CHECK_EQ(0, strcmp("tipli", *string_value1));
Ben Murdoch257744e2011-11-30 15:57:28 +000011062
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011063 Local<Value> args2[] = {v8_str("tipli")};
11064 Local<Value> value_obj2 =
11065 instance->CallAsConstructor(context.local(), 1, args2).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011066 CHECK(value_obj2->IsObject());
11067 Local<Object> object2 = Local<Object>::Cast(value_obj2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011068 value = object2->Get(context.local(), v8_str("a")).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011069 CHECK(!try_catch.HasCaught());
11070 CHECK(value->IsString());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011071 String::Utf8Value string_value2(
11072 value->ToString(context.local()).ToLocalChecked());
11073 CHECK_EQ(0, strcmp("tipli", *string_value2));
Ben Murdoch257744e2011-11-30 15:57:28 +000011074
11075 // Call the Object's constructor with a Boolean.
11076 value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
11077 CHECK(!try_catch.HasCaught());
11078 CHECK(value->IsBoolean());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011079 CHECK_EQ(true, value->BooleanValue(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011080
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011081 Local<Value> args3[] = {v8::True(isolate)};
11082 Local<Value> value_obj3 =
11083 instance->CallAsConstructor(context.local(), 1, args3).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011084 CHECK(value_obj3->IsObject());
11085 Local<Object> object3 = Local<Object>::Cast(value_obj3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011086 value = object3->Get(context.local(), v8_str("a")).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011087 CHECK(!try_catch.HasCaught());
11088 CHECK(value->IsBoolean());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011089 CHECK_EQ(true, value->BooleanValue(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011090
11091 // Call the Object's constructor with undefined.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011092 Local<Value> args4[] = {v8::Undefined(isolate)};
11093 Local<Value> value_obj4 =
11094 instance->CallAsConstructor(context.local(), 1, args4).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011095 CHECK(value_obj4->IsObject());
11096 Local<Object> object4 = Local<Object>::Cast(value_obj4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011097 value = object4->Get(context.local(), v8_str("a")).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011098 CHECK(!try_catch.HasCaught());
11099 CHECK(value->IsUndefined());
11100
11101 // Call the Object's constructor with null.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011102 Local<Value> args5[] = {v8::Null(isolate)};
11103 Local<Value> value_obj5 =
11104 instance->CallAsConstructor(context.local(), 1, args5).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011105 CHECK(value_obj5->IsObject());
11106 Local<Object> object5 = Local<Object>::Cast(value_obj5);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011107 value = object5->Get(context.local(), v8_str("a")).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011108 CHECK(!try_catch.HasCaught());
11109 CHECK(value->IsNull());
11110 }
11111
11112 // Check exception handling when there is no constructor set for the Object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011113 {
11114 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
11115 Local<Object> instance =
11116 instance_template->NewInstance(context.local()).ToLocalChecked();
11117 CHECK(context->Global()
11118 ->Set(context.local(), v8_str("obj2"), instance)
11119 .FromJust());
11120 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011121 Local<Value> value;
11122 CHECK(!try_catch.HasCaught());
11123
11124 value = CompileRun("new obj2(28)");
11125 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011126 String::Utf8Value exception_value1(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011127 CHECK_EQ(0,
11128 strcmp("TypeError: obj2 is not a constructor", *exception_value1));
Ben Murdoch257744e2011-11-30 15:57:28 +000011129 try_catch.Reset();
11130
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011131 Local<Value> args[] = {v8_num(29)};
11132 CHECK(instance->CallAsConstructor(context.local(), 1, args).IsEmpty());
Ben Murdoch257744e2011-11-30 15:57:28 +000011133 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011134 String::Utf8Value exception_value2(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011135 CHECK_EQ(
11136 0, strcmp("TypeError: object is not a constructor", *exception_value2));
Ben Murdoch257744e2011-11-30 15:57:28 +000011137 try_catch.Reset();
11138 }
11139
11140 // Check the case when constructor throws exception.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011141 {
11142 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011143 instance_template->SetCallAsFunctionHandler(ThrowValue);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011144 Local<Object> instance =
11145 instance_template->NewInstance(context.local()).ToLocalChecked();
11146 CHECK(context->Global()
11147 ->Set(context.local(), v8_str("obj3"), instance)
11148 .FromJust());
11149 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011150 Local<Value> value;
11151 CHECK(!try_catch.HasCaught());
11152
11153 value = CompileRun("new obj3(22)");
11154 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011155 String::Utf8Value exception_value1(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011156 CHECK_EQ(0, strcmp("22", *exception_value1));
Ben Murdoch257744e2011-11-30 15:57:28 +000011157 try_catch.Reset();
11158
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011159 Local<Value> args[] = {v8_num(23)};
11160 CHECK(instance->CallAsConstructor(context.local(), 1, args).IsEmpty());
Ben Murdoch257744e2011-11-30 15:57:28 +000011161 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011162 String::Utf8Value exception_value2(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011163 CHECK_EQ(0, strcmp("23", *exception_value2));
Ben Murdoch257744e2011-11-30 15:57:28 +000011164 try_catch.Reset();
11165 }
11166
11167 // Check whether constructor returns with an object or non-object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011168 {
11169 Local<FunctionTemplate> function_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011170 FunctionTemplate::New(isolate, FakeConstructorCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011171 Local<Function> function =
11172 function_template->GetFunction(context.local()).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011173 Local<Object> instance1 = function;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011174 CHECK(context->Global()
11175 ->Set(context.local(), v8_str("obj4"), instance1)
11176 .FromJust());
11177 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011178 Local<Value> value;
11179 CHECK(!try_catch.HasCaught());
11180
11181 CHECK(instance1->IsObject());
11182 CHECK(instance1->IsFunction());
11183
11184 value = CompileRun("new obj4(28)");
11185 CHECK(!try_catch.HasCaught());
11186 CHECK(value->IsObject());
11187
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011188 Local<Value> args1[] = {v8_num(28)};
11189 value = instance1->CallAsConstructor(context.local(), 1, args1)
11190 .ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011191 CHECK(!try_catch.HasCaught());
11192 CHECK(value->IsObject());
11193
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011194 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011195 instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011196 Local<Object> instance2 =
11197 instance_template->NewInstance(context.local()).ToLocalChecked();
11198 CHECK(context->Global()
11199 ->Set(context.local(), v8_str("obj5"), instance2)
11200 .FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011201 CHECK(!try_catch.HasCaught());
11202
11203 CHECK(instance2->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011204 CHECK(instance2->IsFunction());
Ben Murdoch257744e2011-11-30 15:57:28 +000011205
11206 value = CompileRun("new obj5(28)");
11207 CHECK(!try_catch.HasCaught());
11208 CHECK(!value->IsObject());
11209
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011210 Local<Value> args2[] = {v8_num(28)};
11211 value = instance2->CallAsConstructor(context.local(), 1, args2)
11212 .ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011213 CHECK(!try_catch.HasCaught());
11214 CHECK(!value->IsObject());
11215 }
11216}
11217
11218
Steve Blocka7e24c12009-10-30 11:49:00 +000011219THREADED_TEST(FunctionDescriptorException) {
Steve Blocka7e24c12009-10-30 11:49:00 +000011220 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011221 v8::Isolate* isolate = context->GetIsolate();
11222 v8::HandleScope handle_scope(isolate);
11223 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011224 templ->SetClassName(v8_str("Fun"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011225 Local<Function> cons = templ->GetFunction(context.local()).ToLocalChecked();
11226 CHECK(
11227 context->Global()->Set(context.local(), v8_str("Fun"), cons).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011228 Local<Value> value = CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011229 "function test() {"
11230 " try {"
11231 " (new Fun()).blah()"
11232 " } catch (e) {"
11233 " var str = String(e);"
11234 // " if (str.indexOf('TypeError') == -1) return 1;"
11235 // " if (str.indexOf('[object Fun]') != -1) return 2;"
11236 // " if (str.indexOf('#<Fun>') == -1) return 3;"
11237 " return 0;"
11238 " }"
11239 " return 4;"
11240 "}"
11241 "test();");
11242 CHECK_EQ(0, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011243}
11244
11245
11246THREADED_TEST(EvalAliasedDynamic) {
Steve Blocka7e24c12009-10-30 11:49:00 +000011247 LocalContext current;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011248 v8::HandleScope scope(current->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000011249
11250 // Tests where aliased eval can only be resolved dynamically.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011251 Local<Script> script = v8_compile(
11252 "function f(x) { "
11253 " var foo = 2;"
11254 " with (x) { return eval('foo'); }"
11255 "}"
11256 "foo = 0;"
11257 "result1 = f(new Object());"
11258 "result2 = f(this);"
11259 "var x = new Object();"
11260 "x.eval = function(x) { return 1; };"
11261 "result3 = f(x);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011262 script->Run(current.local()).ToLocalChecked();
11263 CHECK_EQ(2, current->Global()
11264 ->Get(current.local(), v8_str("result1"))
11265 .ToLocalChecked()
11266 ->Int32Value(current.local())
11267 .FromJust());
11268 CHECK_EQ(0, current->Global()
11269 ->Get(current.local(), v8_str("result2"))
11270 .ToLocalChecked()
11271 ->Int32Value(current.local())
11272 .FromJust());
11273 CHECK_EQ(1, current->Global()
11274 ->Get(current.local(), v8_str("result3"))
11275 .ToLocalChecked()
11276 ->Int32Value(current.local())
11277 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011278
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011279 v8::TryCatch try_catch(current->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011280 script = v8_compile(
11281 "function f(x) { "
11282 " var bar = 2;"
11283 " with (x) { return eval('bar'); }"
11284 "}"
11285 "result4 = f(this)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011286 script->Run(current.local()).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011287 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011288 CHECK_EQ(2, current->Global()
11289 ->Get(current.local(), v8_str("result4"))
11290 .ToLocalChecked()
11291 ->Int32Value(current.local())
11292 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011293
Steve Blocka7e24c12009-10-30 11:49:00 +000011294 try_catch.Reset();
11295}
11296
11297
11298THREADED_TEST(CrossEval) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011299 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000011300 LocalContext other;
11301 LocalContext current;
11302
11303 Local<String> token = v8_str("<security token>");
11304 other->SetSecurityToken(token);
11305 current->SetSecurityToken(token);
11306
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011307 // Set up reference from current to other.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011308 CHECK(current->Global()
11309 ->Set(current.local(), v8_str("other"), other->Global())
11310 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011311
11312 // Check that new variables are introduced in other context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011313 Local<Script> script = v8_compile("other.eval('var foo = 1234')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011314 script->Run(current.local()).ToLocalChecked();
11315 Local<Value> foo =
11316 other->Global()->Get(current.local(), v8_str("foo")).ToLocalChecked();
11317 CHECK_EQ(1234, foo->Int32Value(other.local()).FromJust());
11318 CHECK(!current->Global()->Has(current.local(), v8_str("foo")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011319
11320 // Check that writing to non-existing properties introduces them in
11321 // the other context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011322 script = v8_compile("other.eval('na = 1234')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011323 script->Run(current.local()).ToLocalChecked();
11324 CHECK_EQ(1234, other->Global()
11325 ->Get(current.local(), v8_str("na"))
11326 .ToLocalChecked()
11327 ->Int32Value(other.local())
11328 .FromJust());
11329 CHECK(!current->Global()->Has(current.local(), v8_str("na")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011330
11331 // Check that global variables in current context are not visible in other
11332 // context.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011333 v8::TryCatch try_catch(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011334 script = v8_compile("var bar = 42; other.eval('bar');");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011335 CHECK(script->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000011336 CHECK(try_catch.HasCaught());
11337 try_catch.Reset();
11338
11339 // Check that local variables in current context are not visible in other
11340 // context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011341 script = v8_compile(
11342 "(function() { "
11343 " var baz = 87;"
11344 " return other.eval('baz');"
11345 "})();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011346 CHECK(script->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000011347 CHECK(try_catch.HasCaught());
11348 try_catch.Reset();
11349
11350 // Check that global variables in the other environment are visible
11351 // when evaluting code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011352 CHECK(other->Global()
11353 ->Set(other.local(), v8_str("bis"), v8_num(1234))
11354 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011355 script = v8_compile("other.eval('bis')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011356 CHECK_EQ(1234, script->Run(current.local())
11357 .ToLocalChecked()
11358 ->Int32Value(current.local())
11359 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011360 CHECK(!try_catch.HasCaught());
11361
11362 // Check that the 'this' pointer points to the global object evaluating
11363 // code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011364 CHECK(other->Global()
11365 ->Set(current.local(), v8_str("t"), other->Global())
11366 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011367 script = v8_compile("other.eval('this == t')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011368 Local<Value> result = script->Run(current.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000011369 CHECK(result->IsTrue());
11370 CHECK(!try_catch.HasCaught());
11371
11372 // Check that variables introduced in with-statement are not visible in
11373 // other context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011374 script = v8_compile("with({x:2}){other.eval('x')}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011375 CHECK(script->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000011376 CHECK(try_catch.HasCaught());
11377 try_catch.Reset();
11378
11379 // Check that you cannot use 'eval.call' with another object than the
11380 // current global object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011381 script = v8_compile("other.y = 1; eval.call(other, 'y')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011382 CHECK(script->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000011383 CHECK(try_catch.HasCaught());
11384}
11385
11386
11387// Test that calling eval in a context which has been detached from
Emily Bernierd0a1eb72015-03-24 16:35:39 -040011388// its global proxy works.
Steve Blocka7e24c12009-10-30 11:49:00 +000011389THREADED_TEST(EvalInDetachedGlobal) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011390 v8::Isolate* isolate = CcTest::isolate();
11391 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011392
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011393 v8::Local<Context> context0 = Context::New(isolate);
11394 v8::Local<Context> context1 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011395
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011396 // Set up function in context0 that uses eval from context0.
Steve Blocka7e24c12009-10-30 11:49:00 +000011397 context0->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011398 v8::Local<v8::Value> fun = CompileRun(
11399 "var x = 42;"
11400 "(function() {"
11401 " var e = eval;"
11402 " return function(s) { return e(s); }"
11403 "})()");
Steve Blocka7e24c12009-10-30 11:49:00 +000011404 context0->Exit();
11405
11406 // Put the function into context1 and call it before and after
11407 // detaching the global. Before detaching, the call succeeds and
11408 // after detaching and exception is thrown.
11409 context1->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011410 CHECK(context1->Global()->Set(context1, v8_str("fun"), fun).FromJust());
11411 v8::Local<v8::Value> x_value = CompileRun("fun('x')");
11412 CHECK_EQ(42, x_value->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011413 context0->DetachGlobal();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011414 v8::TryCatch catcher(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011415 x_value = CompileRun("fun('x')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011416 CHECK_EQ(42, x_value->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011417 context1->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +000011418}
11419
11420
11421THREADED_TEST(CrossLazyLoad) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011422 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000011423 LocalContext other;
11424 LocalContext current;
11425
11426 Local<String> token = v8_str("<security token>");
11427 other->SetSecurityToken(token);
11428 current->SetSecurityToken(token);
11429
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011430 // Set up reference from current to other.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011431 CHECK(current->Global()
11432 ->Set(current.local(), v8_str("other"), other->Global())
11433 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011434
11435 // Trigger lazy loading in other context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011436 Local<Script> script = v8_compile("other.eval('new Date(42)')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011437 Local<Value> value = script->Run(current.local()).ToLocalChecked();
11438 CHECK_EQ(42.0, value->NumberValue(current.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011439}
11440
11441
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011442static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
Andrei Popescu402d9372010-02-26 13:31:12 +000011443 ApiTestFuzzer::Fuzz();
Steve Blocka7e24c12009-10-30 11:49:00 +000011444 if (args.IsConstructCall()) {
11445 if (args[0]->IsInt32()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011446 args.GetReturnValue().Set(
11447 v8_num(-args[0]
11448 ->Int32Value(args.GetIsolate()->GetCurrentContext())
11449 .FromJust()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011450 return;
Steve Blocka7e24c12009-10-30 11:49:00 +000011451 }
11452 }
11453
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011454 args.GetReturnValue().Set(args[0]);
11455}
11456
11457
11458static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
11459 args.GetReturnValue().Set(args.This());
Steve Blocka7e24c12009-10-30 11:49:00 +000011460}
11461
11462
11463// Test that a call handler can be set for objects which will allow
11464// non-function objects created through the API to be called as
11465// functions.
11466THREADED_TEST(CallAsFunction) {
Steve Blocka7e24c12009-10-30 11:49:00 +000011467 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011468 v8::Isolate* isolate = context->GetIsolate();
11469 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011470
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011471 {
11472 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011473 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
11474 instance_template->SetCallAsFunctionHandler(call_as_function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011475 Local<v8::Object> instance = t->GetFunction(context.local())
11476 .ToLocalChecked()
11477 ->NewInstance(context.local())
11478 .ToLocalChecked();
11479 CHECK(context->Global()
11480 ->Set(context.local(), v8_str("obj"), instance)
11481 .FromJust());
11482 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011483 Local<Value> value;
11484 CHECK(!try_catch.HasCaught());
Steve Blocka7e24c12009-10-30 11:49:00 +000011485
Ben Murdoch257744e2011-11-30 15:57:28 +000011486 value = CompileRun("obj(42)");
11487 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011488 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011489
Ben Murdoch257744e2011-11-30 15:57:28 +000011490 value = CompileRun("(function(o){return o(49)})(obj)");
11491 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011492 CHECK_EQ(49, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011493
Ben Murdoch257744e2011-11-30 15:57:28 +000011494 // test special case of call as function
11495 value = CompileRun("[obj]['0'](45)");
11496 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011497 CHECK_EQ(45, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011498
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011499 value = CompileRun(
11500 "obj.call = Function.prototype.call;"
11501 "obj.call(null, 87)");
Ben Murdoch257744e2011-11-30 15:57:28 +000011502 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011503 CHECK_EQ(87, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011504
Ben Murdoch257744e2011-11-30 15:57:28 +000011505 // Regression tests for bug #1116356: Calling call through call/apply
11506 // must work for non-function receivers.
11507 const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
11508 value = CompileRun(apply_99);
11509 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011510 CHECK_EQ(99, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011511
Ben Murdoch257744e2011-11-30 15:57:28 +000011512 const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
11513 value = CompileRun(call_17);
11514 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011515 CHECK_EQ(17, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011516
Ben Murdoch257744e2011-11-30 15:57:28 +000011517 // Check that the call-as-function handler can be called through
11518 // new.
11519 value = CompileRun("new obj(43)");
11520 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011521 CHECK_EQ(-43, value->Int32Value(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011522
11523 // Check that the call-as-function handler can be called through
11524 // the API.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011525 v8::Local<Value> args[] = {v8_num(28)};
11526 value = instance->CallAsFunction(context.local(), instance, 1, args)
11527 .ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011528 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011529 CHECK_EQ(28, value->Int32Value(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011530 }
11531
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011532 {
11533 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011534 Local<ObjectTemplate> instance_template(t->InstanceTemplate());
11535 USE(instance_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011536 Local<v8::Object> instance = t->GetFunction(context.local())
11537 .ToLocalChecked()
11538 ->NewInstance(context.local())
11539 .ToLocalChecked();
11540 CHECK(context->Global()
11541 ->Set(context.local(), v8_str("obj2"), instance)
11542 .FromJust());
11543 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011544 Local<Value> value;
11545 CHECK(!try_catch.HasCaught());
11546
11547 // Call an object without call-as-function handler through the JS
11548 value = CompileRun("obj2(28)");
11549 CHECK(value.IsEmpty());
11550 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011551 String::Utf8Value exception_value1(try_catch.Exception());
11552 // TODO(verwaest): Better message
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011553 CHECK_EQ(0, strcmp("TypeError: obj2 is not a function", *exception_value1));
Ben Murdoch257744e2011-11-30 15:57:28 +000011554 try_catch.Reset();
11555
11556 // Call an object without call-as-function handler through the API
11557 value = CompileRun("obj2(28)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011558 v8::Local<Value> args[] = {v8_num(28)};
11559 CHECK(
11560 instance->CallAsFunction(context.local(), instance, 1, args).IsEmpty());
Ben Murdoch257744e2011-11-30 15:57:28 +000011561 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011562 String::Utf8Value exception_value2(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011563 CHECK_EQ(0,
11564 strcmp("TypeError: object is not a function", *exception_value2));
Ben Murdoch257744e2011-11-30 15:57:28 +000011565 try_catch.Reset();
11566 }
11567
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011568 {
11569 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011570 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
11571 instance_template->SetCallAsFunctionHandler(ThrowValue);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011572 Local<v8::Object> instance = t->GetFunction(context.local())
11573 .ToLocalChecked()
11574 ->NewInstance(context.local())
11575 .ToLocalChecked();
11576 CHECK(context->Global()
11577 ->Set(context.local(), v8_str("obj3"), instance)
11578 .FromJust());
11579 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011580 Local<Value> value;
11581 CHECK(!try_catch.HasCaught());
11582
11583 // Catch the exception which is thrown by call-as-function handler
11584 value = CompileRun("obj3(22)");
11585 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011586 String::Utf8Value exception_value1(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011587 CHECK_EQ(0, strcmp("22", *exception_value1));
Ben Murdoch257744e2011-11-30 15:57:28 +000011588 try_catch.Reset();
11589
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011590 v8::Local<Value> args[] = {v8_num(23)};
11591 CHECK(
11592 instance->CallAsFunction(context.local(), instance, 1, args).IsEmpty());
Ben Murdoch257744e2011-11-30 15:57:28 +000011593 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011594 String::Utf8Value exception_value2(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011595 CHECK_EQ(0, strcmp("23", *exception_value2));
Ben Murdoch257744e2011-11-30 15:57:28 +000011596 try_catch.Reset();
11597 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011598
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011599 {
11600 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011601 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
11602 instance_template->SetCallAsFunctionHandler(ReturnThis);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011603 Local<v8::Object> instance = t->GetFunction(context.local())
11604 .ToLocalChecked()
11605 ->NewInstance(context.local())
11606 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011607
11608 Local<v8::Value> a1 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011609 instance->CallAsFunction(context.local(), v8::Undefined(isolate), 0,
11610 NULL)
11611 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011612 CHECK(a1->StrictEquals(instance));
11613 Local<v8::Value> a2 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011614 instance->CallAsFunction(context.local(), v8::Null(isolate), 0, NULL)
11615 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011616 CHECK(a2->StrictEquals(instance));
11617 Local<v8::Value> a3 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011618 instance->CallAsFunction(context.local(), v8_num(42), 0, NULL)
11619 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011620 CHECK(a3->StrictEquals(instance));
11621 Local<v8::Value> a4 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011622 instance->CallAsFunction(context.local(), v8_str("hello"), 0, NULL)
11623 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011624 CHECK(a4->StrictEquals(instance));
11625 Local<v8::Value> a5 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011626 instance->CallAsFunction(context.local(), v8::True(isolate), 0, NULL)
11627 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011628 CHECK(a5->StrictEquals(instance));
11629 }
11630
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011631 {
11632 CompileRun(
11633 "function ReturnThisSloppy() {"
11634 " return this;"
11635 "}"
11636 "function ReturnThisStrict() {"
11637 " 'use strict';"
11638 " return this;"
11639 "}");
11640 Local<Function> ReturnThisSloppy = Local<Function>::Cast(
11641 context->Global()
11642 ->Get(context.local(), v8_str("ReturnThisSloppy"))
11643 .ToLocalChecked());
11644 Local<Function> ReturnThisStrict = Local<Function>::Cast(
11645 context->Global()
11646 ->Get(context.local(), v8_str("ReturnThisStrict"))
11647 .ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011648
11649 Local<v8::Value> a1 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011650 ReturnThisSloppy->CallAsFunction(context.local(),
11651 v8::Undefined(isolate), 0, NULL)
11652 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011653 CHECK(a1->StrictEquals(context->Global()));
11654 Local<v8::Value> a2 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011655 ReturnThisSloppy->CallAsFunction(context.local(), v8::Null(isolate), 0,
11656 NULL)
11657 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011658 CHECK(a2->StrictEquals(context->Global()));
11659 Local<v8::Value> a3 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011660 ReturnThisSloppy->CallAsFunction(context.local(), v8_num(42), 0, NULL)
11661 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011662 CHECK(a3->IsNumberObject());
11663 CHECK_EQ(42.0, a3.As<v8::NumberObject>()->ValueOf());
11664 Local<v8::Value> a4 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011665 ReturnThisSloppy->CallAsFunction(context.local(), v8_str("hello"), 0,
11666 NULL)
11667 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011668 CHECK(a4->IsStringObject());
11669 CHECK(a4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
11670 Local<v8::Value> a5 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011671 ReturnThisSloppy->CallAsFunction(context.local(), v8::True(isolate), 0,
11672 NULL)
11673 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011674 CHECK(a5->IsBooleanObject());
11675 CHECK(a5.As<v8::BooleanObject>()->ValueOf());
11676
11677 Local<v8::Value> a6 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011678 ReturnThisStrict->CallAsFunction(context.local(),
11679 v8::Undefined(isolate), 0, NULL)
11680 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011681 CHECK(a6->IsUndefined());
11682 Local<v8::Value> a7 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011683 ReturnThisStrict->CallAsFunction(context.local(), v8::Null(isolate), 0,
11684 NULL)
11685 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011686 CHECK(a7->IsNull());
11687 Local<v8::Value> a8 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011688 ReturnThisStrict->CallAsFunction(context.local(), v8_num(42), 0, NULL)
11689 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011690 CHECK(a8->StrictEquals(v8_num(42)));
11691 Local<v8::Value> a9 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011692 ReturnThisStrict->CallAsFunction(context.local(), v8_str("hello"), 0,
11693 NULL)
11694 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011695 CHECK(a9->StrictEquals(v8_str("hello")));
11696 Local<v8::Value> a10 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011697 ReturnThisStrict->CallAsFunction(context.local(), v8::True(isolate), 0,
11698 NULL)
11699 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011700 CHECK(a10->StrictEquals(v8::True(isolate)));
11701 }
Ben Murdoch257744e2011-11-30 15:57:28 +000011702}
11703
11704
11705// Check whether a non-function object is callable.
11706THREADED_TEST(CallableObject) {
Ben Murdoch257744e2011-11-30 15:57:28 +000011707 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011708 v8::Isolate* isolate = context->GetIsolate();
11709 v8::HandleScope scope(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011710
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011711 {
11712 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011713 instance_template->SetCallAsFunctionHandler(call_as_function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011714 Local<Object> instance =
11715 instance_template->NewInstance(context.local()).ToLocalChecked();
11716 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011717
11718 CHECK(instance->IsCallable());
11719 CHECK(!try_catch.HasCaught());
11720 }
11721
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011722 {
11723 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
11724 Local<Object> instance =
11725 instance_template->NewInstance(context.local()).ToLocalChecked();
11726 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011727
11728 CHECK(!instance->IsCallable());
11729 CHECK(!try_catch.HasCaught());
11730 }
11731
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011732 {
11733 Local<FunctionTemplate> function_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011734 FunctionTemplate::New(isolate, call_as_function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011735 Local<Function> function =
11736 function_template->GetFunction(context.local()).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011737 Local<Object> instance = function;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011738 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011739
11740 CHECK(instance->IsCallable());
11741 CHECK(!try_catch.HasCaught());
11742 }
11743
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011744 {
11745 Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate);
11746 Local<Function> function =
11747 function_template->GetFunction(context.local()).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011748 Local<Object> instance = function;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011749 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011750
11751 CHECK(instance->IsCallable());
11752 CHECK(!try_catch.HasCaught());
11753 }
Steve Blocka7e24c12009-10-30 11:49:00 +000011754}
11755
11756
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011757THREADED_TEST(Regress567998) {
11758 LocalContext env;
11759 v8::HandleScope scope(env->GetIsolate());
11760
11761 Local<v8::FunctionTemplate> desc =
11762 v8::FunctionTemplate::New(env->GetIsolate());
11763 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
11764 desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis); // callable
11765
11766 Local<v8::Object> obj = desc->GetFunction(env.local())
11767 .ToLocalChecked()
11768 ->NewInstance(env.local())
11769 .ToLocalChecked();
11770 CHECK(
11771 env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
11772
11773 ExpectString("undetectable.toString()", "[object Object]");
11774 ExpectString("typeof undetectable", "undefined");
11775 ExpectString("typeof(undetectable)", "undefined");
11776 ExpectBoolean("typeof undetectable == 'undefined'", true);
11777 ExpectBoolean("typeof undetectable == 'object'", false);
11778 ExpectBoolean("if (undetectable) { true; } else { false; }", false);
11779 ExpectBoolean("!undetectable", true);
11780
11781 ExpectObject("true&&undetectable", obj);
11782 ExpectBoolean("false&&undetectable", false);
11783 ExpectBoolean("true||undetectable", true);
11784 ExpectObject("false||undetectable", obj);
11785
11786 ExpectObject("undetectable&&true", obj);
11787 ExpectObject("undetectable&&false", obj);
11788 ExpectBoolean("undetectable||true", true);
11789 ExpectBoolean("undetectable||false", false);
11790
11791 ExpectBoolean("undetectable==null", true);
11792 ExpectBoolean("null==undetectable", true);
11793 ExpectBoolean("undetectable==undefined", true);
11794 ExpectBoolean("undefined==undetectable", true);
11795 ExpectBoolean("undetectable==undetectable", true);
11796
11797 ExpectBoolean("undetectable===null", false);
11798 ExpectBoolean("null===undetectable", false);
11799 ExpectBoolean("undetectable===undefined", false);
11800 ExpectBoolean("undefined===undetectable", false);
11801 ExpectBoolean("undetectable===undetectable", true);
11802}
11803
11804
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011805static int Recurse(v8::Isolate* isolate, int depth, int iterations) {
11806 v8::HandleScope scope(isolate);
11807 if (depth == 0) return v8::HandleScope::NumberOfHandles(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011808 for (int i = 0; i < iterations; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011809 Local<v8::Number> n(v8::Integer::New(isolate, 42));
Steve Blocka7e24c12009-10-30 11:49:00 +000011810 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011811 return Recurse(isolate, depth - 1, iterations);
Steve Blocka7e24c12009-10-30 11:49:00 +000011812}
11813
11814
11815THREADED_TEST(HandleIteration) {
11816 static const int kIterations = 500;
11817 static const int kNesting = 200;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011818 LocalContext context;
11819 v8::Isolate* isolate = context->GetIsolate();
11820 v8::HandleScope scope0(isolate);
11821 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000011822 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011823 v8::HandleScope scope1(isolate);
11824 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000011825 for (int i = 0; i < kIterations; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011826 Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
11827 CHECK_EQ(i + 1, v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000011828 }
11829
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011830 CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000011831 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011832 v8::HandleScope scope2(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000011833 for (int j = 0; j < kIterations; j++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011834 Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
11835 CHECK_EQ(j + 1 + kIterations,
11836 v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000011837 }
11838 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011839 CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000011840 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011841 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
11842 CHECK_EQ(kNesting * kIterations, Recurse(isolate, kNesting, kIterations));
Steve Blocka7e24c12009-10-30 11:49:00 +000011843}
11844
11845
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011846static void InterceptorCallICFastApi(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040011847 Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
Andrei Popescu402d9372010-02-26 13:31:12 +000011848 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011849 CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
11850 int* call_count =
11851 reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
Andrei Popescu402d9372010-02-26 13:31:12 +000011852 ++(*call_count);
11853 if ((*call_count) % 20 == 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011854 CcTest::heap()->CollectAllGarbage();
Andrei Popescu402d9372010-02-26 13:31:12 +000011855 }
Andrei Popescu402d9372010-02-26 13:31:12 +000011856}
11857
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011858static void FastApiCallback_TrivialSignature(
11859 const v8::FunctionCallbackInfo<v8::Value>& args) {
Andrei Popescu402d9372010-02-26 13:31:12 +000011860 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011861 CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
11862 v8::Isolate* isolate = CcTest::isolate();
11863 CHECK_EQ(isolate, args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011864 CHECK(args.This()
11865 ->Equals(isolate->GetCurrentContext(), args.Holder())
11866 .FromJust());
11867 CHECK(args.Data()
11868 ->Equals(isolate->GetCurrentContext(), v8_str("method_data"))
11869 .FromJust());
11870 args.GetReturnValue().Set(
11871 args[0]->Int32Value(isolate->GetCurrentContext()).FromJust() + 1);
Andrei Popescu402d9372010-02-26 13:31:12 +000011872}
11873
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011874static void FastApiCallback_SimpleSignature(
11875 const v8::FunctionCallbackInfo<v8::Value>& args) {
Andrei Popescu402d9372010-02-26 13:31:12 +000011876 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011877 CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
11878 v8::Isolate* isolate = CcTest::isolate();
11879 CHECK_EQ(isolate, args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011880 CHECK(args.This()
11881 ->GetPrototype()
11882 ->Equals(isolate->GetCurrentContext(), args.Holder())
11883 .FromJust());
11884 CHECK(args.Data()
11885 ->Equals(isolate->GetCurrentContext(), v8_str("method_data"))
11886 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000011887 // Note, we're using HasRealNamedProperty instead of Has to avoid
11888 // invoking the interceptor again.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011889 CHECK(args.Holder()
11890 ->HasRealNamedProperty(isolate->GetCurrentContext(), v8_str("foo"))
11891 .FromJust());
11892 args.GetReturnValue().Set(
11893 args[0]->Int32Value(isolate->GetCurrentContext()).FromJust() + 1);
Andrei Popescu402d9372010-02-26 13:31:12 +000011894}
11895
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011896
Andrei Popescu402d9372010-02-26 13:31:12 +000011897// Helper to maximize the odds of object moving.
11898static void GenerateSomeGarbage() {
11899 CompileRun(
11900 "var garbage;"
11901 "for (var i = 0; i < 1000; i++) {"
11902 " garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
11903 "}"
11904 "garbage = undefined;");
11905}
11906
Ben Murdoche0cee9b2011-05-25 10:26:03 +010011907
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011908void DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Block1e0659c2011-05-24 12:43:12 +010011909 static int count = 0;
11910 if (count++ % 3 == 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011911 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011912 // This should move the stub
Steve Block1e0659c2011-05-24 12:43:12 +010011913 GenerateSomeGarbage(); // This should ensure the old stub memory is flushed
11914 }
Steve Block1e0659c2011-05-24 12:43:12 +010011915}
11916
11917
11918THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
Steve Block1e0659c2011-05-24 12:43:12 +010011919 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011920 v8::Isolate* isolate = context->GetIsolate();
11921 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011922 v8::Local<v8::ObjectTemplate> nativeobject_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011923 v8::ObjectTemplate::New(isolate);
11924 nativeobject_templ->Set(isolate, "callback",
11925 v8::FunctionTemplate::New(isolate,
11926 DirectApiCallback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011927 v8::Local<v8::Object> nativeobject_obj =
11928 nativeobject_templ->NewInstance(context.local()).ToLocalChecked();
11929 CHECK(context->Global()
11930 ->Set(context.local(), v8_str("nativeobject"), nativeobject_obj)
11931 .FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +010011932 // call the api function multiple times to ensure direct call stub creation.
11933 CompileRun(
11934 "function f() {"
11935 " for (var i = 1; i <= 30; i++) {"
11936 " nativeobject.callback();"
11937 " }"
11938 "}"
11939 "f();");
11940}
11941
11942
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011943void ThrowingDirectApiCallback(
11944 const v8::FunctionCallbackInfo<v8::Value>& args) {
11945 args.GetIsolate()->ThrowException(v8_str("g"));
Steve Block1e0659c2011-05-24 12:43:12 +010011946}
11947
11948
11949THREADED_TEST(CallICFastApi_DirectCall_Throw) {
Steve Block1e0659c2011-05-24 12:43:12 +010011950 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011951 v8::Isolate* isolate = context->GetIsolate();
11952 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011953 v8::Local<v8::ObjectTemplate> nativeobject_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011954 v8::ObjectTemplate::New(isolate);
11955 nativeobject_templ->Set(isolate, "callback",
11956 v8::FunctionTemplate::New(isolate,
11957 ThrowingDirectApiCallback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011958 v8::Local<v8::Object> nativeobject_obj =
11959 nativeobject_templ->NewInstance(context.local()).ToLocalChecked();
11960 CHECK(context->Global()
11961 ->Set(context.local(), v8_str("nativeobject"), nativeobject_obj)
11962 .FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +010011963 // call the api function multiple times to ensure direct call stub creation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011964 v8::Local<Value> result = CompileRun(
Steve Block1e0659c2011-05-24 12:43:12 +010011965 "var result = '';"
11966 "function f() {"
11967 " for (var i = 1; i <= 5; i++) {"
11968 " try { nativeobject.callback(); } catch (e) { result += e; }"
11969 " }"
11970 "}"
11971 "f(); result;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011972 CHECK(v8_str("ggggg")->Equals(context.local(), result).FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +010011973}
11974
11975
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011976static int p_getter_count_3;
11977
11978
11979static Local<Value> DoDirectGetter() {
11980 if (++p_getter_count_3 % 3 == 0) {
11981 CcTest::heap()->CollectAllGarbage();
Ben Murdoche0cee9b2011-05-25 10:26:03 +010011982 GenerateSomeGarbage();
11983 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011984 return v8_str("Direct Getter Result");
11985}
11986
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011987
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011988static void DirectGetterCallback(
11989 Local<String> name,
11990 const v8::PropertyCallbackInfo<v8::Value>& info) {
11991 CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
11992 info.GetReturnValue().Set(DoDirectGetter());
Ben Murdoche0cee9b2011-05-25 10:26:03 +010011993}
11994
11995
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011996template<typename Accessor>
11997static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +010011998 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011999 v8::Isolate* isolate = context->GetIsolate();
12000 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012001 v8::Local<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012002 obj->SetAccessor(v8_str("p1"), accessor);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012003 CHECK(context->Global()
12004 ->Set(context.local(), v8_str("o1"),
12005 obj->NewInstance(context.local()).ToLocalChecked())
12006 .FromJust());
12007 p_getter_count_3 = 0;
12008 v8::Local<v8::Value> result = CompileRun(
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012009 "function f() {"
12010 " for (var i = 0; i < 30; i++) o1.p1;"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012011 " return o1.p1"
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012012 "}"
12013 "f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012014 CHECK(v8_str("Direct Getter Result")
12015 ->Equals(context.local(), result)
12016 .FromJust());
12017 CHECK_EQ(31, p_getter_count_3);
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012018}
12019
12020
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012021THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
12022 LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
12023}
12024
12025
12026void ThrowingDirectGetterCallback(
12027 Local<String> name,
12028 const v8::PropertyCallbackInfo<v8::Value>& info) {
12029 info.GetIsolate()->ThrowException(v8_str("g"));
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012030}
12031
12032
12033THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012034 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012035 v8::Isolate* isolate = context->GetIsolate();
12036 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012037 v8::Local<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012038 obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012039 CHECK(context->Global()
12040 ->Set(context.local(), v8_str("o1"),
12041 obj->NewInstance(context.local()).ToLocalChecked())
12042 .FromJust());
12043 v8::Local<Value> result = CompileRun(
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012044 "var result = '';"
12045 "for (var i = 0; i < 5; i++) {"
12046 " try { o1.p1; } catch (e) { result += e; }"
12047 "}"
12048 "result;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012049 CHECK(v8_str("ggggg")->Equals(context.local(), result).FromJust());
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012050}
12051
12052
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012053THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012054 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012055 v8::Isolate* isolate = CcTest::isolate();
12056 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012057 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012058 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012059 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
12060 isolate, FastApiCallback_TrivialSignature, v8_str("method_data"),
12061 v8::Local<v8::Signature>());
12062 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012063 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012064 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012065 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012066 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012067 v8::External::New(isolate, &interceptor_call_count)));
Andrei Popescu402d9372010-02-26 13:31:12 +000012068 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012069 v8::Local<v8::Function> fun =
12070 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012071 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012072 CHECK(context->Global()
12073 ->Set(context.local(), v8_str("o"),
12074 fun->NewInstance(context.local()).ToLocalChecked())
12075 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012076 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012077 "var result = 0;"
12078 "for (var i = 0; i < 100; i++) {"
12079 " result = o.method(41);"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012080 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012081 CHECK_EQ(42, context->Global()
12082 ->Get(context.local(), v8_str("result"))
12083 .ToLocalChecked()
12084 ->Int32Value(context.local())
12085 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012086 CHECK_EQ(100, interceptor_call_count);
12087}
12088
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012089
12090THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012091 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012092 v8::Isolate* isolate = CcTest::isolate();
12093 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012094 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012095 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012096 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012097 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12098 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012099 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012100 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012101 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012102 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012103 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012104 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012105 v8::External::New(isolate, &interceptor_call_count)));
Andrei Popescu402d9372010-02-26 13:31:12 +000012106 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012107 v8::Local<v8::Function> fun =
12108 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012109 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012110 CHECK(context->Global()
12111 ->Set(context.local(), v8_str("o"),
12112 fun->NewInstance(context.local()).ToLocalChecked())
12113 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012114 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012115 "o.foo = 17;"
12116 "var receiver = {};"
12117 "receiver.__proto__ = o;"
12118 "var result = 0;"
12119 "for (var i = 0; i < 100; i++) {"
12120 " result = receiver.method(41);"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012121 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012122 CHECK_EQ(42, context->Global()
12123 ->Get(context.local(), v8_str("result"))
12124 .ToLocalChecked()
12125 ->Int32Value(context.local())
12126 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012127 CHECK_EQ(100, interceptor_call_count);
12128}
12129
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012130
12131THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012132 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012133 v8::Isolate* isolate = CcTest::isolate();
12134 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012135 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012136 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012137 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012138 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12139 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012140 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012141 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012142 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012143 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012144 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012145 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012146 v8::External::New(isolate, &interceptor_call_count)));
Andrei Popescu402d9372010-02-26 13:31:12 +000012147 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012148 v8::Local<v8::Function> fun =
12149 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012150 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012151 CHECK(context->Global()
12152 ->Set(context.local(), v8_str("o"),
12153 fun->NewInstance(context.local()).ToLocalChecked())
12154 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012155 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012156 "o.foo = 17;"
12157 "var receiver = {};"
12158 "receiver.__proto__ = o;"
12159 "var result = 0;"
12160 "var saved_result = 0;"
12161 "for (var i = 0; i < 100; i++) {"
12162 " result = receiver.method(41);"
12163 " if (i == 50) {"
12164 " saved_result = result;"
12165 " receiver = {method: function(x) { return x - 1 }};"
12166 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012167 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012168 CHECK_EQ(40, context->Global()
12169 ->Get(context.local(), v8_str("result"))
12170 .ToLocalChecked()
12171 ->Int32Value(context.local())
12172 .FromJust());
12173 CHECK_EQ(42, context->Global()
12174 ->Get(context.local(), v8_str("saved_result"))
12175 .ToLocalChecked()
12176 ->Int32Value(context.local())
12177 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012178 CHECK_GE(interceptor_call_count, 50);
12179}
12180
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012181
12182THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012183 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012184 v8::Isolate* isolate = CcTest::isolate();
12185 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012186 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012187 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012188 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012189 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12190 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012191 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012192 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012193 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012194 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012195 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012196 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012197 v8::External::New(isolate, &interceptor_call_count)));
Andrei Popescu402d9372010-02-26 13:31:12 +000012198 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012199 v8::Local<v8::Function> fun =
12200 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012201 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012202 CHECK(context->Global()
12203 ->Set(context.local(), v8_str("o"),
12204 fun->NewInstance(context.local()).ToLocalChecked())
12205 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012206 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012207 "o.foo = 17;"
12208 "var receiver = {};"
12209 "receiver.__proto__ = o;"
12210 "var result = 0;"
12211 "var saved_result = 0;"
12212 "for (var i = 0; i < 100; i++) {"
12213 " result = receiver.method(41);"
12214 " if (i == 50) {"
12215 " saved_result = result;"
12216 " o.method = function(x) { return x - 1 };"
12217 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012218 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012219 CHECK_EQ(40, context->Global()
12220 ->Get(context.local(), v8_str("result"))
12221 .ToLocalChecked()
12222 ->Int32Value(context.local())
12223 .FromJust());
12224 CHECK_EQ(42, context->Global()
12225 ->Get(context.local(), v8_str("saved_result"))
12226 .ToLocalChecked()
12227 ->Int32Value(context.local())
12228 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012229 CHECK_GE(interceptor_call_count, 50);
12230}
12231
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012232
12233THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
Steve Block6ded16b2010-05-10 14:33:55 +010012234 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012235 v8::Isolate* isolate = CcTest::isolate();
12236 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012237 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012238 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012239 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012240 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12241 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012242 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Steve Block6ded16b2010-05-10 14:33:55 +010012243 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012244 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012245 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012246 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012247 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012248 v8::External::New(isolate, &interceptor_call_count)));
Steve Block6ded16b2010-05-10 14:33:55 +010012249 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012250 v8::Local<v8::Function> fun =
12251 fun_templ->GetFunction(context.local()).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +010012252 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012253 CHECK(context->Global()
12254 ->Set(context.local(), v8_str("o"),
12255 fun->NewInstance(context.local()).ToLocalChecked())
12256 .FromJust());
12257 v8::TryCatch try_catch(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012258 CompileRun(
Steve Block6ded16b2010-05-10 14:33:55 +010012259 "o.foo = 17;"
12260 "var receiver = {};"
12261 "receiver.__proto__ = o;"
12262 "var result = 0;"
12263 "var saved_result = 0;"
12264 "for (var i = 0; i < 100; i++) {"
12265 " result = receiver.method(41);"
12266 " if (i == 50) {"
12267 " saved_result = result;"
12268 " receiver = 333;"
12269 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012270 "}");
Steve Block6ded16b2010-05-10 14:33:55 +010012271 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012272 // TODO(verwaest): Adjust message.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012273 CHECK(
12274 v8_str("TypeError: receiver.method is not a function")
12275 ->Equals(
12276 context.local(),
12277 try_catch.Exception()->ToString(context.local()).ToLocalChecked())
12278 .FromJust());
12279 CHECK_EQ(42, context->Global()
12280 ->Get(context.local(), v8_str("saved_result"))
12281 .ToLocalChecked()
12282 ->Int32Value(context.local())
12283 .FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +010012284 CHECK_GE(interceptor_call_count, 50);
12285}
12286
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012287
12288THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012289 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012290 v8::Isolate* isolate = CcTest::isolate();
12291 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012292 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012293 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012294 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012295 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12296 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012297 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012298 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012299 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012300 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012301 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012302 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012303 v8::External::New(isolate, &interceptor_call_count)));
Andrei Popescu402d9372010-02-26 13:31:12 +000012304 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012305 v8::Local<v8::Function> fun =
12306 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012307 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012308 CHECK(context->Global()
12309 ->Set(context.local(), v8_str("o"),
12310 fun->NewInstance(context.local()).ToLocalChecked())
12311 .FromJust());
12312 v8::TryCatch try_catch(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012313 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012314 "o.foo = 17;"
12315 "var receiver = {};"
12316 "receiver.__proto__ = o;"
12317 "var result = 0;"
12318 "var saved_result = 0;"
12319 "for (var i = 0; i < 100; i++) {"
12320 " result = receiver.method(41);"
12321 " if (i == 50) {"
12322 " saved_result = result;"
12323 " receiver = {method: receiver.method};"
12324 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012325 "}");
Andrei Popescu402d9372010-02-26 13:31:12 +000012326 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012327 CHECK(
12328 v8_str("TypeError: Illegal invocation")
12329 ->Equals(
12330 context.local(),
12331 try_catch.Exception()->ToString(context.local()).ToLocalChecked())
12332 .FromJust());
12333 CHECK_EQ(42, context->Global()
12334 ->Get(context.local(), v8_str("saved_result"))
12335 .ToLocalChecked()
12336 ->Int32Value(context.local())
12337 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012338 CHECK_GE(interceptor_call_count, 50);
12339}
12340
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012341
12342THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
12343 v8::Isolate* isolate = CcTest::isolate();
12344 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012345 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012346 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012347 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
12348 isolate, FastApiCallback_TrivialSignature, v8_str("method_data"),
12349 v8::Local<v8::Signature>());
12350 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012351 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012352 v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012353 USE(templ);
Andrei Popescu402d9372010-02-26 13:31:12 +000012354 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012355 v8::Local<v8::Function> fun =
12356 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012357 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012358 CHECK(context->Global()
12359 ->Set(context.local(), v8_str("o"),
12360 fun->NewInstance(context.local()).ToLocalChecked())
12361 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012362 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012363 "var result = 0;"
12364 "for (var i = 0; i < 100; i++) {"
12365 " result = o.method(41);"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012366 "}");
Andrei Popescu402d9372010-02-26 13:31:12 +000012367
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012368 CHECK_EQ(42, context->Global()
12369 ->Get(context.local(), v8_str("result"))
12370 .ToLocalChecked()
12371 ->Int32Value(context.local())
12372 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012373}
12374
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012375
12376THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
12377 v8::Isolate* isolate = CcTest::isolate();
12378 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012379 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012380 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012381 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012382 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12383 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012384 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012385 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012386 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012387 v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012388 CHECK(!templ.IsEmpty());
Andrei Popescu402d9372010-02-26 13:31:12 +000012389 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012390 v8::Local<v8::Function> fun =
12391 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012392 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012393 CHECK(context->Global()
12394 ->Set(context.local(), v8_str("o"),
12395 fun->NewInstance(context.local()).ToLocalChecked())
12396 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012397 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012398 "o.foo = 17;"
12399 "var receiver = {};"
12400 "receiver.__proto__ = o;"
12401 "var result = 0;"
12402 "for (var i = 0; i < 100; i++) {"
12403 " result = receiver.method(41);"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012404 "}");
Andrei Popescu402d9372010-02-26 13:31:12 +000012405
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012406 CHECK_EQ(42, context->Global()
12407 ->Get(context.local(), v8_str("result"))
12408 .ToLocalChecked()
12409 ->Int32Value(context.local())
12410 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012411}
12412
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012413
12414THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
12415 v8::Isolate* isolate = CcTest::isolate();
12416 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012417 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012418 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012419 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012420 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12421 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012422 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012423 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012424 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012425 v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012426 CHECK(!templ.IsEmpty());
Andrei Popescu402d9372010-02-26 13:31:12 +000012427 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012428 v8::Local<v8::Function> fun =
12429 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012430 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012431 CHECK(context->Global()
12432 ->Set(context.local(), v8_str("o"),
12433 fun->NewInstance(context.local()).ToLocalChecked())
12434 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012435 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012436 "o.foo = 17;"
12437 "var receiver = {};"
12438 "receiver.__proto__ = o;"
12439 "var result = 0;"
12440 "var saved_result = 0;"
12441 "for (var i = 0; i < 100; i++) {"
12442 " result = receiver.method(41);"
12443 " if (i == 50) {"
12444 " saved_result = result;"
12445 " receiver = {method: function(x) { return x - 1 }};"
12446 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012447 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012448 CHECK_EQ(40, context->Global()
12449 ->Get(context.local(), v8_str("result"))
12450 .ToLocalChecked()
12451 ->Int32Value(context.local())
12452 .FromJust());
12453 CHECK_EQ(42, context->Global()
12454 ->Get(context.local(), v8_str("saved_result"))
12455 .ToLocalChecked()
12456 ->Int32Value(context.local())
12457 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012458}
12459
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012460
12461THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
12462 v8::Isolate* isolate = CcTest::isolate();
12463 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012464 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012465 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012466 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012467 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12468 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012469 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Steve Block6ded16b2010-05-10 14:33:55 +010012470 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012471 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012472 v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012473 CHECK(!templ.IsEmpty());
Steve Block6ded16b2010-05-10 14:33:55 +010012474 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012475 v8::Local<v8::Function> fun =
12476 fun_templ->GetFunction(context.local()).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +010012477 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012478 CHECK(context->Global()
12479 ->Set(context.local(), v8_str("o"),
12480 fun->NewInstance(context.local()).ToLocalChecked())
12481 .FromJust());
12482 v8::TryCatch try_catch(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012483 CompileRun(
Steve Block6ded16b2010-05-10 14:33:55 +010012484 "o.foo = 17;"
12485 "var receiver = {};"
12486 "receiver.__proto__ = o;"
12487 "var result = 0;"
12488 "var saved_result = 0;"
12489 "for (var i = 0; i < 100; i++) {"
12490 " result = receiver.method(41);"
12491 " if (i == 50) {"
12492 " saved_result = result;"
12493 " receiver = 333;"
12494 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012495 "}");
Steve Block6ded16b2010-05-10 14:33:55 +010012496 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012497 // TODO(verwaest): Adjust message.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012498 CHECK(
12499 v8_str("TypeError: receiver.method is not a function")
12500 ->Equals(
12501 context.local(),
12502 try_catch.Exception()->ToString(context.local()).ToLocalChecked())
12503 .FromJust());
12504 CHECK_EQ(42, context->Global()
12505 ->Get(context.local(), v8_str("saved_result"))
12506 .ToLocalChecked()
12507 ->Int32Value(context.local())
12508 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012509}
12510
12511
12512THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) {
12513 v8::Isolate* isolate = CcTest::isolate();
12514 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012515 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012516 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012517 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012518 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12519 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012520 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012521 proto_templ->Set(v8_str("method"), method_templ);
12522 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012523 v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012524 CHECK(!templ.IsEmpty());
12525 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012526 v8::Local<v8::Function> fun =
12527 fun_templ->GetFunction(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012528 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012529 CHECK(context->Global()
12530 ->Set(context.local(), v8_str("o"),
12531 fun->NewInstance(context.local()).ToLocalChecked())
12532 .FromJust());
12533 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012534 CompileRun(
12535 "o.foo = 17;"
12536 "var receiver = {};"
12537 "receiver.__proto__ = o;"
12538 "var result = 0;"
12539 "var saved_result = 0;"
12540 "for (var i = 0; i < 100; i++) {"
12541 " result = receiver.method(41);"
12542 " if (i == 50) {"
12543 " saved_result = result;"
12544 " receiver = Object.create(receiver);"
12545 " }"
12546 "}");
12547 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012548 CHECK(
12549 v8_str("TypeError: Illegal invocation")
12550 ->Equals(
12551 context.local(),
12552 try_catch.Exception()->ToString(context.local()).ToLocalChecked())
12553 .FromJust());
12554 CHECK_EQ(42, context->Global()
12555 ->Get(context.local(), v8_str("saved_result"))
12556 .ToLocalChecked()
12557 ->Int32Value(context.local())
12558 .FromJust());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010012559}
12560
12561
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012562static void ThrowingGetter(Local<String> name,
12563 const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010012564 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012565 info.GetIsolate()->ThrowException(Local<Value>());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012566 info.GetReturnValue().SetUndefined();
Ben Murdoch8b112d22011-06-08 16:22:53 +010012567}
12568
12569
12570THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010012571 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012572 HandleScope scope(context->GetIsolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012573
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012574 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012575 Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
12576 instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
12577
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012578 Local<Object> instance = templ->GetFunction(context.local())
12579 .ToLocalChecked()
12580 ->NewInstance(context.local())
12581 .ToLocalChecked();
Ben Murdoch8b112d22011-06-08 16:22:53 +010012582
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012583 Local<Object> another = Object::New(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012584 CHECK(another->SetPrototype(context.local(), instance).FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012585
12586 Local<Object> with_js_getter = CompileRun(
12587 "o = {};\n"
12588 "o.__defineGetter__('f', function() { throw undefined; });\n"
12589 "o\n").As<Object>();
12590 CHECK(!with_js_getter.IsEmpty());
12591
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012592 TryCatch try_catch(context->GetIsolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012593
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012594 v8::MaybeLocal<Value> result =
12595 instance->GetRealNamedProperty(context.local(), v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012596 CHECK(try_catch.HasCaught());
12597 try_catch.Reset();
12598 CHECK(result.IsEmpty());
12599
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012600 Maybe<PropertyAttribute> attr =
12601 instance->GetRealNamedPropertyAttributes(context.local(), v8_str("f"));
12602 CHECK(!try_catch.HasCaught());
12603 CHECK(Just(None) == attr);
12604
12605 result = another->GetRealNamedProperty(context.local(), v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012606 CHECK(try_catch.HasCaught());
12607 try_catch.Reset();
12608 CHECK(result.IsEmpty());
12609
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012610 attr = another->GetRealNamedPropertyAttributes(context.local(), v8_str("f"));
12611 CHECK(!try_catch.HasCaught());
12612 CHECK(Just(None) == attr);
12613
12614 result = another->GetRealNamedPropertyInPrototypeChain(context.local(),
12615 v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012616 CHECK(try_catch.HasCaught());
12617 try_catch.Reset();
12618 CHECK(result.IsEmpty());
12619
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012620 attr = another->GetRealNamedPropertyAttributesInPrototypeChain(
12621 context.local(), v8_str("f"));
12622 CHECK(!try_catch.HasCaught());
12623 CHECK(Just(None) == attr);
12624
12625 result = another->Get(context.local(), v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012626 CHECK(try_catch.HasCaught());
12627 try_catch.Reset();
12628 CHECK(result.IsEmpty());
12629
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012630 result = with_js_getter->GetRealNamedProperty(context.local(), v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012631 CHECK(try_catch.HasCaught());
12632 try_catch.Reset();
12633 CHECK(result.IsEmpty());
12634
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012635 attr = with_js_getter->GetRealNamedPropertyAttributes(context.local(),
12636 v8_str("f"));
12637 CHECK(!try_catch.HasCaught());
12638 CHECK(Just(None) == attr);
12639
12640 result = with_js_getter->Get(context.local(), v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012641 CHECK(try_catch.HasCaught());
12642 try_catch.Reset();
12643 CHECK(result.IsEmpty());
12644}
12645
12646
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012647static void ThrowingCallbackWithTryCatch(
12648 const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012649 TryCatch try_catch(args.GetIsolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012650 // Verboseness is important: it triggers message delivery which can call into
12651 // external code.
12652 try_catch.SetVerbose(true);
12653 CompileRun("throw 'from JS';");
12654 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012655 CHECK(!CcTest::i_isolate()->has_pending_exception());
12656 CHECK(!CcTest::i_isolate()->has_scheduled_exception());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012657}
12658
12659
12660static int call_depth;
12661
12662
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012663static void WithTryCatch(Local<Message> message, Local<Value> data) {
12664 TryCatch try_catch(CcTest::isolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012665}
12666
12667
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012668static void ThrowFromJS(Local<Message> message, Local<Value> data) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010012669 if (--call_depth) CompileRun("throw 'ThrowInJS';");
12670}
12671
12672
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012673static void ThrowViaApi(Local<Message> message, Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012674 if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012675}
12676
12677
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012678static void WebKitLike(Local<Message> message, Local<Value> data) {
12679 Local<String> errorMessageString = message->Get();
Ben Murdoch8b112d22011-06-08 16:22:53 +010012680 CHECK(!errorMessageString.IsEmpty());
12681 message->GetStackTrace();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012682 message->GetScriptOrigin().ResourceName();
Ben Murdoch8b112d22011-06-08 16:22:53 +010012683}
12684
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012685
Ben Murdoch8b112d22011-06-08 16:22:53 +010012686THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010012687 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012688 v8::Isolate* isolate = context->GetIsolate();
12689 HandleScope scope(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +010012690
12691 Local<Function> func =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012692 FunctionTemplate::New(isolate, ThrowingCallbackWithTryCatch)
12693 ->GetFunction(context.local())
12694 .ToLocalChecked();
12695 CHECK(
12696 context->Global()->Set(context.local(), v8_str("func"), func).FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012697
12698 MessageCallback callbacks[] =
12699 { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
12700 for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
12701 MessageCallback callback = callbacks[i];
12702 if (callback != NULL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012703 isolate->AddMessageListener(callback);
Ben Murdoch8b112d22011-06-08 16:22:53 +010012704 }
Ben Murdoch257744e2011-11-30 15:57:28 +000012705 // Some small number to control number of times message handler should
12706 // throw an exception.
Ben Murdoch8b112d22011-06-08 16:22:53 +010012707 call_depth = 5;
12708 ExpectFalse(
12709 "var thrown = false;\n"
12710 "try { func(); } catch(e) { thrown = true; }\n"
12711 "thrown\n");
12712 if (callback != NULL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012713 isolate->RemoveMessageListeners(callback);
Ben Murdoch8b112d22011-06-08 16:22:53 +010012714 }
12715 }
12716}
12717
12718
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012719static void ParentGetter(Local<String> name,
12720 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +000012721 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012722 info.GetReturnValue().Set(v8_num(1));
Steve Blocka7e24c12009-10-30 11:49:00 +000012723}
12724
12725
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012726static void ChildGetter(Local<String> name,
12727 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +000012728 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012729 info.GetReturnValue().Set(v8_num(42));
Steve Blocka7e24c12009-10-30 11:49:00 +000012730}
12731
12732
12733THREADED_TEST(Overriding) {
Steve Blocka7e24c12009-10-30 11:49:00 +000012734 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012735 v8::Isolate* isolate = context->GetIsolate();
12736 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000012737
12738 // Parent template.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012739 Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000012740 Local<ObjectTemplate> parent_instance_templ =
12741 parent_templ->InstanceTemplate();
12742 parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
12743
12744 // Template that inherits from the parent template.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012745 Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000012746 Local<ObjectTemplate> child_instance_templ =
12747 child_templ->InstanceTemplate();
12748 child_templ->Inherit(parent_templ);
12749 // Override 'f'. The child version of 'f' should get called for child
12750 // instances.
12751 child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
12752 // Add 'g' twice. The 'g' added last should get called for instances.
12753 child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
12754 child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
12755
12756 // Add 'h' as an accessor to the proto template with ReadOnly attributes
12757 // so 'h' can be shadowed on the instance object.
12758 Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
12759 child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012760 v8::Local<Value>(), v8::DEFAULT, v8::ReadOnly);
Steve Blocka7e24c12009-10-30 11:49:00 +000012761
12762 // Add 'i' as an accessor to the instance template with ReadOnly attributes
12763 // but the attribute does not have effect because it is duplicated with
12764 // NULL setter.
12765 child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012766 v8::Local<Value>(), v8::DEFAULT,
12767 v8::ReadOnly);
Steve Blocka7e24c12009-10-30 11:49:00 +000012768
12769
12770 // Instantiate the child template.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012771 Local<v8::Object> instance = child_templ->GetFunction(context.local())
12772 .ToLocalChecked()
12773 ->NewInstance(context.local())
12774 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000012775
12776 // Check that the child function overrides the parent one.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012777 CHECK(context->Global()
12778 ->Set(context.local(), v8_str("o"), instance)
12779 .FromJust());
12780 Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000012781 // Check that the 'g' that was added last is hit.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012782 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
12783 value = v8_compile("o.g")->Run(context.local()).ToLocalChecked();
12784 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000012785
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012786 // Check that 'h' cannot be shadowed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012787 value = v8_compile("o.h = 3; o.h")->Run(context.local()).ToLocalChecked();
12788 CHECK_EQ(1, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000012789
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012790 // Check that 'i' cannot be shadowed or changed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012791 value = v8_compile("o.i = 3; o.i")->Run(context.local()).ToLocalChecked();
12792 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000012793}
12794
12795
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012796static void IsConstructHandler(
12797 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +000012798 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012799 args.GetReturnValue().Set(args.IsConstructCall());
Steve Blocka7e24c12009-10-30 11:49:00 +000012800}
12801
12802
12803THREADED_TEST(IsConstructCall) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012804 v8::Isolate* isolate = CcTest::isolate();
12805 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000012806
12807 // Function template with call handler.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012808 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000012809 templ->SetCallHandler(IsConstructHandler);
12810
12811 LocalContext context;
12812
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012813 CHECK(context->Global()
12814 ->Set(context.local(), v8_str("f"),
12815 templ->GetFunction(context.local()).ToLocalChecked())
12816 .FromJust());
12817 Local<Value> value = v8_compile("f()")->Run(context.local()).ToLocalChecked();
12818 CHECK(!value->BooleanValue(context.local()).FromJust());
12819 value = v8_compile("new f()")->Run(context.local()).ToLocalChecked();
12820 CHECK(value->BooleanValue(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000012821}
12822
12823
12824THREADED_TEST(ObjectProtoToString) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012825 v8::Isolate* isolate = CcTest::isolate();
12826 v8::HandleScope scope(isolate);
12827 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000012828 templ->SetClassName(v8_str("MyClass"));
12829
12830 LocalContext context;
12831
12832 Local<String> customized_tostring = v8_str("customized toString");
12833
12834 // Replace Object.prototype.toString
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012835 v8_compile(
12836 "Object.prototype.toString = function() {"
12837 " return 'customized toString';"
12838 "}")
12839 ->Run(context.local())
12840 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000012841
12842 // Normal ToString call should call replaced Object.prototype.toString
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012843 Local<v8::Object> instance = templ->GetFunction(context.local())
12844 .ToLocalChecked()
12845 ->NewInstance(context.local())
12846 .ToLocalChecked();
12847 Local<String> value = instance->ToString(context.local()).ToLocalChecked();
12848 CHECK(value->IsString() &&
12849 value->Equals(context.local(), customized_tostring).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000012850
12851 // ObjectProtoToString should not call replace toString function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012852 value = instance->ObjectProtoToString(context.local()).ToLocalChecked();
12853 CHECK(value->IsString() &&
12854 value->Equals(context.local(), v8_str("[object MyClass]")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000012855
12856 // Check global
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012857 value =
12858 context->Global()->ObjectProtoToString(context.local()).ToLocalChecked();
12859 CHECK(value->IsString() &&
12860 value->Equals(context.local(), v8_str("[object global]")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000012861
12862 // Check ordinary object
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012863 Local<Value> object =
12864 v8_compile("new Object()")->Run(context.local()).ToLocalChecked();
12865 value = object.As<v8::Object>()
12866 ->ObjectProtoToString(context.local())
12867 .ToLocalChecked();
12868 CHECK(value->IsString() &&
12869 value->Equals(context.local(), v8_str("[object Object]")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000012870}
12871
12872
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012873TEST(ObjectProtoToStringES6) {
12874 // TODO(dslomov, caitp): merge into ObjectProtoToString test once shipped.
12875 i::FLAG_harmony_tostring = true;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080012876 LocalContext context;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012877 v8::Isolate* isolate = CcTest::isolate();
12878 v8::HandleScope scope(isolate);
12879 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
12880 templ->SetClassName(v8_str("MyClass"));
12881
12882 Local<String> customized_tostring = v8_str("customized toString");
12883
12884 // Replace Object.prototype.toString
12885 CompileRun(
12886 "Object.prototype.toString = function() {"
12887 " return 'customized toString';"
12888 "}");
12889
12890 // Normal ToString call should call replaced Object.prototype.toString
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012891 Local<v8::Object> instance = templ->GetFunction(context.local())
12892 .ToLocalChecked()
12893 ->NewInstance(context.local())
12894 .ToLocalChecked();
12895 Local<String> value = instance->ToString(context.local()).ToLocalChecked();
12896 CHECK(value->IsString() &&
12897 value->Equals(context.local(), customized_tostring).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012898
12899 // ObjectProtoToString should not call replace toString function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012900 value = instance->ObjectProtoToString(context.local()).ToLocalChecked();
12901 CHECK(value->IsString() &&
12902 value->Equals(context.local(), v8_str("[object MyClass]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012903
12904 // Check global
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012905 value =
12906 context->Global()->ObjectProtoToString(context.local()).ToLocalChecked();
12907 CHECK(value->IsString() &&
12908 value->Equals(context.local(), v8_str("[object global]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012909
12910 // Check ordinary object
12911 Local<Value> object = CompileRun("new Object()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012912 value = object.As<v8::Object>()
12913 ->ObjectProtoToString(context.local())
12914 .ToLocalChecked();
12915 CHECK(value->IsString() &&
12916 value->Equals(context.local(), v8_str("[object Object]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012917
12918 // Check that ES6 semantics using @@toStringTag work
12919 Local<v8::Symbol> toStringTag = v8::Symbol::GetToStringTag(isolate);
12920
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012921#define TEST_TOSTRINGTAG(type, tag, expected) \
12922 do { \
12923 object = CompileRun("new " #type "()"); \
12924 CHECK(object.As<v8::Object>() \
12925 ->Set(context.local(), toStringTag, v8_str(#tag)) \
12926 .FromJust()); \
12927 value = object.As<v8::Object>() \
12928 ->ObjectProtoToString(context.local()) \
12929 .ToLocalChecked(); \
12930 CHECK(value->IsString() && \
12931 value->Equals(context.local(), v8_str("[object " #expected "]")) \
12932 .FromJust()); \
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012933 } while (0)
12934
12935 TEST_TOSTRINGTAG(Array, Object, Object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012936 TEST_TOSTRINGTAG(Object, Arguments, Arguments);
12937 TEST_TOSTRINGTAG(Object, Array, Array);
12938 TEST_TOSTRINGTAG(Object, Boolean, Boolean);
12939 TEST_TOSTRINGTAG(Object, Date, Date);
12940 TEST_TOSTRINGTAG(Object, Error, Error);
12941 TEST_TOSTRINGTAG(Object, Function, Function);
12942 TEST_TOSTRINGTAG(Object, Number, Number);
12943 TEST_TOSTRINGTAG(Object, RegExp, RegExp);
12944 TEST_TOSTRINGTAG(Object, String, String);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012945 TEST_TOSTRINGTAG(Object, Foo, Foo);
12946
12947#undef TEST_TOSTRINGTAG
12948
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012949 Local<v8::RegExp> valueRegExp =
12950 v8::RegExp::New(context.local(), v8_str("^$"), v8::RegExp::kNone)
12951 .ToLocalChecked();
12952 Local<Value> valueNumber = v8_num(123);
12953 Local<v8::Symbol> valueSymbol = v8_symbol("TestSymbol");
12954 Local<v8::Function> valueFunction =
12955 CompileRun("(function fn() {})").As<v8::Function>();
12956 Local<v8::Object> valueObject = v8::Object::New(v8::Isolate::GetCurrent());
12957 Local<v8::Primitive> valueNull = v8::Null(v8::Isolate::GetCurrent());
12958 Local<v8::Primitive> valueUndef = v8::Undefined(v8::Isolate::GetCurrent());
12959
12960#define TEST_TOSTRINGTAG(type, tagValue, expected) \
12961 do { \
12962 object = CompileRun("new " #type "()"); \
12963 CHECK(object.As<v8::Object>() \
12964 ->Set(context.local(), toStringTag, tagValue) \
12965 .FromJust()); \
12966 value = object.As<v8::Object>() \
12967 ->ObjectProtoToString(context.local()) \
12968 .ToLocalChecked(); \
12969 CHECK(value->IsString() && \
12970 value->Equals(context.local(), v8_str("[object " #expected "]")) \
12971 .FromJust()); \
12972 } while (0)
12973
12974#define TEST_TOSTRINGTAG_TYPES(tagValue) \
12975 TEST_TOSTRINGTAG(Array, tagValue, Array); \
12976 TEST_TOSTRINGTAG(Object, tagValue, Object); \
12977 TEST_TOSTRINGTAG(Function, tagValue, Function); \
12978 TEST_TOSTRINGTAG(Date, tagValue, Date); \
12979 TEST_TOSTRINGTAG(RegExp, tagValue, RegExp); \
12980 TEST_TOSTRINGTAG(Error, tagValue, Error); \
12981
12982 // Test non-String-valued @@toStringTag
12983 TEST_TOSTRINGTAG_TYPES(valueRegExp);
12984 TEST_TOSTRINGTAG_TYPES(valueNumber);
12985 TEST_TOSTRINGTAG_TYPES(valueSymbol);
12986 TEST_TOSTRINGTAG_TYPES(valueFunction);
12987 TEST_TOSTRINGTAG_TYPES(valueObject);
12988 TEST_TOSTRINGTAG_TYPES(valueNull);
12989 TEST_TOSTRINGTAG_TYPES(valueUndef);
12990
12991#undef TEST_TOSTRINGTAG
12992#undef TEST_TOSTRINGTAG_TYPES
12993
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012994 // @@toStringTag getter throws
12995 Local<Value> obj = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012996 obj.As<v8::Object>()
12997 ->SetAccessor(context.local(), toStringTag, ThrowingSymbolAccessorGetter)
12998 .FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012999 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013000 TryCatch try_catch(isolate);
13001 CHECK(obj.As<v8::Object>()->ObjectProtoToString(context.local()).IsEmpty());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013002 CHECK(try_catch.HasCaught());
13003 }
13004
13005 // @@toStringTag getter does not throw
13006 obj = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013007 obj.As<v8::Object>()
13008 ->SetAccessor(context.local(), toStringTag,
13009 SymbolAccessorGetterReturnsDefault, 0, v8_str("Test"))
13010 .FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013011 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013012 TryCatch try_catch(isolate);
13013 value = obj.As<v8::Object>()
13014 ->ObjectProtoToString(context.local())
13015 .ToLocalChecked();
13016 CHECK(value->IsString() &&
13017 value->Equals(context.local(), v8_str("[object Test]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013018 CHECK(!try_catch.HasCaught());
13019 }
13020
13021 // JS @@toStringTag value
13022 obj = CompileRun("obj = {}; obj[Symbol.toStringTag] = 'Test'; obj");
13023 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013024 TryCatch try_catch(isolate);
13025 value = obj.As<v8::Object>()
13026 ->ObjectProtoToString(context.local())
13027 .ToLocalChecked();
13028 CHECK(value->IsString() &&
13029 value->Equals(context.local(), v8_str("[object Test]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013030 CHECK(!try_catch.HasCaught());
13031 }
13032
13033 // JS @@toStringTag getter throws
13034 obj = CompileRun(
13035 "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
13036 " get: function() { throw 'Test'; }"
13037 "}); obj");
13038 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013039 TryCatch try_catch(isolate);
13040 CHECK(obj.As<v8::Object>()->ObjectProtoToString(context.local()).IsEmpty());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013041 CHECK(try_catch.HasCaught());
13042 }
13043
13044 // JS @@toStringTag getter does not throw
13045 obj = CompileRun(
13046 "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
13047 " get: function() { return 'Test'; }"
13048 "}); obj");
13049 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013050 TryCatch try_catch(isolate);
13051 value = obj.As<v8::Object>()
13052 ->ObjectProtoToString(context.local())
13053 .ToLocalChecked();
13054 CHECK(value->IsString() &&
13055 value->Equals(context.local(), v8_str("[object Test]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013056 CHECK(!try_catch.HasCaught());
13057 }
13058}
13059
13060
13061THREADED_TEST(ObjectGetConstructorName) {
13062 v8::Isolate* isolate = CcTest::isolate();
13063 LocalContext context;
13064 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013065 v8_compile(
13066 "function Parent() {};"
13067 "function Child() {};"
13068 "Child.prototype = new Parent();"
13069 "Child.prototype.constructor = Child;"
13070 "var outer = { inner: function() { } };"
13071 "var p = new Parent();"
13072 "var c = new Child();"
13073 "var x = new outer.inner();"
13074 "var proto = Child.prototype;")
13075 ->Run(context.local())
13076 .ToLocalChecked();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080013077
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013078 Local<v8::Value> p =
13079 context->Global()->Get(context.local(), v8_str("p")).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013080 CHECK(p->IsObject() &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013081 p->ToObject(context.local())
13082 .ToLocalChecked()
13083 ->GetConstructorName()
13084 ->Equals(context.local(), v8_str("Parent"))
13085 .FromJust());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080013086
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013087 Local<v8::Value> c =
13088 context->Global()->Get(context.local(), v8_str("c")).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013089 CHECK(c->IsObject() &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013090 c->ToObject(context.local())
13091 .ToLocalChecked()
13092 ->GetConstructorName()
13093 ->Equals(context.local(), v8_str("Child"))
13094 .FromJust());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080013095
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013096 Local<v8::Value> x =
13097 context->Global()->Get(context.local(), v8_str("x")).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013098 CHECK(x->IsObject() &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013099 x->ToObject(context.local())
13100 .ToLocalChecked()
13101 ->GetConstructorName()
13102 ->Equals(context.local(), v8_str("outer.inner"))
13103 .FromJust());
13104
13105 Local<v8::Value> child_prototype =
13106 context->Global()->Get(context.local(), v8_str("proto")).ToLocalChecked();
13107 CHECK(child_prototype->IsObject() &&
13108 child_prototype->ToObject(context.local())
13109 .ToLocalChecked()
13110 ->GetConstructorName()
13111 ->Equals(context.local(), v8_str("Parent"))
13112 .FromJust());
13113}
13114
13115
13116THREADED_TEST(SubclassGetConstructorName) {
13117 v8::Isolate* isolate = CcTest::isolate();
13118 LocalContext context;
13119 v8::HandleScope scope(isolate);
13120 v8_compile(
13121 "\"use strict\";"
13122 "class Parent {}"
13123 "class Child extends Parent {}"
13124 "var p = new Parent();"
13125 "var c = new Child();")
13126 ->Run(context.local())
13127 .ToLocalChecked();
13128
13129 Local<v8::Value> p =
13130 context->Global()->Get(context.local(), v8_str("p")).ToLocalChecked();
13131 CHECK(p->IsObject() &&
13132 p->ToObject(context.local())
13133 .ToLocalChecked()
13134 ->GetConstructorName()
13135 ->Equals(context.local(), v8_str("Parent"))
13136 .FromJust());
13137
13138 Local<v8::Value> c =
13139 context->Global()->Get(context.local(), v8_str("c")).ToLocalChecked();
13140 CHECK(c->IsObject() &&
13141 c->ToObject(context.local())
13142 .ToLocalChecked()
13143 ->GetConstructorName()
13144 ->Equals(context.local(), v8_str("Child"))
13145 .FromJust());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080013146}
13147
13148
Steve Blocka7e24c12009-10-30 11:49:00 +000013149bool ApiTestFuzzer::fuzzing_ = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013150v8::base::Semaphore ApiTestFuzzer::all_tests_done_(0);
Steve Blocka7e24c12009-10-30 11:49:00 +000013151int ApiTestFuzzer::active_tests_;
13152int ApiTestFuzzer::tests_being_run_;
13153int ApiTestFuzzer::current_;
13154
13155
13156// We are in a callback and want to switch to another thread (if we
13157// are currently running the thread fuzzing test).
13158void ApiTestFuzzer::Fuzz() {
13159 if (!fuzzing_) return;
13160 ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
13161 test->ContextSwitch();
13162}
13163
13164
13165// Let the next thread go. Since it is also waiting on the V8 lock it may
13166// not start immediately.
13167bool ApiTestFuzzer::NextThread() {
13168 int test_position = GetNextTestNumber();
Steve Blockd0582a62009-12-15 09:54:21 +000013169 const char* test_name = RegisterThreadedTest::nth(current_)->name();
Steve Blocka7e24c12009-10-30 11:49:00 +000013170 if (test_position == current_) {
Steve Blockd0582a62009-12-15 09:54:21 +000013171 if (kLogThreading)
13172 printf("Stay with %s\n", test_name);
Steve Blocka7e24c12009-10-30 11:49:00 +000013173 return false;
13174 }
Steve Blockd0582a62009-12-15 09:54:21 +000013175 if (kLogThreading) {
13176 printf("Switch from %s to %s\n",
13177 test_name,
13178 RegisterThreadedTest::nth(test_position)->name());
13179 }
Steve Blocka7e24c12009-10-30 11:49:00 +000013180 current_ = test_position;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013181 RegisterThreadedTest::nth(current_)->fuzzer_->gate_.Signal();
Steve Blocka7e24c12009-10-30 11:49:00 +000013182 return true;
13183}
13184
13185
13186void ApiTestFuzzer::Run() {
13187 // When it is our turn...
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013188 gate_.Wait();
Steve Blocka7e24c12009-10-30 11:49:00 +000013189 {
13190 // ... get the V8 lock and start running the test.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013191 v8::Locker locker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013192 CallTest();
13193 }
13194 // This test finished.
13195 active_ = false;
13196 active_tests_--;
13197 // If it was the last then signal that fact.
13198 if (active_tests_ == 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013199 all_tests_done_.Signal();
Steve Blocka7e24c12009-10-30 11:49:00 +000013200 } else {
13201 // Otherwise select a new test and start that.
13202 NextThread();
13203 }
13204}
13205
13206
13207static unsigned linear_congruential_generator;
13208
13209
Ben Murdoch3ef787d2012-04-12 10:51:47 +010013210void ApiTestFuzzer::SetUp(PartOfTest part) {
Steve Blocka7e24c12009-10-30 11:49:00 +000013211 linear_congruential_generator = i::FLAG_testing_prng_seed;
13212 fuzzing_ = true;
Ben Murdoch257744e2011-11-30 15:57:28 +000013213 int count = RegisterThreadedTest::count();
13214 int start = count * part / (LAST_PART + 1);
13215 int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
13216 active_tests_ = tests_being_run_ = end - start + 1;
Steve Blocka7e24c12009-10-30 11:49:00 +000013217 for (int i = 0; i < tests_being_run_; i++) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000013218 RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
Steve Blocka7e24c12009-10-30 11:49:00 +000013219 }
13220 for (int i = 0; i < active_tests_; i++) {
13221 RegisterThreadedTest::nth(i)->fuzzer_->Start();
13222 }
13223}
13224
13225
13226static void CallTestNumber(int test_number) {
13227 (RegisterThreadedTest::nth(test_number)->callback())();
13228}
13229
13230
13231void ApiTestFuzzer::RunAllTests() {
13232 // Set off the first test.
13233 current_ = -1;
13234 NextThread();
13235 // Wait till they are all done.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013236 all_tests_done_.Wait();
Steve Blocka7e24c12009-10-30 11:49:00 +000013237}
13238
13239
13240int ApiTestFuzzer::GetNextTestNumber() {
13241 int next_test;
13242 do {
13243 next_test = (linear_congruential_generator >> 16) % tests_being_run_;
13244 linear_congruential_generator *= 1664525u;
13245 linear_congruential_generator += 1013904223u;
13246 } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
13247 return next_test;
13248}
13249
13250
13251void ApiTestFuzzer::ContextSwitch() {
13252 // If the new thread is the same as the current thread there is nothing to do.
13253 if (NextThread()) {
13254 // Now it can start.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013255 v8::Unlocker unlocker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013256 // Wait till someone starts us again.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013257 gate_.Wait();
Steve Blocka7e24c12009-10-30 11:49:00 +000013258 // And we're off.
13259 }
13260}
13261
13262
13263void ApiTestFuzzer::TearDown() {
13264 fuzzing_ = false;
13265 for (int i = 0; i < RegisterThreadedTest::count(); i++) {
13266 ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
13267 if (fuzzer != NULL) fuzzer->Join();
13268 }
13269}
13270
13271
13272// Lets not be needlessly self-referential.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013273TEST(Threading1) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010013274 ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART);
Steve Blocka7e24c12009-10-30 11:49:00 +000013275 ApiTestFuzzer::RunAllTests();
13276 ApiTestFuzzer::TearDown();
13277}
13278
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013279
Steve Blocka7e24c12009-10-30 11:49:00 +000013280TEST(Threading2) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010013281 ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
Steve Blocka7e24c12009-10-30 11:49:00 +000013282 ApiTestFuzzer::RunAllTests();
13283 ApiTestFuzzer::TearDown();
13284}
13285
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013286
Ben Murdoch257744e2011-11-30 15:57:28 +000013287TEST(Threading3) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010013288 ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
Ben Murdoch257744e2011-11-30 15:57:28 +000013289 ApiTestFuzzer::RunAllTests();
13290 ApiTestFuzzer::TearDown();
13291}
13292
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013293
Ben Murdoch257744e2011-11-30 15:57:28 +000013294TEST(Threading4) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010013295 ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
Ben Murdoch257744e2011-11-30 15:57:28 +000013296 ApiTestFuzzer::RunAllTests();
13297 ApiTestFuzzer::TearDown();
13298}
Steve Blocka7e24c12009-10-30 11:49:00 +000013299
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013300
Steve Blocka7e24c12009-10-30 11:49:00 +000013301void ApiTestFuzzer::CallTest() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013302 v8::Isolate::Scope scope(CcTest::isolate());
Steve Blockd0582a62009-12-15 09:54:21 +000013303 if (kLogThreading)
13304 printf("Start test %d\n", test_number_);
Steve Blocka7e24c12009-10-30 11:49:00 +000013305 CallTestNumber(test_number_);
Steve Blockd0582a62009-12-15 09:54:21 +000013306 if (kLogThreading)
13307 printf("End test %d\n", test_number_);
Steve Blocka7e24c12009-10-30 11:49:00 +000013308}
13309
13310
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013311static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
13312 v8::Isolate* isolate = args.GetIsolate();
13313 CHECK(v8::Locker::IsLocked(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000013314 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013315 v8::Unlocker unlocker(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000013316 const char* code = "throw 7;";
13317 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013318 v8::Locker nested_locker(isolate);
13319 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013320 v8::Local<Value> exception;
13321 {
13322 v8::TryCatch try_catch(isolate);
13323 v8::Local<Value> value = CompileRun(code);
Steve Blocka7e24c12009-10-30 11:49:00 +000013324 CHECK(value.IsEmpty());
13325 CHECK(try_catch.HasCaught());
13326 // Make sure to wrap the exception in a new handle because
13327 // the handle returned from the TryCatch is destroyed
13328 // when the TryCatch is destroyed.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013329 exception = Local<Value>::New(isolate, try_catch.Exception());
Steve Blocka7e24c12009-10-30 11:49:00 +000013330 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013331 args.GetIsolate()->ThrowException(exception);
Steve Blocka7e24c12009-10-30 11:49:00 +000013332 }
13333}
13334
13335
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013336static void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
13337 CHECK(v8::Locker::IsLocked(CcTest::isolate()));
Steve Blocka7e24c12009-10-30 11:49:00 +000013338 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013339 v8::Unlocker unlocker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013340 const char* code = "throw 7;";
13341 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013342 v8::Locker nested_locker(CcTest::isolate());
13343 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013344 v8::Local<Value> value = CompileRun(code);
Steve Blocka7e24c12009-10-30 11:49:00 +000013345 CHECK(value.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013346 args.GetReturnValue().Set(v8_str("foo"));
Steve Blocka7e24c12009-10-30 11:49:00 +000013347 }
13348}
13349
13350
13351// These are locking tests that don't need to be run again
13352// as part of the locking aggregation tests.
13353TEST(NestedLockers) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013354 v8::Isolate* isolate = CcTest::isolate();
13355 v8::Locker locker(isolate);
13356 CHECK(v8::Locker::IsLocked(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000013357 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013358 v8::HandleScope scope(env->GetIsolate());
13359 Local<v8::FunctionTemplate> fun_templ =
13360 v8::FunctionTemplate::New(isolate, ThrowInJS);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013361 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
13362 CHECK(env->Global()->Set(env.local(), v8_str("throw_in_js"), fun).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013363 Local<Script> script = v8_compile("(function () {"
13364 " try {"
13365 " throw_in_js();"
13366 " return 42;"
13367 " } catch (e) {"
13368 " return e * 13;"
13369 " }"
13370 "})();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013371 CHECK_EQ(91, script->Run(env.local())
13372 .ToLocalChecked()
13373 ->Int32Value(env.local())
13374 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013375}
13376
13377
13378// These are locking tests that don't need to be run again
13379// as part of the locking aggregation tests.
13380TEST(NestedLockersNoTryCatch) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013381 v8::Locker locker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013382 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013383 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013384 Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013385 v8::FunctionTemplate::New(env->GetIsolate(), ThrowInJSNoCatch);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013386 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
13387 CHECK(env->Global()->Set(env.local(), v8_str("throw_in_js"), fun).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013388 Local<Script> script = v8_compile("(function () {"
13389 " try {"
13390 " throw_in_js();"
13391 " return 42;"
13392 " } catch (e) {"
13393 " return e * 13;"
13394 " }"
13395 "})();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013396 CHECK_EQ(91, script->Run(env.local())
13397 .ToLocalChecked()
13398 ->Int32Value(env.local())
13399 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013400}
13401
13402
13403THREADED_TEST(RecursiveLocking) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013404 v8::Locker locker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013405 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013406 v8::Locker locker2(CcTest::isolate());
13407 CHECK(v8::Locker::IsLocked(CcTest::isolate()));
Steve Blocka7e24c12009-10-30 11:49:00 +000013408 }
13409}
13410
13411
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013412static void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +000013413 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013414 v8::Unlocker unlocker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013415}
13416
13417
13418THREADED_TEST(LockUnlockLock) {
13419 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013420 v8::Locker locker(CcTest::isolate());
13421 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013422 LocalContext env;
13423 Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013424 v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013425 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
13426 CHECK(env->Global()
13427 ->Set(env.local(), v8_str("unlock_for_a_moment"), fun)
13428 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013429 Local<Script> script = v8_compile("(function () {"
13430 " unlock_for_a_moment();"
13431 " return 42;"
13432 "})();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013433 CHECK_EQ(42, script->Run(env.local())
13434 .ToLocalChecked()
13435 ->Int32Value(env.local())
13436 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013437 }
13438 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013439 v8::Locker locker(CcTest::isolate());
13440 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013441 LocalContext env;
13442 Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013443 v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013444 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
13445 CHECK(env->Global()
13446 ->Set(env.local(), v8_str("unlock_for_a_moment"), fun)
13447 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013448 Local<Script> script = v8_compile("(function () {"
13449 " unlock_for_a_moment();"
13450 " return 42;"
13451 "})();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013452 CHECK_EQ(42, script->Run(env.local())
13453 .ToLocalChecked()
13454 ->Int32Value(env.local())
13455 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013456 }
13457}
13458
13459
Leon Clarked91b9f72010-01-27 17:25:45 +000013460static int GetGlobalObjectsCount() {
Leon Clarkeeab96aa2010-01-27 16:31:12 +000013461 int count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013462 i::HeapIterator it(CcTest::heap());
Leon Clarked91b9f72010-01-27 17:25:45 +000013463 for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013464 if (object->IsJSGlobalObject()) {
13465 i::JSGlobalObject* g = i::JSGlobalObject::cast(object);
13466 // Skip dummy global object.
13467 if (i::GlobalDictionary::cast(g->properties())->NumberOfElements() != 0) {
13468 count++;
13469 }
13470 }
Leon Clarked91b9f72010-01-27 17:25:45 +000013471 return count;
13472}
13473
13474
Ben Murdochf87a2032010-10-22 12:50:53 +010013475static void CheckSurvivingGlobalObjectsCount(int expected) {
Steve Blocka7e24c12009-10-30 11:49:00 +000013476 // We need to collect all garbage twice to be sure that everything
13477 // has been collected. This is because inline caches are cleared in
13478 // the first garbage collection but some of the maps have already
13479 // been marked at that point. Therefore some of the maps are not
13480 // collected until the second garbage collection.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013481 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013482 CcTest::heap()->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
Leon Clarked91b9f72010-01-27 17:25:45 +000013483 int count = GetGlobalObjectsCount();
Steve Blocka7e24c12009-10-30 11:49:00 +000013484#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013485 if (count != expected) CcTest::heap()->TracePathToGlobal();
Steve Blocka7e24c12009-10-30 11:49:00 +000013486#endif
Ben Murdochf87a2032010-10-22 12:50:53 +010013487 CHECK_EQ(expected, count);
Steve Blocka7e24c12009-10-30 11:49:00 +000013488}
13489
13490
13491TEST(DontLeakGlobalObjects) {
13492 // Regression test for issues 1139850 and 1174891.
13493
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013494 i::FLAG_expose_gc = true;
Steve Blocka7e24c12009-10-30 11:49:00 +000013495 v8::V8::Initialize();
13496
Steve Blocka7e24c12009-10-30 11:49:00 +000013497 for (int i = 0; i < 5; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013498 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013499 LocalContext context;
13500 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013501 CcTest::isolate()->ContextDisposedNotification();
Ben Murdochf87a2032010-10-22 12:50:53 +010013502 CheckSurvivingGlobalObjectsCount(0);
Steve Blocka7e24c12009-10-30 11:49:00 +000013503
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013504 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013505 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013506 v8_compile("Date")->Run(context.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000013507 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013508 CcTest::isolate()->ContextDisposedNotification();
Ben Murdochf87a2032010-10-22 12:50:53 +010013509 CheckSurvivingGlobalObjectsCount(0);
Steve Blocka7e24c12009-10-30 11:49:00 +000013510
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013511 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013512 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013513 v8_compile("/aaa/")->Run(context.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000013514 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013515 CcTest::isolate()->ContextDisposedNotification();
Ben Murdochf87a2032010-10-22 12:50:53 +010013516 CheckSurvivingGlobalObjectsCount(0);
Steve Blocka7e24c12009-10-30 11:49:00 +000013517
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013518 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013519 const char* extension_list[] = { "v8/gc" };
13520 v8::ExtensionConfiguration extensions(1, extension_list);
13521 LocalContext context(&extensions);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013522 v8_compile("gc();")->Run(context.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000013523 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013524 CcTest::isolate()->ContextDisposedNotification();
Ben Murdochf87a2032010-10-22 12:50:53 +010013525 CheckSurvivingGlobalObjectsCount(0);
Steve Blocka7e24c12009-10-30 11:49:00 +000013526 }
13527}
13528
13529
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013530TEST(CopyablePersistent) {
13531 LocalContext context;
13532 v8::Isolate* isolate = context->GetIsolate();
13533 i::GlobalHandles* globals =
13534 reinterpret_cast<i::Isolate*>(isolate)->global_handles();
13535 int initial_handles = globals->global_handles_count();
13536 typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> >
13537 CopyableObject;
13538 {
13539 CopyableObject handle1;
13540 {
13541 v8::HandleScope scope(isolate);
13542 handle1.Reset(isolate, v8::Object::New(isolate));
13543 }
13544 CHECK_EQ(initial_handles + 1, globals->global_handles_count());
13545 CopyableObject handle2;
13546 handle2 = handle1;
13547 CHECK(handle1 == handle2);
13548 CHECK_EQ(initial_handles + 2, globals->global_handles_count());
13549 CopyableObject handle3(handle2);
13550 CHECK(handle1 == handle3);
13551 CHECK_EQ(initial_handles + 3, globals->global_handles_count());
13552 }
13553 // Verify autodispose
13554 CHECK_EQ(initial_handles, globals->global_handles_count());
13555}
13556
13557
13558static void WeakApiCallback(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013559 const v8::WeakCallbackInfo<Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013560 data.GetParameter()->Reset();
13561 delete data.GetParameter();
13562}
13563
13564
13565TEST(WeakCallbackApi) {
13566 LocalContext context;
13567 v8::Isolate* isolate = context->GetIsolate();
13568 i::GlobalHandles* globals =
13569 reinterpret_cast<i::Isolate*>(isolate)->global_handles();
13570 int initial_handles = globals->global_handles_count();
13571 {
13572 v8::HandleScope scope(isolate);
13573 v8::Local<v8::Object> obj = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013574 CHECK(
13575 obj->Set(context.local(), v8_str("key"), v8::Integer::New(isolate, 231))
13576 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013577 v8::Persistent<v8::Object>* handle =
13578 new v8::Persistent<v8::Object>(isolate, obj);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013579 handle->SetWeak<v8::Persistent<v8::Object>>(
13580 handle, WeakApiCallback, v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013581 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013582 reinterpret_cast<i::Isolate*>(isolate)->heap()->CollectAllGarbage(
13583 i::Heap::kAbortIncrementalMarkingMask);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013584 // Verify disposed.
13585 CHECK_EQ(initial_handles, globals->global_handles_count());
13586}
13587
13588
Steve Blocka7e24c12009-10-30 11:49:00 +000013589v8::Persistent<v8::Object> some_object;
13590v8::Persistent<v8::Object> bad_handle;
13591
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013592
13593void NewPersistentHandleCallback2(
13594 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013595 v8::HandleScope scope(data.GetIsolate());
13596 bad_handle.Reset(data.GetIsolate(), some_object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013597}
13598
13599
13600void NewPersistentHandleCallback1(
13601 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013602 data.GetParameter()->Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013603 data.SetSecondPassCallback(NewPersistentHandleCallback2);
Steve Blocka7e24c12009-10-30 11:49:00 +000013604}
13605
13606
13607THREADED_TEST(NewPersistentHandleFromWeakCallback) {
13608 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013609 v8::Isolate* isolate = context->GetIsolate();
Steve Blocka7e24c12009-10-30 11:49:00 +000013610
13611 v8::Persistent<v8::Object> handle1, handle2;
13612 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013613 v8::HandleScope scope(isolate);
13614 some_object.Reset(isolate, v8::Object::New(isolate));
13615 handle1.Reset(isolate, v8::Object::New(isolate));
13616 handle2.Reset(isolate, v8::Object::New(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000013617 }
13618 // Note: order is implementation dependent alas: currently
13619 // global handle nodes are processed by PostGarbageCollectionProcessing
13620 // in reverse allocation order, so if second allocated handle is deleted,
13621 // weak callback of the first handle would be able to 'reallocate' it.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013622 handle1.SetWeak(&handle1, NewPersistentHandleCallback1,
13623 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013624 handle2.Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013625 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +000013626}
13627
13628
13629v8::Persistent<v8::Object> to_be_disposed;
13630
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013631
13632void DisposeAndForceGcCallback2(
13633 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013634 to_be_disposed.Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013635 CcTest::heap()->CollectAllGarbage();
13636}
13637
13638
13639void DisposeAndForceGcCallback1(
13640 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013641 data.GetParameter()->Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013642 data.SetSecondPassCallback(DisposeAndForceGcCallback2);
Steve Blocka7e24c12009-10-30 11:49:00 +000013643}
13644
13645
13646THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
13647 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013648 v8::Isolate* isolate = context->GetIsolate();
Steve Blocka7e24c12009-10-30 11:49:00 +000013649
13650 v8::Persistent<v8::Object> handle1, handle2;
13651 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013652 v8::HandleScope scope(isolate);
13653 handle1.Reset(isolate, v8::Object::New(isolate));
13654 handle2.Reset(isolate, v8::Object::New(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000013655 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013656 handle1.SetWeak(&handle1, DisposeAndForceGcCallback1,
13657 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013658 to_be_disposed.Reset(isolate, handle2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013659 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +000013660}
13661
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013662void DisposingCallback(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013663 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013664 data.GetParameter()->Reset();
Steve Blockd0582a62009-12-15 09:54:21 +000013665}
13666
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013667void HandleCreatingCallback2(
13668 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013669 v8::HandleScope scope(data.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013670 v8::Global<v8::Object>(data.GetIsolate(), v8::Object::New(data.GetIsolate()));
13671}
13672
13673
13674void HandleCreatingCallback1(
13675 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013676 data.GetParameter()->Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013677 data.SetSecondPassCallback(HandleCreatingCallback2);
Steve Blockd0582a62009-12-15 09:54:21 +000013678}
13679
13680
13681THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013682 v8::Locker locker(CcTest::isolate());
Steve Blockd0582a62009-12-15 09:54:21 +000013683 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013684 v8::Isolate* isolate = context->GetIsolate();
Steve Blockd0582a62009-12-15 09:54:21 +000013685
13686 v8::Persistent<v8::Object> handle1, handle2, handle3;
13687 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013688 v8::HandleScope scope(isolate);
13689 handle3.Reset(isolate, v8::Object::New(isolate));
13690 handle2.Reset(isolate, v8::Object::New(isolate));
13691 handle1.Reset(isolate, v8::Object::New(isolate));
Steve Blockd0582a62009-12-15 09:54:21 +000013692 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013693 handle2.SetWeak(&handle2, DisposingCallback,
13694 v8::WeakCallbackType::kParameter);
13695 handle3.SetWeak(&handle3, HandleCreatingCallback1,
13696 v8::WeakCallbackType::kParameter);
13697 CcTest::heap()->CollectAllGarbage();
13698 EmptyMessageQueues(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000013699}
13700
Steve Blocka7e24c12009-10-30 11:49:00 +000013701
13702THREADED_TEST(CheckForCrossContextObjectLiterals) {
13703 v8::V8::Initialize();
13704
13705 const int nof = 2;
13706 const char* sources[nof] = {
13707 "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
13708 "Object()"
13709 };
13710
13711 for (int i = 0; i < nof; i++) {
13712 const char* source = sources[i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013713 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013714 LocalContext context;
13715 CompileRun(source);
13716 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013717 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013718 LocalContext context;
13719 CompileRun(source);
13720 }
13721 }
13722}
13723
13724
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013725static v8::Local<Value> NestedScope(v8::Local<Context> env) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013726 v8::EscapableHandleScope inner(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013727 env->Enter();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013728 v8::Local<Value> three = v8_num(3);
13729 v8::Local<Value> value = inner.Escape(three);
Steve Blocka7e24c12009-10-30 11:49:00 +000013730 env->Exit();
13731 return value;
13732}
13733
13734
13735THREADED_TEST(NestedHandleScopeAndContexts) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013736 v8::Isolate* isolate = CcTest::isolate();
13737 v8::HandleScope outer(isolate);
13738 v8::Local<Context> env = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000013739 env->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013740 v8::Local<Value> value = NestedScope(env);
13741 v8::Local<String> str(value->ToString(env).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010013742 CHECK(!str.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000013743 env->Exit();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013744}
13745
13746
13747static bool MatchPointers(void* key1, void* key2) {
13748 return key1 == key2;
13749}
13750
13751
13752struct SymbolInfo {
13753 size_t id;
13754 size_t size;
13755 std::string name;
13756};
13757
13758
13759class SetFunctionEntryHookTest {
13760 public:
13761 SetFunctionEntryHookTest() {
13762 CHECK(instance_ == NULL);
13763 instance_ = this;
13764 }
13765 ~SetFunctionEntryHookTest() {
13766 CHECK(instance_ == this);
13767 instance_ = NULL;
13768 }
13769 void Reset() {
13770 symbols_.clear();
13771 symbol_locations_.clear();
13772 invocations_.clear();
13773 }
13774 void RunTest();
13775 void OnJitEvent(const v8::JitCodeEvent* event);
13776 static void JitEvent(const v8::JitCodeEvent* event) {
13777 CHECK(instance_ != NULL);
13778 instance_->OnJitEvent(event);
13779 }
13780
13781 void OnEntryHook(uintptr_t function,
13782 uintptr_t return_addr_location);
13783 static void EntryHook(uintptr_t function,
13784 uintptr_t return_addr_location) {
13785 CHECK(instance_ != NULL);
13786 instance_->OnEntryHook(function, return_addr_location);
13787 }
13788
13789 static void RuntimeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
13790 CHECK(instance_ != NULL);
13791 args.GetReturnValue().Set(v8_num(42));
13792 }
13793 void RunLoopInNewEnv(v8::Isolate* isolate);
13794
13795 // Records addr as location of symbol.
13796 void InsertSymbolAt(i::Address addr, SymbolInfo* symbol);
13797
13798 // Finds the symbol containing addr
13799 SymbolInfo* FindSymbolForAddr(i::Address addr);
13800 // Returns the number of invocations where the caller name contains
13801 // \p caller_name and the function name contains \p function_name.
13802 int CountInvocations(const char* caller_name,
13803 const char* function_name);
13804
13805 i::Handle<i::JSFunction> foo_func_;
13806 i::Handle<i::JSFunction> bar_func_;
13807
13808 typedef std::map<size_t, SymbolInfo> SymbolMap;
13809 typedef std::map<i::Address, SymbolInfo*> SymbolLocationMap;
13810 typedef std::map<std::pair<SymbolInfo*, SymbolInfo*>, int> InvocationMap;
13811 SymbolMap symbols_;
13812 SymbolLocationMap symbol_locations_;
13813 InvocationMap invocations_;
13814
13815 static SetFunctionEntryHookTest* instance_;
13816};
13817SetFunctionEntryHookTest* SetFunctionEntryHookTest::instance_ = NULL;
13818
13819
13820// Returns true if addr is in the range [start, start+len).
13821static bool Overlaps(i::Address start, size_t len, i::Address addr) {
13822 if (start <= addr && start + len > addr)
13823 return true;
13824
13825 return false;
13826}
13827
13828void SetFunctionEntryHookTest::InsertSymbolAt(i::Address addr,
13829 SymbolInfo* symbol) {
13830 // Insert the symbol at the new location.
13831 SymbolLocationMap::iterator it =
13832 symbol_locations_.insert(std::make_pair(addr, symbol)).first;
13833 // Now erase symbols to the left and right that overlap this one.
13834 while (it != symbol_locations_.begin()) {
13835 SymbolLocationMap::iterator left = it;
13836 --left;
13837 if (!Overlaps(left->first, left->second->size, addr))
13838 break;
13839 symbol_locations_.erase(left);
13840 }
13841
13842 // Now erase symbols to the left and right that overlap this one.
13843 while (true) {
13844 SymbolLocationMap::iterator right = it;
13845 ++right;
13846 if (right == symbol_locations_.end())
13847 break;
13848 if (!Overlaps(addr, symbol->size, right->first))
13849 break;
13850 symbol_locations_.erase(right);
13851 }
13852}
13853
13854
13855void SetFunctionEntryHookTest::OnJitEvent(const v8::JitCodeEvent* event) {
13856 switch (event->type) {
13857 case v8::JitCodeEvent::CODE_ADDED: {
13858 CHECK(event->code_start != NULL);
13859 CHECK_NE(0, static_cast<int>(event->code_len));
13860 CHECK(event->name.str != NULL);
13861 size_t symbol_id = symbols_.size();
13862
13863 // Record the new symbol.
13864 SymbolInfo& info = symbols_[symbol_id];
13865 info.id = symbol_id;
13866 info.size = event->code_len;
13867 info.name.assign(event->name.str, event->name.str + event->name.len);
13868
13869 // And record it's location.
13870 InsertSymbolAt(reinterpret_cast<i::Address>(event->code_start), &info);
13871 }
13872 break;
13873
13874 case v8::JitCodeEvent::CODE_MOVED: {
13875 // We would like to never see code move that we haven't seen before,
13876 // but the code creation event does not happen until the line endings
13877 // have been calculated (this is so that we can report the line in the
13878 // script at which the function source is found, see
13879 // Compiler::RecordFunctionCompilation) and the line endings
13880 // calculations can cause a GC, which can move the newly created code
13881 // before its existence can be logged.
13882 SymbolLocationMap::iterator it(
13883 symbol_locations_.find(
13884 reinterpret_cast<i::Address>(event->code_start)));
13885 if (it != symbol_locations_.end()) {
13886 // Found a symbol at this location, move it.
13887 SymbolInfo* info = it->second;
13888 symbol_locations_.erase(it);
13889 InsertSymbolAt(reinterpret_cast<i::Address>(event->new_code_start),
13890 info);
13891 }
13892 }
13893 default:
13894 break;
13895 }
13896}
13897
13898void SetFunctionEntryHookTest::OnEntryHook(
13899 uintptr_t function, uintptr_t return_addr_location) {
13900 // Get the function's code object.
13901 i::Code* function_code = i::Code::GetCodeFromTargetAddress(
13902 reinterpret_cast<i::Address>(function));
13903 CHECK(function_code != NULL);
13904
13905 // Then try and look up the caller's code object.
13906 i::Address caller = *reinterpret_cast<i::Address*>(return_addr_location);
13907
13908 // Count the invocation.
13909 SymbolInfo* caller_symbol = FindSymbolForAddr(caller);
13910 SymbolInfo* function_symbol =
13911 FindSymbolForAddr(reinterpret_cast<i::Address>(function));
13912 ++invocations_[std::make_pair(caller_symbol, function_symbol)];
13913
13914 if (!bar_func_.is_null() && function_code == bar_func_->code()) {
13915 // Check that we have a symbol for the "bar" function at the right location.
13916 SymbolLocationMap::iterator it(
13917 symbol_locations_.find(function_code->instruction_start()));
13918 CHECK(it != symbol_locations_.end());
13919 }
13920
13921 if (!foo_func_.is_null() && function_code == foo_func_->code()) {
13922 // Check that we have a symbol for "foo" at the right location.
13923 SymbolLocationMap::iterator it(
13924 symbol_locations_.find(function_code->instruction_start()));
13925 CHECK(it != symbol_locations_.end());
13926 }
13927}
13928
13929
13930SymbolInfo* SetFunctionEntryHookTest::FindSymbolForAddr(i::Address addr) {
13931 SymbolLocationMap::iterator it(symbol_locations_.lower_bound(addr));
13932 // Do we have a direct hit on a symbol?
13933 if (it != symbol_locations_.end()) {
13934 if (it->first == addr)
13935 return it->second;
13936 }
13937
13938 // If not a direct hit, it'll have to be the previous symbol.
13939 if (it == symbol_locations_.begin())
13940 return NULL;
13941
13942 --it;
13943 size_t offs = addr - it->first;
13944 if (offs < it->second->size)
13945 return it->second;
13946
13947 return NULL;
13948}
13949
13950
13951int SetFunctionEntryHookTest::CountInvocations(
13952 const char* caller_name, const char* function_name) {
13953 InvocationMap::iterator it(invocations_.begin());
13954 int invocations = 0;
13955 for (; it != invocations_.end(); ++it) {
13956 SymbolInfo* caller = it->first.first;
13957 SymbolInfo* function = it->first.second;
13958
13959 // Filter out non-matching functions.
13960 if (function_name != NULL) {
13961 if (function->name.find(function_name) == std::string::npos)
13962 continue;
13963 }
13964
13965 // Filter out non-matching callers.
13966 if (caller_name != NULL) {
13967 if (caller == NULL)
13968 continue;
13969 if (caller->name.find(caller_name) == std::string::npos)
13970 continue;
13971 }
13972
13973 // It matches add the invocation count to the tally.
13974 invocations += it->second;
13975 }
13976
13977 return invocations;
13978}
13979
13980
13981void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
13982 v8::HandleScope outer(isolate);
13983 v8::Local<Context> env = Context::New(isolate);
13984 env->Enter();
13985
13986 Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
13987 t->Set(v8_str("asdf"), v8::FunctionTemplate::New(isolate, RuntimeCallback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013988 CHECK(env->Global()
13989 ->Set(env, v8_str("obj"), t->NewInstance(env).ToLocalChecked())
13990 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013991
13992 const char* script =
13993 "function bar() {\n"
13994 " var sum = 0;\n"
13995 " for (i = 0; i < 100; ++i)\n"
13996 " sum = foo(i);\n"
13997 " return sum;\n"
13998 "}\n"
13999 "function foo(i) { return i * i; }\n"
14000 "// Invoke on the runtime function.\n"
14001 "obj.asdf()";
14002 CompileRun(script);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014003 bar_func_ = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(
14004 *env->Global()->Get(env, v8_str("bar")).ToLocalChecked()));
14005 CHECK(!bar_func_.is_null());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014006
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014007 foo_func_ = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(
14008 *env->Global()->Get(env, v8_str("foo")).ToLocalChecked()));
14009 CHECK(!foo_func_.is_null());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014010
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014011 v8::Local<v8::Value> value = CompileRun("bar();");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014012 CHECK(value->IsNumber());
14013 CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
14014
14015 // Test the optimized codegen path.
14016 value = CompileRun("%OptimizeFunctionOnNextCall(foo);"
14017 "bar();");
14018 CHECK(value->IsNumber());
14019 CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
14020
14021 env->Exit();
14022}
14023
14024
14025void SetFunctionEntryHookTest::RunTest() {
14026 // Work in a new isolate throughout.
14027 v8::Isolate::CreateParams create_params;
14028 create_params.entry_hook = EntryHook;
14029 create_params.code_event_handler = JitEvent;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014030 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014031 v8::Isolate* isolate = v8::Isolate::New(create_params);
14032
14033 {
14034 v8::Isolate::Scope scope(isolate);
14035
14036 RunLoopInNewEnv(isolate);
14037
14038 // Check the exepected invocation counts.
14039 CHECK_EQ(2, CountInvocations(NULL, "bar"));
14040 CHECK_EQ(200, CountInvocations("bar", "foo"));
14041 CHECK_EQ(200, CountInvocations(NULL, "foo"));
14042
14043 // Verify that we have an entry hook on some specific stubs.
14044 CHECK_NE(0, CountInvocations(NULL, "CEntryStub"));
14045 CHECK_NE(0, CountInvocations(NULL, "JSEntryStub"));
14046 CHECK_NE(0, CountInvocations(NULL, "JSEntryTrampoline"));
14047 }
14048 isolate->Dispose();
14049
14050 Reset();
14051
14052 // Make sure a second isolate is unaffected by the previous entry hook.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014053 create_params = v8::Isolate::CreateParams();
14054 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
14055 isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014056 {
14057 v8::Isolate::Scope scope(isolate);
14058
14059 // Reset the entry count to zero and set the entry hook.
14060 RunLoopInNewEnv(isolate);
14061
14062 // We should record no invocations in this isolate.
14063 CHECK_EQ(0, static_cast<int>(invocations_.size()));
14064 }
14065
14066 isolate->Dispose();
14067}
14068
14069
14070TEST(SetFunctionEntryHook) {
14071 // FunctionEntryHook does not work well with experimental natives.
14072 // Experimental natives are compiled during snapshot deserialization.
14073 // This test breaks because InstallGetter (function from snapshot that
14074 // only gets called from experimental natives) is compiled with entry hooks.
14075 i::FLAG_allow_natives_syntax = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014076 i::FLAG_turbo_inlining = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014077 i::FLAG_use_inlining = false;
14078
14079 SetFunctionEntryHookTest test;
14080 test.RunTest();
14081}
14082
14083
14084static i::HashMap* code_map = NULL;
14085static i::HashMap* jitcode_line_info = NULL;
14086static int saw_bar = 0;
14087static int move_events = 0;
14088
14089
14090static bool FunctionNameIs(const char* expected,
14091 const v8::JitCodeEvent* event) {
14092 // Log lines for functions are of the general form:
14093 // "LazyCompile:<type><function_name>", where the type is one of
14094 // "*", "~" or "".
14095 static const char kPreamble[] = "LazyCompile:";
14096 static size_t kPreambleLen = sizeof(kPreamble) - 1;
14097
14098 if (event->name.len < sizeof(kPreamble) - 1 ||
14099 strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
14100 return false;
14101 }
14102
14103 const char* tail = event->name.str + kPreambleLen;
14104 size_t tail_len = event->name.len - kPreambleLen;
14105 size_t expected_len = strlen(expected);
14106 if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
14107 --tail_len;
14108 ++tail;
14109 }
14110
14111 // Check for tails like 'bar :1'.
14112 if (tail_len > expected_len + 2 &&
14113 tail[expected_len] == ' ' &&
14114 tail[expected_len + 1] == ':' &&
14115 tail[expected_len + 2] &&
14116 !strncmp(tail, expected, expected_len)) {
14117 return true;
14118 }
14119
14120 if (tail_len != expected_len)
14121 return false;
14122
14123 return strncmp(tail, expected, expected_len) == 0;
14124}
14125
14126
14127static void event_handler(const v8::JitCodeEvent* event) {
14128 CHECK(event != NULL);
14129 CHECK(code_map != NULL);
14130 CHECK(jitcode_line_info != NULL);
14131
14132 class DummyJitCodeLineInfo {
14133 };
14134
14135 switch (event->type) {
14136 case v8::JitCodeEvent::CODE_ADDED: {
14137 CHECK(event->code_start != NULL);
14138 CHECK_NE(0, static_cast<int>(event->code_len));
14139 CHECK(event->name.str != NULL);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014140 i::HashMap::Entry* entry = code_map->LookupOrInsert(
14141 event->code_start, i::ComputePointerHash(event->code_start));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014142 entry->value = reinterpret_cast<void*>(event->code_len);
14143
14144 if (FunctionNameIs("bar", event)) {
14145 ++saw_bar;
14146 }
14147 }
14148 break;
14149
14150 case v8::JitCodeEvent::CODE_MOVED: {
14151 uint32_t hash = i::ComputePointerHash(event->code_start);
14152 // We would like to never see code move that we haven't seen before,
14153 // but the code creation event does not happen until the line endings
14154 // have been calculated (this is so that we can report the line in the
14155 // script at which the function source is found, see
14156 // Compiler::RecordFunctionCompilation) and the line endings
14157 // calculations can cause a GC, which can move the newly created code
14158 // before its existence can be logged.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014159 i::HashMap::Entry* entry = code_map->Lookup(event->code_start, hash);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014160 if (entry != NULL) {
14161 ++move_events;
14162
14163 CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
14164 code_map->Remove(event->code_start, hash);
14165
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014166 entry = code_map->LookupOrInsert(
14167 event->new_code_start,
14168 i::ComputePointerHash(event->new_code_start));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014169 entry->value = reinterpret_cast<void*>(event->code_len);
14170 }
14171 }
14172 break;
14173
14174 case v8::JitCodeEvent::CODE_REMOVED:
14175 // Object/code removal events are currently not dispatched from the GC.
14176 CHECK(false);
14177 break;
14178
14179 // For CODE_START_LINE_INFO_RECORDING event, we will create one
14180 // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
14181 // record it in jitcode_line_info.
14182 case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
14183 DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
14184 v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
14185 temp_event->user_data = line_info;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014186 i::HashMap::Entry* entry = jitcode_line_info->LookupOrInsert(
14187 line_info, i::ComputePointerHash(line_info));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014188 entry->value = reinterpret_cast<void*>(line_info);
14189 }
14190 break;
14191 // For these two events, we will check whether the event->user_data
14192 // data structure is created before during CODE_START_LINE_INFO_RECORDING
14193 // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
14194 case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
14195 CHECK(event->user_data != NULL);
14196 uint32_t hash = i::ComputePointerHash(event->user_data);
14197 i::HashMap::Entry* entry =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014198 jitcode_line_info->Lookup(event->user_data, hash);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014199 CHECK(entry != NULL);
14200 delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
14201 }
14202 break;
14203
14204 case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
14205 CHECK(event->user_data != NULL);
14206 uint32_t hash = i::ComputePointerHash(event->user_data);
14207 i::HashMap::Entry* entry =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014208 jitcode_line_info->Lookup(event->user_data, hash);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014209 CHECK(entry != NULL);
14210 }
14211 break;
14212
14213 default:
14214 // Impossible event.
14215 CHECK(false);
14216 break;
14217 }
14218}
14219
14220
14221UNINITIALIZED_TEST(SetJitCodeEventHandler) {
14222 i::FLAG_stress_compaction = true;
14223 i::FLAG_incremental_marking = false;
14224 if (i::FLAG_never_compact) return;
14225 const char* script =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014226 "function bar() {"
14227 " var sum = 0;"
14228 " for (i = 0; i < 10; ++i)"
14229 " sum = foo(i);"
14230 " return sum;"
14231 "}"
14232 "function foo(i) { return i; };"
14233 "bar();";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014234
14235 // Run this test in a new isolate to make sure we don't
14236 // have remnants of state from other code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014237 v8::Isolate::CreateParams create_params;
14238 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
14239 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014240 isolate->Enter();
14241 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
14242 i::Heap* heap = i_isolate->heap();
14243
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014244 // Start with a clean slate.
14245 heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler_Prepare");
14246
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014247 {
14248 v8::HandleScope scope(isolate);
14249 i::HashMap code(MatchPointers);
14250 code_map = &code;
14251
14252 i::HashMap lineinfo(MatchPointers);
14253 jitcode_line_info = &lineinfo;
14254
14255 saw_bar = 0;
14256 move_events = 0;
14257
14258 isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
14259
14260 // Generate new code objects sparsely distributed across several
14261 // different fragmented code-space pages.
14262 const int kIterations = 10;
14263 for (int i = 0; i < kIterations; ++i) {
14264 LocalContext env(isolate);
14265 i::AlwaysAllocateScope always_allocate(i_isolate);
14266 SimulateFullSpace(heap->code_space());
14267 CompileRun(script);
14268
14269 // Keep a strong reference to the code object in the handle scope.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014270 i::Handle<i::Code> bar_code(
14271 i::Handle<i::JSFunction>::cast(
14272 v8::Utils::OpenHandle(*env->Global()
14273 ->Get(env.local(), v8_str("bar"))
14274 .ToLocalChecked()))
14275 ->code());
14276 i::Handle<i::Code> foo_code(
14277 i::Handle<i::JSFunction>::cast(
14278 v8::Utils::OpenHandle(*env->Global()
14279 ->Get(env.local(), v8_str("foo"))
14280 .ToLocalChecked()))
14281 ->code());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014282
14283 // Clear the compilation cache to get more wastage.
14284 reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear();
14285 }
14286
14287 // Force code movement.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014288 heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler_Move");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014289
14290 isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
14291
14292 CHECK_LE(kIterations, saw_bar);
14293 CHECK_LT(0, move_events);
14294
14295 code_map = NULL;
14296 jitcode_line_info = NULL;
14297 }
14298
14299 isolate->Exit();
14300 isolate->Dispose();
14301
14302 // Do this in a new isolate.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014303 isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014304 isolate->Enter();
14305
14306 // Verify that we get callbacks for existing code objects when we
14307 // request enumeration of existing code.
14308 {
14309 v8::HandleScope scope(isolate);
14310 LocalContext env(isolate);
14311 CompileRun(script);
14312
14313 // Now get code through initial iteration.
14314 i::HashMap code(MatchPointers);
14315 code_map = &code;
14316
14317 i::HashMap lineinfo(MatchPointers);
14318 jitcode_line_info = &lineinfo;
14319
14320 isolate->SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting,
14321 event_handler);
14322 isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
14323
14324 jitcode_line_info = NULL;
14325 // We expect that we got some events. Note that if we could get code removal
14326 // notifications, we could compare two collections, one created by listening
14327 // from the time of creation of an isolate, and the other by subscribing
14328 // with EnumExisting.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014329 CHECK_LT(0u, code.occupancy());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014330
14331 code_map = NULL;
14332 }
14333
14334 isolate->Exit();
14335 isolate->Dispose();
Steve Blocka7e24c12009-10-30 11:49:00 +000014336}
14337
14338
14339THREADED_TEST(ExternalAllocatedMemory) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014340 v8::Isolate* isolate = CcTest::isolate();
14341 v8::HandleScope outer(isolate);
14342 v8::Local<Context> env(Context::New(isolate));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010014343 CHECK(!env.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014344 const int64_t kSize = 1024*1024;
14345 int64_t baseline = isolate->AdjustAmountOfExternalAllocatedMemory(0);
14346 CHECK_EQ(baseline + kSize,
14347 isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
14348 CHECK_EQ(baseline,
14349 isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014350 const int64_t kTriggerGCSize =
14351 v8::internal::Internals::kExternalAllocationLimit + 1;
14352 CHECK_EQ(baseline + kTriggerGCSize,
14353 isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize));
14354 CHECK_EQ(baseline,
14355 isolate->AdjustAmountOfExternalAllocatedMemory(-kTriggerGCSize));
14356}
14357
14358
14359TEST(Regress51719) {
14360 i::FLAG_incremental_marking = false;
14361 CcTest::InitializeVM();
14362
14363 const int64_t kTriggerGCSize =
14364 v8::internal::Internals::kExternalAllocationLimit + 1;
14365 v8::Isolate* isolate = CcTest::isolate();
14366 isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize);
Steve Blocka7e24c12009-10-30 11:49:00 +000014367}
14368
14369
14370// Regression test for issue 54, object templates with internal fields
14371// but no accessors or interceptors did not get their internal field
14372// count set on instances.
14373THREADED_TEST(Regress54) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014374 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014375 v8::Isolate* isolate = context->GetIsolate();
14376 v8::HandleScope outer(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000014377 static v8::Persistent<v8::ObjectTemplate> templ;
14378 if (templ.IsEmpty()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014379 v8::EscapableHandleScope inner(isolate);
14380 v8::Local<v8::ObjectTemplate> local = v8::ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000014381 local->SetInternalFieldCount(1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014382 templ.Reset(isolate, inner.Escape(local));
Steve Blocka7e24c12009-10-30 11:49:00 +000014383 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014384 v8::Local<v8::Object> result =
14385 v8::Local<v8::ObjectTemplate>::New(isolate, templ)
14386 ->NewInstance(context.local())
14387 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000014388 CHECK_EQ(1, result->InternalFieldCount());
14389}
14390
14391
14392// If part of the threaded tests, this test makes ThreadingTest fail
14393// on mac.
14394TEST(CatchStackOverflow) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014395 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014396 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014397 v8::TryCatch try_catch(context->GetIsolate());
14398 v8::Local<v8::Value> result = CompileRun(
14399 "function f() {"
14400 " return f();"
14401 "}"
14402 ""
14403 "f();");
Steve Blocka7e24c12009-10-30 11:49:00 +000014404 CHECK(result.IsEmpty());
14405}
14406
14407
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014408static void CheckTryCatchSourceInfo(v8::Local<v8::Script> script,
Steve Blocka7e24c12009-10-30 11:49:00 +000014409 const char* resource_name,
14410 int line_offset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014411 v8::HandleScope scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014412 v8::TryCatch try_catch(CcTest::isolate());
14413 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
14414 CHECK(script->Run(context).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000014415 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014416 v8::Local<v8::Message> message = try_catch.Message();
Steve Blocka7e24c12009-10-30 11:49:00 +000014417 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014418 CHECK_EQ(10 + line_offset, message->GetLineNumber(context).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000014419 CHECK_EQ(91, message->GetStartPosition());
14420 CHECK_EQ(92, message->GetEndPosition());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014421 CHECK_EQ(2, message->GetStartColumn(context).FromJust());
14422 CHECK_EQ(3, message->GetEndColumn(context).FromJust());
14423 v8::String::Utf8Value line(message->GetSourceLine(context).ToLocalChecked());
14424 CHECK_EQ(0, strcmp(" throw 'nirk';", *line));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014425 v8::String::Utf8Value name(message->GetScriptOrigin().ResourceName());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014426 CHECK_EQ(0, strcmp(resource_name, *name));
Steve Blocka7e24c12009-10-30 11:49:00 +000014427}
14428
14429
14430THREADED_TEST(TryCatchSourceInfo) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014431 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014432 v8::HandleScope scope(context->GetIsolate());
14433 v8::Local<v8::String> source = v8_str(
Steve Blocka7e24c12009-10-30 11:49:00 +000014434 "function Foo() {\n"
14435 " return Bar();\n"
14436 "}\n"
14437 "\n"
14438 "function Bar() {\n"
14439 " return Baz();\n"
14440 "}\n"
14441 "\n"
14442 "function Baz() {\n"
14443 " throw 'nirk';\n"
14444 "}\n"
14445 "\n"
14446 "Foo();\n");
14447
14448 const char* resource_name;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014449 v8::Local<v8::Script> script;
Steve Blocka7e24c12009-10-30 11:49:00 +000014450 resource_name = "test.js";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014451 script = CompileWithOrigin(source, resource_name);
Steve Blocka7e24c12009-10-30 11:49:00 +000014452 CheckTryCatchSourceInfo(script, resource_name, 0);
14453
14454 resource_name = "test1.js";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014455 v8::ScriptOrigin origin1(v8_str(resource_name));
14456 script =
14457 v8::Script::Compile(context.local(), source, &origin1).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000014458 CheckTryCatchSourceInfo(script, resource_name, 0);
14459
14460 resource_name = "test2.js";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014461 v8::ScriptOrigin origin2(v8_str(resource_name),
14462 v8::Integer::New(context->GetIsolate(), 7));
14463 script =
14464 v8::Script::Compile(context.local(), source, &origin2).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000014465 CheckTryCatchSourceInfo(script, resource_name, 7);
14466}
14467
14468
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014469THREADED_TEST(TryCatchSourceInfoForEOSError) {
14470 LocalContext context;
14471 v8::HandleScope scope(context->GetIsolate());
14472 v8::TryCatch try_catch(context->GetIsolate());
14473 CHECK(v8::Script::Compile(context.local(), v8_str("!\n")).IsEmpty());
14474 CHECK(try_catch.HasCaught());
14475 v8::Local<v8::Message> message = try_catch.Message();
14476 CHECK_EQ(1, message->GetLineNumber(context.local()).FromJust());
14477 CHECK_EQ(0, message->GetStartColumn(context.local()).FromJust());
14478}
14479
14480
Steve Blocka7e24c12009-10-30 11:49:00 +000014481THREADED_TEST(CompilationCache) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014482 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014483 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014484 v8::Local<v8::String> source0 = v8_str("1234");
14485 v8::Local<v8::String> source1 = v8_str("1234");
14486 v8::Local<v8::Script> script0 = CompileWithOrigin(source0, "test.js");
14487 v8::Local<v8::Script> script1 = CompileWithOrigin(source1, "test.js");
14488 v8::Local<v8::Script> script2 = v8::Script::Compile(context.local(), source0)
14489 .ToLocalChecked(); // different origin
14490 CHECK_EQ(1234, script0->Run(context.local())
14491 .ToLocalChecked()
14492 ->Int32Value(context.local())
14493 .FromJust());
14494 CHECK_EQ(1234, script1->Run(context.local())
14495 .ToLocalChecked()
14496 ->Int32Value(context.local())
14497 .FromJust());
14498 CHECK_EQ(1234, script2->Run(context.local())
14499 .ToLocalChecked()
14500 ->Int32Value(context.local())
14501 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000014502}
14503
14504
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014505static void FunctionNameCallback(
14506 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014507 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014508 args.GetReturnValue().Set(v8_num(42));
Steve Blocka7e24c12009-10-30 11:49:00 +000014509}
14510
14511
14512THREADED_TEST(CallbackFunctionName) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014513 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014514 v8::Isolate* isolate = context->GetIsolate();
14515 v8::HandleScope scope(isolate);
14516 Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
14517 t->Set(v8_str("asdf"),
14518 v8::FunctionTemplate::New(isolate, FunctionNameCallback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014519 CHECK(context->Global()
14520 ->Set(context.local(), v8_str("obj"),
14521 t->NewInstance(context.local()).ToLocalChecked())
14522 .FromJust());
14523 v8::Local<v8::Value> value = CompileRun("obj.asdf.name");
Steve Blocka7e24c12009-10-30 11:49:00 +000014524 CHECK(value->IsString());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014525 v8::String::Utf8Value name(value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014526 CHECK_EQ(0, strcmp("asdf", *name));
Steve Blocka7e24c12009-10-30 11:49:00 +000014527}
14528
14529
14530THREADED_TEST(DateAccess) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014531 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014532 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014533 v8::Local<v8::Value> date =
14534 v8::Date::New(context.local(), 1224744689038.0).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000014535 CHECK(date->IsDate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014536 CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
Steve Blocka7e24c12009-10-30 11:49:00 +000014537}
14538
14539
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014540void CheckProperties(v8::Isolate* isolate, v8::Local<v8::Value> val,
14541 unsigned elmc, const char* elmv[]) {
14542 v8::Local<v8::Context> context = isolate->GetCurrentContext();
14543 v8::Local<v8::Object> obj = val.As<v8::Object>();
14544 v8::Local<v8::Array> props = obj->GetPropertyNames(context).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000014545 CHECK_EQ(elmc, props->Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014546 for (unsigned i = 0; i < elmc; i++) {
14547 v8::String::Utf8Value elm(
14548 props->Get(context, v8::Integer::New(isolate, i)).ToLocalChecked());
14549 CHECK_EQ(0, strcmp(elmv[i], *elm));
Steve Blocka7e24c12009-10-30 11:49:00 +000014550 }
14551}
14552
14553
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014554void CheckOwnProperties(v8::Isolate* isolate, v8::Local<v8::Value> val,
14555 unsigned elmc, const char* elmv[]) {
14556 v8::Local<v8::Context> context = isolate->GetCurrentContext();
14557 v8::Local<v8::Object> obj = val.As<v8::Object>();
14558 v8::Local<v8::Array> props =
14559 obj->GetOwnPropertyNames(context).ToLocalChecked();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000014560 CHECK_EQ(elmc, props->Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014561 for (unsigned i = 0; i < elmc; i++) {
14562 v8::String::Utf8Value elm(
14563 props->Get(context, v8::Integer::New(isolate, i)).ToLocalChecked());
14564 CHECK_EQ(0, strcmp(elmv[i], *elm));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000014565 }
14566}
14567
14568
Steve Blocka7e24c12009-10-30 11:49:00 +000014569THREADED_TEST(PropertyEnumeration) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014570 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014571 v8::Isolate* isolate = context->GetIsolate();
14572 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014573 v8::Local<v8::Value> obj = CompileRun(
Steve Blocka7e24c12009-10-30 11:49:00 +000014574 "var result = [];"
14575 "result[0] = {};"
14576 "result[1] = {a: 1, b: 2};"
14577 "result[2] = [1, 2, 3];"
14578 "var proto = {x: 1, y: 2, z: 3};"
14579 "var x = { __proto__: proto, w: 0, z: 1 };"
14580 "result[3] = x;"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014581 "result;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014582 v8::Local<v8::Array> elms = obj.As<v8::Array>();
14583 CHECK_EQ(4u, elms->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +000014584 int elmc0 = 0;
14585 const char** elmv0 = NULL;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014586 CheckProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014587 isolate,
14588 elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
14589 elmc0, elmv0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014590 CheckOwnProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014591 isolate,
14592 elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
14593 elmc0, elmv0);
Steve Blocka7e24c12009-10-30 11:49:00 +000014594 int elmc1 = 2;
14595 const char* elmv1[] = {"a", "b"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014596 CheckProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014597 isolate,
14598 elms->Get(context.local(), v8::Integer::New(isolate, 1)).ToLocalChecked(),
14599 elmc1, elmv1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014600 CheckOwnProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014601 isolate,
14602 elms->Get(context.local(), v8::Integer::New(isolate, 1)).ToLocalChecked(),
14603 elmc1, elmv1);
Steve Blocka7e24c12009-10-30 11:49:00 +000014604 int elmc2 = 3;
14605 const char* elmv2[] = {"0", "1", "2"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014606 CheckProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014607 isolate,
14608 elms->Get(context.local(), v8::Integer::New(isolate, 2)).ToLocalChecked(),
14609 elmc2, elmv2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014610 CheckOwnProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014611 isolate,
14612 elms->Get(context.local(), v8::Integer::New(isolate, 2)).ToLocalChecked(),
14613 elmc2, elmv2);
Steve Blocka7e24c12009-10-30 11:49:00 +000014614 int elmc3 = 4;
14615 const char* elmv3[] = {"w", "z", "x", "y"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014616 CheckProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014617 isolate,
14618 elms->Get(context.local(), v8::Integer::New(isolate, 3)).ToLocalChecked(),
14619 elmc3, elmv3);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000014620 int elmc4 = 2;
14621 const char* elmv4[] = {"w", "z"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014622 CheckOwnProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014623 isolate,
14624 elms->Get(context.local(), v8::Integer::New(isolate, 3)).ToLocalChecked(),
14625 elmc4, elmv4);
Steve Blocka7e24c12009-10-30 11:49:00 +000014626}
14627
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014628
Steve Block44f0eee2011-05-26 01:26:41 +010014629THREADED_TEST(PropertyEnumeration2) {
Steve Block44f0eee2011-05-26 01:26:41 +010014630 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014631 v8::Isolate* isolate = context->GetIsolate();
14632 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014633 v8::Local<v8::Value> obj = CompileRun(
Steve Block44f0eee2011-05-26 01:26:41 +010014634 "var result = [];"
14635 "result[0] = {};"
14636 "result[1] = {a: 1, b: 2};"
14637 "result[2] = [1, 2, 3];"
14638 "var proto = {x: 1, y: 2, z: 3};"
14639 "var x = { __proto__: proto, w: 0, z: 1 };"
14640 "result[3] = x;"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014641 "result;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014642 v8::Local<v8::Array> elms = obj.As<v8::Array>();
14643 CHECK_EQ(4u, elms->Length());
Steve Block44f0eee2011-05-26 01:26:41 +010014644 int elmc0 = 0;
14645 const char** elmv0 = NULL;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014646 CheckProperties(
14647 isolate,
14648 elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
14649 elmc0, elmv0);
Steve Block44f0eee2011-05-26 01:26:41 +010014650
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014651 v8::Local<v8::Value> val =
14652 elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked();
14653 v8::Local<v8::Array> props =
14654 val.As<v8::Object>()->GetPropertyNames(context.local()).ToLocalChecked();
14655 CHECK_EQ(0u, props->Length());
Steve Block44f0eee2011-05-26 01:26:41 +010014656 for (uint32_t i = 0; i < props->Length(); i++) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040014657 printf("p[%u]\n", i);
Steve Block44f0eee2011-05-26 01:26:41 +010014658 }
14659}
Steve Blocka7e24c12009-10-30 11:49:00 +000014660
Steve Blocka7e24c12009-10-30 11:49:00 +000014661
14662THREADED_TEST(AccessChecksReenabledCorrectly) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014663 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014664 v8::Isolate* isolate = context->GetIsolate();
14665 v8::HandleScope scope(isolate);
14666 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014667 templ->SetAccessCheckCallback(AccessAlwaysBlocked);
Steve Blocka7e24c12009-10-30 11:49:00 +000014668 templ->Set(v8_str("a"), v8_str("a"));
14669 // Add more than 8 (see kMaxFastProperties) properties
14670 // so that the constructor will force copying map.
14671 // Cannot sprintf, gcc complains unsafety.
14672 char buf[4];
14673 for (char i = '0'; i <= '9' ; i++) {
14674 buf[0] = i;
14675 for (char j = '0'; j <= '9'; j++) {
14676 buf[1] = j;
14677 for (char k = '0'; k <= '9'; k++) {
14678 buf[2] = k;
14679 buf[3] = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014680 templ->Set(v8_str(buf), v8::Number::New(isolate, k));
Steve Blocka7e24c12009-10-30 11:49:00 +000014681 }
14682 }
14683 }
14684
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014685 Local<v8::Object> instance_1 =
14686 templ->NewInstance(context.local()).ToLocalChecked();
14687 CHECK(context->Global()
14688 ->Set(context.local(), v8_str("obj_1"), instance_1)
14689 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000014690
14691 Local<Value> value_1 = CompileRun("obj_1.a");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014692 CHECK(value_1.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000014693
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014694 Local<v8::Object> instance_2 =
14695 templ->NewInstance(context.local()).ToLocalChecked();
14696 CHECK(context->Global()
14697 ->Set(context.local(), v8_str("obj_2"), instance_2)
14698 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000014699
14700 Local<Value> value_2 = CompileRun("obj_2.a");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014701 CHECK(value_2.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000014702}
14703
14704
Leon Clarkef7060e22010-06-03 12:02:55 +010014705// Tests that ScriptData can be serialized and deserialized.
14706TEST(PreCompileSerialization) {
14707 v8::V8::Initialize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014708 LocalContext env;
14709 v8::Isolate* isolate = env->GetIsolate();
14710 HandleScope handle_scope(isolate);
Leon Clarkef7060e22010-06-03 12:02:55 +010014711
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014712 i::FLAG_min_preparse_length = 0;
14713 const char* script = "function foo(a) { return a+1; }";
14714 v8::ScriptCompiler::Source source(v8_str(script));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014715 v8::ScriptCompiler::Compile(env.local(), &source,
14716 v8::ScriptCompiler::kProduceParserCache)
14717 .ToLocalChecked();
Leon Clarkef7060e22010-06-03 12:02:55 +010014718 // Serialize.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014719 const v8::ScriptCompiler::CachedData* cd = source.GetCachedData();
14720 i::byte* serialized_data = i::NewArray<i::byte>(cd->length);
14721 i::MemCopy(serialized_data, cd->data, cd->length);
Leon Clarkef7060e22010-06-03 12:02:55 +010014722
14723 // Deserialize.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014724 i::ScriptData* deserialized = new i::ScriptData(serialized_data, cd->length);
Leon Clarkef7060e22010-06-03 12:02:55 +010014725
14726 // Verify that the original is the same as the deserialized.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014727 CHECK_EQ(cd->length, deserialized->length());
14728 CHECK_EQ(0, memcmp(cd->data, deserialized->data(), cd->length));
Leon Clarkef7060e22010-06-03 12:02:55 +010014729
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014730 delete deserialized;
14731 i::DeleteArray(serialized_data);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010014732}
14733
14734
Steve Blocka7e24c12009-10-30 11:49:00 +000014735// This tests that we do not allow dictionary load/call inline caches
14736// to use functions that have not yet been compiled. The potential
14737// problem of loading a function that has not yet been compiled can
14738// arise because we share code between contexts via the compilation
14739// cache.
14740THREADED_TEST(DictionaryICLoadedFunction) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014741 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000014742 // Test LoadIC.
14743 for (int i = 0; i < 2; i++) {
14744 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014745 CHECK(context->Global()
14746 ->Set(context.local(), v8_str("tmp"), v8::True(CcTest::isolate()))
14747 .FromJust());
14748 context->Global()->Delete(context.local(), v8_str("tmp")).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +000014749 CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
14750 }
14751 // Test CallIC.
14752 for (int i = 0; i < 2; i++) {
14753 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014754 CHECK(context->Global()
14755 ->Set(context.local(), v8_str("tmp"), v8::True(CcTest::isolate()))
14756 .FromJust());
14757 context->Global()->Delete(context.local(), v8_str("tmp")).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +000014758 CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
14759 }
14760}
14761
14762
14763// Test that cross-context new calls use the context of the callee to
14764// create the new JavaScript object.
14765THREADED_TEST(CrossContextNew) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014766 v8::Isolate* isolate = CcTest::isolate();
14767 v8::HandleScope scope(isolate);
14768 v8::Local<Context> context0 = Context::New(isolate);
14769 v8::Local<Context> context1 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000014770
14771 // Allow cross-domain access.
14772 Local<String> token = v8_str("<security token>");
14773 context0->SetSecurityToken(token);
14774 context1->SetSecurityToken(token);
14775
14776 // Set an 'x' property on the Object prototype and define a
14777 // constructor function in context0.
14778 context0->Enter();
14779 CompileRun("Object.prototype.x = 42; function C() {};");
14780 context0->Exit();
14781
14782 // Call the constructor function from context0 and check that the
14783 // result has the 'x' property.
14784 context1->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014785 CHECK(context1->Global()
14786 ->Set(context1, v8_str("other"), context0->Global())
14787 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000014788 Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
14789 CHECK(value->IsInt32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014790 CHECK_EQ(42, value->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000014791 context1->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +000014792}
14793
14794
14795// Verify that we can clone an object
14796TEST(ObjectClone) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014797 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014798 v8::Isolate* isolate = env->GetIsolate();
14799 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000014800
14801 const char* sample =
14802 "var rv = {};" \
14803 "rv.alpha = 'hello';" \
14804 "rv.beta = 123;" \
14805 "rv;";
14806
14807 // Create an object, verify basics.
14808 Local<Value> val = CompileRun(sample);
14809 CHECK(val->IsObject());
Steve Block6ded16b2010-05-10 14:33:55 +010014810 Local<v8::Object> obj = val.As<v8::Object>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014811 obj->Set(env.local(), v8_str("gamma"), v8_str("cloneme")).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +000014812
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014813 CHECK(v8_str("hello")
14814 ->Equals(env.local(),
14815 obj->Get(env.local(), v8_str("alpha")).ToLocalChecked())
14816 .FromJust());
14817 CHECK(v8::Integer::New(isolate, 123)
14818 ->Equals(env.local(),
14819 obj->Get(env.local(), v8_str("beta")).ToLocalChecked())
14820 .FromJust());
14821 CHECK(v8_str("cloneme")
14822 ->Equals(env.local(),
14823 obj->Get(env.local(), v8_str("gamma")).ToLocalChecked())
14824 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000014825
14826 // Clone it.
14827 Local<v8::Object> clone = obj->Clone();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014828 CHECK(v8_str("hello")
14829 ->Equals(env.local(),
14830 clone->Get(env.local(), v8_str("alpha")).ToLocalChecked())
14831 .FromJust());
14832 CHECK(v8::Integer::New(isolate, 123)
14833 ->Equals(env.local(),
14834 clone->Get(env.local(), v8_str("beta")).ToLocalChecked())
14835 .FromJust());
14836 CHECK(v8_str("cloneme")
14837 ->Equals(env.local(),
14838 clone->Get(env.local(), v8_str("gamma")).ToLocalChecked())
14839 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000014840
14841 // Set a property on the clone, verify each object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014842 CHECK(clone->Set(env.local(), v8_str("beta"), v8::Integer::New(isolate, 456))
14843 .FromJust());
14844 CHECK(v8::Integer::New(isolate, 123)
14845 ->Equals(env.local(),
14846 obj->Get(env.local(), v8_str("beta")).ToLocalChecked())
14847 .FromJust());
14848 CHECK(v8::Integer::New(isolate, 456)
14849 ->Equals(env.local(),
14850 clone->Get(env.local(), v8_str("beta")).ToLocalChecked())
14851 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000014852}
14853
14854
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014855class OneByteVectorResource : public v8::String::ExternalOneByteStringResource {
Steve Blocka7e24c12009-10-30 11:49:00 +000014856 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014857 explicit OneByteVectorResource(i::Vector<const char> vector)
Steve Blocka7e24c12009-10-30 11:49:00 +000014858 : data_(vector) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014859 virtual ~OneByteVectorResource() {}
Steve Blocka7e24c12009-10-30 11:49:00 +000014860 virtual size_t length() const { return data_.length(); }
14861 virtual const char* data() const { return data_.start(); }
14862 private:
14863 i::Vector<const char> data_;
14864};
14865
14866
14867class UC16VectorResource : public v8::String::ExternalStringResource {
14868 public:
14869 explicit UC16VectorResource(i::Vector<const i::uc16> vector)
14870 : data_(vector) {}
14871 virtual ~UC16VectorResource() {}
14872 virtual size_t length() const { return data_.length(); }
14873 virtual const i::uc16* data() const { return data_.start(); }
14874 private:
14875 i::Vector<const i::uc16> data_;
14876};
14877
14878
14879static void MorphAString(i::String* string,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014880 OneByteVectorResource* one_byte_resource,
Steve Blocka7e24c12009-10-30 11:49:00 +000014881 UC16VectorResource* uc16_resource) {
14882 CHECK(i::StringShape(string).IsExternal());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014883 if (string->IsOneByteRepresentation()) {
14884 // Check old map is not internalized or long.
14885 CHECK(string->map() == CcTest::heap()->external_one_byte_string_map());
Steve Blocka7e24c12009-10-30 11:49:00 +000014886 // Morph external string to be TwoByte string.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014887 string->set_map(CcTest::heap()->external_string_map());
Steve Blocka7e24c12009-10-30 11:49:00 +000014888 i::ExternalTwoByteString* morphed =
14889 i::ExternalTwoByteString::cast(string);
14890 morphed->set_resource(uc16_resource);
14891 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014892 // Check old map is not internalized or long.
14893 CHECK(string->map() == CcTest::heap()->external_string_map());
14894 // Morph external string to be one-byte string.
14895 string->set_map(CcTest::heap()->external_one_byte_string_map());
14896 i::ExternalOneByteString* morphed = i::ExternalOneByteString::cast(string);
14897 morphed->set_resource(one_byte_resource);
Steve Blocka7e24c12009-10-30 11:49:00 +000014898 }
14899}
14900
14901
14902// Test that we can still flatten a string if the components it is built up
14903// from have been turned into 16 bit strings in the mean time.
14904THREADED_TEST(MorphCompositeStringTest) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010014905 char utf_buffer[129];
Steve Blocka7e24c12009-10-30 11:49:00 +000014906 const char* c_string = "Now is the time for all good men"
14907 " to come to the aid of the party";
14908 uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
14909 {
Steve Blocka7e24c12009-10-30 11:49:00 +000014910 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014911 i::Factory* factory = CcTest::i_isolate()->factory();
14912 v8::HandleScope scope(env->GetIsolate());
14913 OneByteVectorResource one_byte_resource(
Steve Blockd0582a62009-12-15 09:54:21 +000014914 i::Vector<const char>(c_string, i::StrLength(c_string)));
Steve Blocka7e24c12009-10-30 11:49:00 +000014915 UC16VectorResource uc16_resource(
Steve Blockd0582a62009-12-15 09:54:21 +000014916 i::Vector<const uint16_t>(two_byte_string,
14917 i::StrLength(c_string)));
Steve Blocka7e24c12009-10-30 11:49:00 +000014918
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014919 Local<String> lhs(
14920 v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
14921 &one_byte_resource).ToHandleChecked()));
14922 Local<String> rhs(
14923 v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
14924 &one_byte_resource).ToHandleChecked()));
Steve Blocka7e24c12009-10-30 11:49:00 +000014925
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014926 CHECK(env->Global()->Set(env.local(), v8_str("lhs"), lhs).FromJust());
14927 CHECK(env->Global()->Set(env.local(), v8_str("rhs"), rhs).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000014928
14929 CompileRun(
14930 "var cons = lhs + rhs;"
14931 "var slice = lhs.substring(1, lhs.length - 1);"
14932 "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
14933
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014934 CHECK(lhs->IsOneByte());
14935 CHECK(rhs->IsOneByte());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010014936
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014937 MorphAString(*v8::Utils::OpenHandle(*lhs), &one_byte_resource,
14938 &uc16_resource);
14939 MorphAString(*v8::Utils::OpenHandle(*rhs), &one_byte_resource,
14940 &uc16_resource);
Steve Blocka7e24c12009-10-30 11:49:00 +000014941
Ben Murdoch3ef787d2012-04-12 10:51:47 +010014942 // This should UTF-8 without flattening, since everything is ASCII.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014943 Local<String> cons =
14944 v8_compile("cons")->Run(env.local()).ToLocalChecked().As<String>();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010014945 CHECK_EQ(128, cons->Utf8Length());
14946 int nchars = -1;
14947 CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
14948 CHECK_EQ(128, nchars);
14949 CHECK_EQ(0, strcmp(
14950 utf_buffer,
14951 "Now is the time for all good men to come to the aid of the party"
14952 "Now is the time for all good men to come to the aid of the party"));
14953
Steve Blocka7e24c12009-10-30 11:49:00 +000014954 // Now do some stuff to make sure the strings are flattened, etc.
14955 CompileRun(
14956 "/[^a-z]/.test(cons);"
14957 "/[^a-z]/.test(slice);"
14958 "/[^a-z]/.test(slice_on_cons);");
14959 const char* expected_cons =
14960 "Now is the time for all good men to come to the aid of the party"
14961 "Now is the time for all good men to come to the aid of the party";
14962 const char* expected_slice =
14963 "ow is the time for all good men to come to the aid of the part";
14964 const char* expected_slice_on_cons =
14965 "ow is the time for all good men to come to the aid of the party"
14966 "Now is the time for all good men to come to the aid of the part";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014967 CHECK(v8_str(expected_cons)
14968 ->Equals(env.local(), env->Global()
14969 ->Get(env.local(), v8_str("cons"))
14970 .ToLocalChecked())
14971 .FromJust());
14972 CHECK(v8_str(expected_slice)
14973 ->Equals(env.local(), env->Global()
14974 ->Get(env.local(), v8_str("slice"))
14975 .ToLocalChecked())
14976 .FromJust());
14977 CHECK(v8_str(expected_slice_on_cons)
14978 ->Equals(env.local(),
14979 env->Global()
14980 ->Get(env.local(), v8_str("slice_on_cons"))
14981 .ToLocalChecked())
14982 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000014983 }
Ben Murdoch3bec4d22010-07-22 14:51:16 +010014984 i::DeleteArray(two_byte_string);
Steve Blocka7e24c12009-10-30 11:49:00 +000014985}
14986
14987
14988TEST(CompileExternalTwoByteSource) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014989 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014990 v8::HandleScope scope(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000014991
14992 // This is a very short list of sources, which currently is to check for a
14993 // regression caused by r2703.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014994 const char* one_byte_sources[] = {
14995 "0.5",
14996 "-0.5", // This mainly testes PushBack in the Scanner.
14997 "--0.5", // This mainly testes PushBack in the Scanner.
14998 NULL};
Steve Blocka7e24c12009-10-30 11:49:00 +000014999
15000 // Compile the sources as external two byte strings.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015001 for (int i = 0; one_byte_sources[i] != NULL; i++) {
15002 uint16_t* two_byte_string = AsciiToTwoByteString(one_byte_sources[i]);
15003 TestResource* uc16_resource = new TestResource(two_byte_string);
15004 v8::Local<v8::String> source =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015005 v8::String::NewExternalTwoByte(context->GetIsolate(), uc16_resource)
15006 .ToLocalChecked();
15007 v8::Script::Compile(context.local(), source).FromMaybe(Local<Script>());
Steve Blocka7e24c12009-10-30 11:49:00 +000015008 }
15009}
15010
15011
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015012#ifndef V8_INTERPRETED_REGEXP
15013
15014struct RegExpInterruptionData {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015015 v8::base::Atomic32 loop_count;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015016 UC16VectorResource* string_resource;
15017 v8::Persistent<v8::String> string;
15018} regexp_interruption_data;
15019
15020
15021class RegExpInterruptionThread : public v8::base::Thread {
Steve Blocka7e24c12009-10-30 11:49:00 +000015022 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015023 explicit RegExpInterruptionThread(v8::Isolate* isolate)
15024 : Thread(Options("TimeoutThread")), isolate_(isolate) {}
Steve Blocka7e24c12009-10-30 11:49:00 +000015025
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015026 virtual void Run() {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015027 for (v8::base::NoBarrier_Store(&regexp_interruption_data.loop_count, 0);
15028 v8::base::NoBarrier_Load(&regexp_interruption_data.loop_count) < 7;
15029 v8::base::NoBarrier_AtomicIncrement(
15030 &regexp_interruption_data.loop_count, 1)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015031 // Wait a bit before requesting GC.
15032 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015033 reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
Steve Blocka7e24c12009-10-30 11:49:00 +000015034 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015035 // Wait a bit before terminating.
15036 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
15037 isolate_->TerminateExecution();
Steve Blocka7e24c12009-10-30 11:49:00 +000015038 }
Steve Blocka7e24c12009-10-30 11:49:00 +000015039
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000015040 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015041 v8::Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +000015042};
15043
15044
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015045void RunBeforeGC(v8::Isolate* isolate, v8::GCType type,
15046 v8::GCCallbackFlags flags) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015047 if (v8::base::NoBarrier_Load(&regexp_interruption_data.loop_count) != 2) {
15048 return;
15049 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015050 v8::HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015051 v8::Local<v8::String> string = v8::Local<v8::String>::New(
15052 CcTest::isolate(), regexp_interruption_data.string);
15053 string->MakeExternal(regexp_interruption_data.string_resource);
Steve Blocka7e24c12009-10-30 11:49:00 +000015054}
15055
15056
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015057// Test that RegExp execution can be interrupted. Specifically, we test
15058// * interrupting with GC
15059// * turn the subject string from one-byte internal to two-byte external string
15060// * force termination
15061TEST(RegExpInterruption) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015062 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015063 v8::HandleScope scope(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015064
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015065 RegExpInterruptionThread timeout_thread(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015066
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015067 env->GetIsolate()->AddGCPrologueCallback(RunBeforeGC);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015068 static const char* one_byte_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
15069 i::uc16* uc16_content = AsciiToTwoByteString(one_byte_content);
15070 v8::Local<v8::String> string = v8_str(one_byte_content);
15071
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015072 env->Global()->Set(env.local(), v8_str("a"), string).FromJust();
15073 regexp_interruption_data.string.Reset(env->GetIsolate(), string);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015074 regexp_interruption_data.string_resource = new UC16VectorResource(
15075 i::Vector<const i::uc16>(uc16_content, i::StrLength(one_byte_content)));
15076
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015077 v8::TryCatch try_catch(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015078 timeout_thread.Start();
15079
15080 CompileRun("/((a*)*)*b/.exec(a)");
15081 CHECK(try_catch.HasTerminated());
15082
15083 timeout_thread.Join();
15084
15085 regexp_interruption_data.string.Reset();
15086 i::DeleteArray(uc16_content);
15087}
15088
15089#endif // V8_INTERPRETED_REGEXP
15090
15091
15092// Test that we cannot set a property on the global object if there
Steve Blocka7e24c12009-10-30 11:49:00 +000015093// is a read-only property in the prototype chain.
15094TEST(ReadOnlyPropertyInGlobalProto) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015095 v8::Isolate* isolate = CcTest::isolate();
15096 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015097 v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000015098 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015099 v8::Local<v8::Object> global = context->Global();
15100 v8::Local<v8::Object> global_proto = v8::Local<v8::Object>::Cast(
15101 global->Get(context.local(), v8_str("__proto__")).ToLocalChecked());
15102 global_proto->DefineOwnProperty(context.local(), v8_str("x"),
15103 v8::Integer::New(isolate, 0), v8::ReadOnly)
15104 .FromJust();
15105 global_proto->DefineOwnProperty(context.local(), v8_str("y"),
15106 v8::Integer::New(isolate, 0), v8::ReadOnly)
15107 .FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +000015108 // Check without 'eval' or 'with'.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015109 v8::Local<v8::Value> res =
Steve Blocka7e24c12009-10-30 11:49:00 +000015110 CompileRun("function f() { x = 42; return x; }; f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015111 CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015112 // Check with 'eval'.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015113 res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015114 CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015115 // Check with 'with'.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015116 res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015117 CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015118}
15119
Steve Blocka7e24c12009-10-30 11:49:00 +000015120
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015121TEST(CreateDataProperty) {
15122 LocalContext env;
15123 v8::Isolate* isolate = env->GetIsolate();
15124 v8::HandleScope handle_scope(isolate);
15125
15126 CompileRun(
15127 "var a = {};"
15128 "var b = [];"
15129 "Object.defineProperty(a, 'foo', {value: 23});"
15130 "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
15131
15132 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
15133 env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
15134 v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(
15135 env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
15136 {
15137 // Can't change a non-configurable properties.
15138 v8::TryCatch try_catch(isolate);
15139 CHECK(!obj->CreateDataProperty(env.local(), v8_str("foo"),
15140 v8::Integer::New(isolate, 42)).FromJust());
15141 CHECK(!try_catch.HasCaught());
15142 CHECK(obj->CreateDataProperty(env.local(), v8_str("bar"),
15143 v8::Integer::New(isolate, 42)).FromJust());
15144 CHECK(!try_catch.HasCaught());
15145 v8::Local<v8::Value> val =
15146 obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
15147 CHECK(val->IsNumber());
15148 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015149 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015150
15151 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015152 // Set a regular property.
15153 v8::TryCatch try_catch(isolate);
15154 CHECK(obj->CreateDataProperty(env.local(), v8_str("blub"),
15155 v8::Integer::New(isolate, 42)).FromJust());
15156 CHECK(!try_catch.HasCaught());
15157 v8::Local<v8::Value> val =
15158 obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
15159 CHECK(val->IsNumber());
15160 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15161 }
15162
15163 {
15164 // Set an indexed property.
15165 v8::TryCatch try_catch(isolate);
15166 CHECK(obj->CreateDataProperty(env.local(), v8_str("1"),
15167 v8::Integer::New(isolate, 42)).FromJust());
15168 CHECK(!try_catch.HasCaught());
15169 v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
15170 CHECK(val->IsNumber());
15171 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15172 }
15173
15174 {
15175 // Special cases for arrays.
15176 v8::TryCatch try_catch(isolate);
15177 CHECK(!arr->CreateDataProperty(env.local(), v8_str("length"),
15178 v8::Integer::New(isolate, 1)).FromJust());
15179 CHECK(!try_catch.HasCaught());
15180 }
15181 {
15182 // Special cases for arrays: index exceeds the array's length
15183 v8::TryCatch try_catch(isolate);
15184 CHECK(arr->CreateDataProperty(env.local(), 1, v8::Integer::New(isolate, 23))
15185 .FromJust());
15186 CHECK(!try_catch.HasCaught());
15187 CHECK_EQ(2U, arr->Length());
15188 v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
15189 CHECK(val->IsNumber());
15190 CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
15191
15192 // Set an existing entry.
15193 CHECK(arr->CreateDataProperty(env.local(), 0, v8::Integer::New(isolate, 42))
15194 .FromJust());
15195 CHECK(!try_catch.HasCaught());
15196 val = arr->Get(env.local(), 0).ToLocalChecked();
15197 CHECK(val->IsNumber());
15198 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15199 }
15200
15201 CompileRun("Object.freeze(a);");
15202 {
15203 // Can't change non-extensible objects.
15204 v8::TryCatch try_catch(isolate);
15205 CHECK(!obj->CreateDataProperty(env.local(), v8_str("baz"),
15206 v8::Integer::New(isolate, 42)).FromJust());
15207 CHECK(!try_catch.HasCaught());
15208 }
15209
15210 v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
15211 templ->SetAccessCheckCallback(AccessAlwaysBlocked);
15212 v8::Local<v8::Object> access_checked =
15213 templ->NewInstance(env.local()).ToLocalChecked();
15214 {
15215 v8::TryCatch try_catch(isolate);
15216 CHECK(access_checked->CreateDataProperty(env.local(), v8_str("foo"),
15217 v8::Integer::New(isolate, 42))
15218 .IsNothing());
15219 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015220 }
15221}
15222
15223
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015224TEST(DefineOwnProperty) {
15225 LocalContext env;
15226 v8::Isolate* isolate = env->GetIsolate();
15227 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000015228
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015229 CompileRun(
15230 "var a = {};"
15231 "var b = [];"
15232 "Object.defineProperty(a, 'foo', {value: 23});"
15233 "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
Steve Blocka7e24c12009-10-30 11:49:00 +000015234
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015235 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
15236 env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
15237 v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(
15238 env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
15239 {
15240 // Can't change a non-configurable properties.
15241 v8::TryCatch try_catch(isolate);
15242 CHECK(!obj->DefineOwnProperty(env.local(), v8_str("foo"),
15243 v8::Integer::New(isolate, 42)).FromJust());
15244 CHECK(!try_catch.HasCaught());
15245 CHECK(obj->DefineOwnProperty(env.local(), v8_str("bar"),
15246 v8::Integer::New(isolate, 42)).FromJust());
15247 CHECK(!try_catch.HasCaught());
15248 v8::Local<v8::Value> val =
15249 obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
15250 CHECK(val->IsNumber());
15251 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15252 }
15253
15254 {
15255 // Set a regular property.
15256 v8::TryCatch try_catch(isolate);
15257 CHECK(obj->DefineOwnProperty(env.local(), v8_str("blub"),
15258 v8::Integer::New(isolate, 42)).FromJust());
15259 CHECK(!try_catch.HasCaught());
15260 v8::Local<v8::Value> val =
15261 obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
15262 CHECK(val->IsNumber());
15263 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15264 }
15265
15266 {
15267 // Set an indexed property.
15268 v8::TryCatch try_catch(isolate);
15269 CHECK(obj->DefineOwnProperty(env.local(), v8_str("1"),
15270 v8::Integer::New(isolate, 42)).FromJust());
15271 CHECK(!try_catch.HasCaught());
15272 v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
15273 CHECK(val->IsNumber());
15274 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15275 }
15276
15277 {
15278 // Special cases for arrays.
15279 v8::TryCatch try_catch(isolate);
15280 CHECK(!arr->DefineOwnProperty(env.local(), v8_str("length"),
15281 v8::Integer::New(isolate, 1)).FromJust());
15282 CHECK(!try_catch.HasCaught());
15283 }
15284 {
15285 // Special cases for arrays: index exceeds the array's length
15286 v8::TryCatch try_catch(isolate);
15287 CHECK(arr->DefineOwnProperty(env.local(), v8_str("1"),
15288 v8::Integer::New(isolate, 23)).FromJust());
15289 CHECK(!try_catch.HasCaught());
15290 CHECK_EQ(2U, arr->Length());
15291 v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
15292 CHECK(val->IsNumber());
15293 CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
15294
15295 // Set an existing entry.
15296 CHECK(arr->DefineOwnProperty(env.local(), v8_str("0"),
15297 v8::Integer::New(isolate, 42)).FromJust());
15298 CHECK(!try_catch.HasCaught());
15299 val = arr->Get(env.local(), 0).ToLocalChecked();
15300 CHECK(val->IsNumber());
15301 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15302 }
15303
15304 {
15305 // Set a non-writable property.
15306 v8::TryCatch try_catch(isolate);
15307 CHECK(obj->DefineOwnProperty(env.local(), v8_str("lala"),
15308 v8::Integer::New(isolate, 42),
15309 v8::ReadOnly).FromJust());
15310 CHECK(!try_catch.HasCaught());
15311 v8::Local<v8::Value> val =
15312 obj->Get(env.local(), v8_str("lala")).ToLocalChecked();
15313 CHECK(val->IsNumber());
15314 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15315 CHECK_EQ(v8::ReadOnly, obj->GetPropertyAttributes(
15316 env.local(), v8_str("lala")).FromJust());
15317 CHECK(!try_catch.HasCaught());
15318 }
15319
15320 CompileRun("Object.freeze(a);");
15321 {
15322 // Can't change non-extensible objects.
15323 v8::TryCatch try_catch(isolate);
15324 CHECK(!obj->DefineOwnProperty(env.local(), v8_str("baz"),
15325 v8::Integer::New(isolate, 42)).FromJust());
15326 CHECK(!try_catch.HasCaught());
15327 }
15328
15329 v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
15330 templ->SetAccessCheckCallback(AccessAlwaysBlocked);
15331 v8::Local<v8::Object> access_checked =
15332 templ->NewInstance(env.local()).ToLocalChecked();
15333 {
15334 v8::TryCatch try_catch(isolate);
15335 CHECK(access_checked->DefineOwnProperty(env.local(), v8_str("foo"),
15336 v8::Integer::New(isolate, 42))
15337 .IsNothing());
15338 CHECK(try_catch.HasCaught());
15339 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015340}
15341
15342
15343THREADED_TEST(GetCurrentContextWhenNotInContext) {
15344 i::Isolate* isolate = CcTest::i_isolate();
15345 CHECK(isolate != NULL);
15346 CHECK(isolate->context() == NULL);
15347 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
15348 v8::HandleScope scope(v8_isolate);
15349 // The following should not crash, but return an empty handle.
15350 v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
15351 CHECK(current.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000015352}
15353
15354
Steve Blocka7e24c12009-10-30 11:49:00 +000015355// Check that a variable declaration with no explicit initialization
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015356// value does shadow an existing property in the prototype chain.
Steve Blocka7e24c12009-10-30 11:49:00 +000015357THREADED_TEST(InitGlobalVarInProtoChain) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015358 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015359 v8::HandleScope scope(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000015360 // Introduce a variable in the prototype chain.
15361 CompileRun("__proto__.x = 42");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015362 v8::Local<v8::Value> result = CompileRun("var x = 43; x");
Steve Blocka7e24c12009-10-30 11:49:00 +000015363 CHECK(!result->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015364 CHECK_EQ(43, result->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015365}
15366
15367
15368// Regression test for issue 398.
15369// If a function is added to an object, creating a constant function
15370// field, and the result is cloned, replacing the constant function on the
15371// original should not affect the clone.
15372// See http://code.google.com/p/v8/issues/detail?id=398
15373THREADED_TEST(ReplaceConstantFunction) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015374 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015375 v8::Isolate* isolate = context->GetIsolate();
15376 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015377 v8::Local<v8::Object> obj = v8::Object::New(isolate);
15378 v8::Local<v8::FunctionTemplate> func_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015379 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015380 v8::Local<v8::String> foo_string = v8_str("foo");
15381 obj->Set(context.local(), foo_string,
15382 func_templ->GetFunction(context.local()).ToLocalChecked())
15383 .FromJust();
15384 v8::Local<v8::Object> obj_clone = obj->Clone();
15385 obj_clone->Set(context.local(), foo_string, v8_str("Hello")).FromJust();
15386 CHECK(!obj->Get(context.local(), foo_string).ToLocalChecked()->IsUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +000015387}
15388
15389
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015390static void CheckElementValue(i::Isolate* isolate,
15391 int expected,
15392 i::Handle<i::Object> obj,
15393 int offset) {
15394 i::Object* element =
15395 *i::Object::GetElement(isolate, obj, offset).ToHandleChecked();
15396 CHECK_EQ(expected, i::Smi::cast(element)->value());
Steve Blocka7e24c12009-10-30 11:49:00 +000015397}
15398
15399
Steve Block3ce2e202009-11-05 08:53:23 +000015400template <class ExternalArrayClass, class ElementType>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015401static void ObjectWithExternalArrayTestHelper(Local<Context> context,
15402 v8::Local<Object> obj,
15403 int element_count,
15404 i::ExternalArrayType array_type,
15405 int64_t low, int64_t high) {
15406 i::Handle<i::JSReceiver> jsobj = v8::Utils::OpenHandle(*obj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015407 i::Isolate* isolate = jsobj->GetIsolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015408 obj->Set(context, v8_str("field"),
15409 v8::Int32::New(reinterpret_cast<v8::Isolate*>(isolate), 1503))
15410 .FromJust();
15411 CHECK(context->Global()->Set(context, v8_str("ext_array"), obj).FromJust());
15412 v8::Local<v8::Value> result = CompileRun("ext_array.field");
15413 CHECK_EQ(1503, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015414 result = CompileRun("ext_array[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015415 CHECK_EQ(1, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015416
Steve Block3ce2e202009-11-05 08:53:23 +000015417 // Check assigned smis
15418 result = CompileRun("for (var i = 0; i < 8; i++) {"
15419 " ext_array[i] = i;"
15420 "}"
15421 "var sum = 0;"
15422 "for (var i = 0; i < 8; i++) {"
15423 " sum += ext_array[i];"
15424 "}"
15425 "sum;");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015426
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015427 CHECK_EQ(28, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015428 // Check pass through of assigned smis
15429 result = CompileRun("var sum = 0;"
15430 "for (var i = 0; i < 8; i++) {"
15431 " sum += ext_array[i] = ext_array[i] = -i;"
15432 "}"
15433 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015434 CHECK_EQ(-28, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015435
Steve Block3ce2e202009-11-05 08:53:23 +000015436
15437 // Check assigned smis in reverse order
15438 result = CompileRun("for (var i = 8; --i >= 0; ) {"
15439 " ext_array[i] = i;"
15440 "}"
15441 "var sum = 0;"
15442 "for (var i = 0; i < 8; i++) {"
15443 " sum += ext_array[i];"
15444 "}"
15445 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015446 CHECK_EQ(28, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015447
15448 // Check pass through of assigned HeapNumbers
15449 result = CompileRun("var sum = 0;"
15450 "for (var i = 0; i < 16; i+=2) {"
15451 " sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
15452 "}"
15453 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015454 CHECK_EQ(-28, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015455
15456 // Check assigned HeapNumbers
15457 result = CompileRun("for (var i = 0; i < 16; i+=2) {"
15458 " ext_array[i] = (i * 0.5);"
15459 "}"
15460 "var sum = 0;"
15461 "for (var i = 0; i < 16; i+=2) {"
15462 " sum += ext_array[i];"
15463 "}"
15464 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015465 CHECK_EQ(28, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015466
15467 // Check assigned HeapNumbers in reverse order
15468 result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
15469 " ext_array[i] = (i * 0.5);"
15470 "}"
15471 "var sum = 0;"
15472 "for (var i = 0; i < 16; i+=2) {"
15473 " sum += ext_array[i];"
15474 "}"
15475 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015476 CHECK_EQ(28, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015477
15478 i::ScopedVector<char> test_buf(1024);
15479
15480 // Check legal boundary conditions.
15481 // The repeated loads and stores ensure the ICs are exercised.
15482 const char* boundary_program =
15483 "var res = 0;"
15484 "for (var i = 0; i < 16; i++) {"
15485 " ext_array[i] = %lld;"
15486 " if (i > 8) {"
15487 " res = ext_array[i];"
15488 " }"
15489 "}"
15490 "res;";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015491 i::SNPrintF(test_buf,
15492 boundary_program,
15493 low);
Steve Block3ce2e202009-11-05 08:53:23 +000015494 result = CompileRun(test_buf.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015495 CHECK_EQ(low, result->IntegerValue(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015496
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015497 i::SNPrintF(test_buf,
15498 boundary_program,
15499 high);
Steve Block3ce2e202009-11-05 08:53:23 +000015500 result = CompileRun(test_buf.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015501 CHECK_EQ(high, result->IntegerValue(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015502
15503 // Check misprediction of type in IC.
15504 result = CompileRun("var tmp_array = ext_array;"
15505 "var sum = 0;"
15506 "for (var i = 0; i < 8; i++) {"
15507 " tmp_array[i] = i;"
15508 " sum += tmp_array[i];"
15509 " if (i == 4) {"
15510 " tmp_array = {};"
15511 " }"
15512 "}"
15513 "sum;");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010015514 // Force GC to trigger verification.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015515 CcTest::heap()->CollectAllGarbage();
15516 CHECK_EQ(28, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015517
15518 // Make sure out-of-range loads do not throw.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015519 i::SNPrintF(test_buf,
15520 "var caught_exception = false;"
15521 "try {"
15522 " ext_array[%d];"
15523 "} catch (e) {"
15524 " caught_exception = true;"
15525 "}"
15526 "caught_exception;",
15527 element_count);
Steve Block3ce2e202009-11-05 08:53:23 +000015528 result = CompileRun(test_buf.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015529 CHECK_EQ(false, result->BooleanValue(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015530
15531 // Make sure out-of-range stores do not throw.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015532 i::SNPrintF(test_buf,
15533 "var caught_exception = false;"
15534 "try {"
15535 " ext_array[%d] = 1;"
15536 "} catch (e) {"
15537 " caught_exception = true;"
15538 "}"
15539 "caught_exception;",
15540 element_count);
Steve Block3ce2e202009-11-05 08:53:23 +000015541 result = CompileRun(test_buf.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015542 CHECK_EQ(false, result->BooleanValue(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015543
15544 // Check other boundary conditions, values and operations.
15545 result = CompileRun("for (var i = 0; i < 8; i++) {"
15546 " ext_array[7] = undefined;"
15547 "}"
15548 "ext_array[7];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015549 CHECK_EQ(0, result->Int32Value(context).FromJust());
15550 if (array_type == i::kExternalFloat64Array ||
15551 array_type == i::kExternalFloat32Array) {
15552 CHECK(std::isnan(
15553 i::Object::GetElement(isolate, jsobj, 7).ToHandleChecked()->Number()));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010015554 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015555 CheckElementValue(isolate, 0, jsobj, 7);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010015556 }
Steve Block3ce2e202009-11-05 08:53:23 +000015557
15558 result = CompileRun("for (var i = 0; i < 8; i++) {"
15559 " ext_array[6] = '2.3';"
15560 "}"
15561 "ext_array[6];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015562 CHECK_EQ(2, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015563 CHECK_EQ(2,
15564 static_cast<int>(
15565 i::Object::GetElement(
15566 isolate, jsobj, 6).ToHandleChecked()->Number()));
Steve Block3ce2e202009-11-05 08:53:23 +000015567
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015568 if (array_type != i::kExternalFloat32Array &&
15569 array_type != i::kExternalFloat64Array) {
Steve Block3ce2e202009-11-05 08:53:23 +000015570 // Though the specification doesn't state it, be explicit about
15571 // converting NaNs and +/-Infinity to zero.
15572 result = CompileRun("for (var i = 0; i < 8; i++) {"
15573 " ext_array[i] = 5;"
15574 "}"
15575 "for (var i = 0; i < 8; i++) {"
15576 " ext_array[i] = NaN;"
15577 "}"
15578 "ext_array[5];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015579 CHECK_EQ(0, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015580 CheckElementValue(isolate, 0, jsobj, 5);
Steve Block3ce2e202009-11-05 08:53:23 +000015581
15582 result = CompileRun("for (var i = 0; i < 8; i++) {"
15583 " ext_array[i] = 5;"
15584 "}"
15585 "for (var i = 0; i < 8; i++) {"
15586 " ext_array[i] = Infinity;"
15587 "}"
15588 "ext_array[5];");
Steve Block44f0eee2011-05-26 01:26:41 +010015589 int expected_value =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015590 (array_type == i::kExternalUint8ClampedArray) ? 255 : 0;
15591 CHECK_EQ(expected_value, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015592 CheckElementValue(isolate, expected_value, jsobj, 5);
Steve Block3ce2e202009-11-05 08:53:23 +000015593
15594 result = CompileRun("for (var i = 0; i < 8; i++) {"
15595 " ext_array[i] = 5;"
15596 "}"
15597 "for (var i = 0; i < 8; i++) {"
15598 " ext_array[i] = -Infinity;"
15599 "}"
15600 "ext_array[5];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015601 CHECK_EQ(0, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015602 CheckElementValue(isolate, 0, jsobj, 5);
Steve Block1e0659c2011-05-24 12:43:12 +010015603
15604 // Check truncation behavior of integral arrays.
15605 const char* unsigned_data =
15606 "var source_data = [0.6, 10.6];"
15607 "var expected_results = [0, 10];";
15608 const char* signed_data =
15609 "var source_data = [0.6, 10.6, -0.6, -10.6];"
15610 "var expected_results = [0, 10, 0, -10];";
Steve Block44f0eee2011-05-26 01:26:41 +010015611 const char* pixel_data =
15612 "var source_data = [0.6, 10.6];"
15613 "var expected_results = [1, 11];";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015614 bool is_unsigned = (array_type == i::kExternalUint8Array ||
15615 array_type == i::kExternalUint16Array ||
15616 array_type == i::kExternalUint32Array);
15617 bool is_pixel_data = array_type == i::kExternalUint8ClampedArray;
Steve Block1e0659c2011-05-24 12:43:12 +010015618
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015619 i::SNPrintF(test_buf,
15620 "%s"
15621 "var all_passed = true;"
15622 "for (var i = 0; i < source_data.length; i++) {"
15623 " for (var j = 0; j < 8; j++) {"
15624 " ext_array[j] = source_data[i];"
15625 " }"
15626 " all_passed = all_passed &&"
15627 " (ext_array[5] == expected_results[i]);"
15628 "}"
15629 "all_passed;",
15630 (is_unsigned ?
15631 unsigned_data :
15632 (is_pixel_data ? pixel_data : signed_data)));
Steve Block1e0659c2011-05-24 12:43:12 +010015633 result = CompileRun(test_buf.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015634 CHECK_EQ(true, result->BooleanValue(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015635 }
15636
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015637 i::Handle<ExternalArrayClass> array(ExternalArrayClass::cast(
15638 i::Handle<i::JSObject>::cast(jsobj)->elements()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015639 for (int i = 0; i < element_count; i++) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010015640 array->set(i, static_cast<ElementType>(i));
15641 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015642
Ben Murdoch8b112d22011-06-08 16:22:53 +010015643 // Test complex assignments
15644 result = CompileRun("function ee_op_test_complex_func(sum) {"
15645 " for (var i = 0; i < 40; ++i) {"
15646 " sum += (ext_array[i] += 1);"
15647 " sum += (ext_array[i] -= 1);"
15648 " } "
15649 " return sum;"
15650 "}"
15651 "sum=0;"
15652 "for (var i=0;i<10000;++i) {"
15653 " sum=ee_op_test_complex_func(sum);"
15654 "}"
15655 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015656 CHECK_EQ(16000000, result->Int32Value(context).FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010015657
15658 // Test count operations
15659 result = CompileRun("function ee_op_test_count_func(sum) {"
15660 " for (var i = 0; i < 40; ++i) {"
15661 " sum += (++ext_array[i]);"
15662 " sum += (--ext_array[i]);"
15663 " } "
15664 " return sum;"
15665 "}"
15666 "sum=0;"
15667 "for (var i=0;i<10000;++i) {"
15668 " sum=ee_op_test_count_func(sum);"
15669 "}"
15670 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015671 CHECK_EQ(16000000, result->Int32Value(context).FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010015672
Steve Block3ce2e202009-11-05 08:53:23 +000015673 result = CompileRun("ext_array[3] = 33;"
15674 "delete ext_array[3];"
15675 "ext_array[3];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015676 CHECK_EQ(33, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015677
15678 result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
15679 "ext_array[2] = 12; ext_array[3] = 13;"
15680 "ext_array.__defineGetter__('2',"
15681 "function() { return 120; });"
15682 "ext_array[2];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015683 CHECK_EQ(12, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015684
15685 result = CompileRun("var js_array = new Array(40);"
15686 "js_array[0] = 77;"
15687 "js_array;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015688 CHECK_EQ(77, v8::Object::Cast(*result)
15689 ->Get(context, v8_str("0"))
15690 .ToLocalChecked()
15691 ->Int32Value(context)
15692 .FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015693
15694 result = CompileRun("ext_array[1] = 23;"
15695 "ext_array.__proto__ = [];"
15696 "js_array.__proto__ = ext_array;"
15697 "js_array.concat(ext_array);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015698 CHECK_EQ(77, v8::Object::Cast(*result)
15699 ->Get(context, v8_str("0"))
15700 .ToLocalChecked()
15701 ->Int32Value(context)
15702 .FromJust());
15703 CHECK_EQ(23, v8::Object::Cast(*result)
15704 ->Get(context, v8_str("1"))
15705 .ToLocalChecked()
15706 ->Int32Value(context)
15707 .FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015708
15709 result = CompileRun("ext_array[1] = 23;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015710 CHECK_EQ(23, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015711}
15712
15713
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015714template <class FixedTypedArrayClass, i::ElementsKind elements_kind,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015715 class ElementType>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015716static void FixedTypedArrayTestHelper(i::ExternalArrayType array_type,
15717 ElementType low, ElementType high) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015718 i::FLAG_allow_natives_syntax = true;
15719 LocalContext context;
15720 i::Isolate* isolate = CcTest::i_isolate();
15721 i::Factory* factory = isolate->factory();
15722 v8::HandleScope scope(context->GetIsolate());
15723 const int kElementCount = 260;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015724 i::Handle<i::JSTypedArray> jsobj =
15725 factory->NewJSTypedArray(elements_kind, kElementCount);
15726 i::Handle<FixedTypedArrayClass> fixed_array(
15727 FixedTypedArrayClass::cast(jsobj->elements()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015728 CHECK_EQ(FixedTypedArrayClass::kInstanceType,
15729 fixed_array->map()->instance_type());
15730 CHECK_EQ(kElementCount, fixed_array->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015731 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015732 for (int i = 0; i < kElementCount; i++) {
15733 fixed_array->set(i, static_cast<ElementType>(i));
15734 }
15735 // Force GC to trigger verification.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015736 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015737 for (int i = 0; i < kElementCount; i++) {
15738 CHECK_EQ(static_cast<int64_t>(static_cast<ElementType>(i)),
15739 static_cast<int64_t>(fixed_array->get_scalar(i)));
15740 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015741 v8::Local<v8::Object> obj = v8::Utils::ToLocal(jsobj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015742
15743 ObjectWithExternalArrayTestHelper<FixedTypedArrayClass, ElementType>(
15744 context.local(), obj, kElementCount, array_type,
15745 static_cast<int64_t>(low),
15746 static_cast<int64_t>(high));
15747}
15748
15749
15750THREADED_TEST(FixedUint8Array) {
15751 FixedTypedArrayTestHelper<i::FixedUint8Array, i::UINT8_ELEMENTS, uint8_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015752 i::kExternalUint8Array, 0x0, 0xFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015753}
15754
15755
15756THREADED_TEST(FixedUint8ClampedArray) {
15757 FixedTypedArrayTestHelper<i::FixedUint8ClampedArray,
15758 i::UINT8_CLAMPED_ELEMENTS, uint8_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015759 i::kExternalUint8ClampedArray, 0x0, 0xFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015760}
15761
15762
15763THREADED_TEST(FixedInt8Array) {
15764 FixedTypedArrayTestHelper<i::FixedInt8Array, i::INT8_ELEMENTS, int8_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015765 i::kExternalInt8Array, -0x80, 0x7F);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015766}
15767
15768
15769THREADED_TEST(FixedUint16Array) {
15770 FixedTypedArrayTestHelper<i::FixedUint16Array, i::UINT16_ELEMENTS, uint16_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015771 i::kExternalUint16Array, 0x0, 0xFFFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015772}
15773
15774
15775THREADED_TEST(FixedInt16Array) {
15776 FixedTypedArrayTestHelper<i::FixedInt16Array, i::INT16_ELEMENTS, int16_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015777 i::kExternalInt16Array, -0x8000, 0x7FFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015778}
15779
15780
15781THREADED_TEST(FixedUint32Array) {
15782 FixedTypedArrayTestHelper<i::FixedUint32Array, i::UINT32_ELEMENTS, uint32_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015783 i::kExternalUint32Array, 0x0, UINT_MAX);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015784}
15785
15786
15787THREADED_TEST(FixedInt32Array) {
15788 FixedTypedArrayTestHelper<i::FixedInt32Array, i::INT32_ELEMENTS, int32_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015789 i::kExternalInt32Array, INT_MIN, INT_MAX);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015790}
15791
15792
15793THREADED_TEST(FixedFloat32Array) {
15794 FixedTypedArrayTestHelper<i::FixedFloat32Array, i::FLOAT32_ELEMENTS, float>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015795 i::kExternalFloat32Array, -500, 500);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015796}
15797
15798
15799THREADED_TEST(FixedFloat64Array) {
15800 FixedTypedArrayTestHelper<i::FixedFloat64Array, i::FLOAT64_ELEMENTS, float>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015801 i::kExternalFloat64Array, -500, 500);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015802}
15803
15804
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015805template <typename ElementType, typename TypedArray, class ExternalArrayClass,
15806 class ArrayBufferType>
15807void TypedArrayTestHelper(i::ExternalArrayType array_type, int64_t low,
15808 int64_t high) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015809 const int kElementCount = 50;
15810
15811 i::ScopedVector<ElementType> backing_store(kElementCount+2);
15812
15813 LocalContext env;
15814 v8::Isolate* isolate = env->GetIsolate();
15815 v8::HandleScope handle_scope(isolate);
15816
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015817 Local<ArrayBufferType> ab =
15818 ArrayBufferType::New(isolate, backing_store.start(),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015819 (kElementCount + 2) * sizeof(ElementType));
15820 Local<TypedArray> ta =
15821 TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
15822 CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
15823 CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015824 CHECK_EQ(2 * sizeof(ElementType), ta->ByteOffset());
15825 CHECK_EQ(kElementCount * sizeof(ElementType), ta->ByteLength());
15826 CHECK(ab->Equals(env.local(), ta->Buffer()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015827
15828 ElementType* data = backing_store.start() + 2;
15829 for (int i = 0; i < kElementCount; i++) {
15830 data[i] = static_cast<ElementType>(i);
15831 }
15832
15833 ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
15834 env.local(), ta, kElementCount, array_type, low, high);
15835}
15836
15837
15838THREADED_TEST(Uint8Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015839 TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
15840 v8::ArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015841}
15842
15843
15844THREADED_TEST(Int8Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015845 TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
15846 v8::ArrayBuffer>(i::kExternalInt8Array, -0x80, 0x7F);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015847}
15848
15849
15850THREADED_TEST(Uint16Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015851 TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
15852 v8::ArrayBuffer>(i::kExternalUint16Array, 0, 0xFFFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015853}
15854
15855
15856THREADED_TEST(Int16Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015857 TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
15858 v8::ArrayBuffer>(i::kExternalInt16Array, -0x8000,
15859 0x7FFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015860}
15861
15862
15863THREADED_TEST(Uint32Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015864 TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
15865 v8::ArrayBuffer>(i::kExternalUint32Array, 0, UINT_MAX);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015866}
15867
15868
15869THREADED_TEST(Int32Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015870 TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
15871 v8::ArrayBuffer>(i::kExternalInt32Array, INT_MIN,
15872 INT_MAX);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015873}
15874
15875
15876THREADED_TEST(Float32Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015877 TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
15878 v8::ArrayBuffer>(i::kExternalFloat32Array, -500, 500);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015879}
15880
15881
15882THREADED_TEST(Float64Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015883 TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
15884 v8::ArrayBuffer>(i::kExternalFloat64Array, -500, 500);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015885}
15886
15887
15888THREADED_TEST(Uint8ClampedArray) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015889 TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
15890 i::FixedUint8ClampedArray, v8::ArrayBuffer>(
15891 i::kExternalUint8ClampedArray, 0, 0xFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015892}
15893
15894
15895THREADED_TEST(DataView) {
15896 const int kSize = 50;
15897
15898 i::ScopedVector<uint8_t> backing_store(kSize+2);
15899
15900 LocalContext env;
15901 v8::Isolate* isolate = env->GetIsolate();
15902 v8::HandleScope handle_scope(isolate);
15903
15904 Local<v8::ArrayBuffer> ab =
15905 v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015906 Local<v8::DataView> dv = v8::DataView::New(ab, 2, kSize);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015907 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015908 CHECK_EQ(2u, dv->ByteOffset());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015909 CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015910 CHECK(ab->Equals(env.local(), dv->Buffer()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015911}
15912
15913
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015914THREADED_TEST(SkipArrayBufferBackingStoreDuringGC) {
15915 LocalContext env;
15916 v8::Isolate* isolate = env->GetIsolate();
15917 v8::HandleScope handle_scope(isolate);
15918
15919 // Make sure the pointer looks like a heap object
15920 uint8_t* store_ptr = reinterpret_cast<uint8_t*>(i::kHeapObjectTag);
15921
15922 // Create ArrayBuffer with pointer-that-cannot-be-visited in the backing store
15923 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, store_ptr, 8);
15924
15925 // Should not crash
15926 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
15927 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
15928 CcTest::heap()->CollectAllGarbage();
15929 CcTest::heap()->CollectAllGarbage();
15930
15931 // Should not move the pointer
15932 CHECK_EQ(ab->GetContents().Data(), store_ptr);
15933}
15934
15935
15936THREADED_TEST(SkipArrayBufferDuringScavenge) {
15937 LocalContext env;
15938 v8::Isolate* isolate = env->GetIsolate();
15939 v8::HandleScope handle_scope(isolate);
15940
15941 // Make sure the pointer looks like a heap object
15942 Local<v8::Object> tmp = v8::Object::New(isolate);
15943 uint8_t* store_ptr =
15944 reinterpret_cast<uint8_t*>(*reinterpret_cast<uintptr_t*>(*tmp));
15945
15946 // Make `store_ptr` point to from space
15947 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
15948
15949 // Create ArrayBuffer with pointer-that-cannot-be-visited in the backing store
15950 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, store_ptr, 8);
15951
15952 // Should not crash,
15953 // i.e. backing store pointer should not be treated as a heap object pointer
15954 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
15955 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
15956
15957 // Use `ab` to silence compiler warning
15958 CHECK_EQ(ab->GetContents().Data(), store_ptr);
15959}
15960
15961
15962THREADED_TEST(SharedUint8Array) {
15963 i::FLAG_harmony_sharedarraybuffer = true;
15964 TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
15965 v8::SharedArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
15966}
15967
15968
15969THREADED_TEST(SharedInt8Array) {
15970 i::FLAG_harmony_sharedarraybuffer = true;
15971 TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
15972 v8::SharedArrayBuffer>(i::kExternalInt8Array, -0x80,
15973 0x7F);
15974}
15975
15976
15977THREADED_TEST(SharedUint16Array) {
15978 i::FLAG_harmony_sharedarraybuffer = true;
15979 TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
15980 v8::SharedArrayBuffer>(i::kExternalUint16Array, 0,
15981 0xFFFF);
15982}
15983
15984
15985THREADED_TEST(SharedInt16Array) {
15986 i::FLAG_harmony_sharedarraybuffer = true;
15987 TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
15988 v8::SharedArrayBuffer>(i::kExternalInt16Array, -0x8000,
15989 0x7FFF);
15990}
15991
15992
15993THREADED_TEST(SharedUint32Array) {
15994 i::FLAG_harmony_sharedarraybuffer = true;
15995 TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
15996 v8::SharedArrayBuffer>(i::kExternalUint32Array, 0,
15997 UINT_MAX);
15998}
15999
16000
16001THREADED_TEST(SharedInt32Array) {
16002 i::FLAG_harmony_sharedarraybuffer = true;
16003 TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
16004 v8::SharedArrayBuffer>(i::kExternalInt32Array, INT_MIN,
16005 INT_MAX);
16006}
16007
16008
16009THREADED_TEST(SharedFloat32Array) {
16010 i::FLAG_harmony_sharedarraybuffer = true;
16011 TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
16012 v8::SharedArrayBuffer>(i::kExternalFloat32Array, -500,
16013 500);
16014}
16015
16016
16017THREADED_TEST(SharedFloat64Array) {
16018 i::FLAG_harmony_sharedarraybuffer = true;
16019 TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
16020 v8::SharedArrayBuffer>(i::kExternalFloat64Array, -500,
16021 500);
16022}
16023
16024
16025THREADED_TEST(SharedUint8ClampedArray) {
16026 i::FLAG_harmony_sharedarraybuffer = true;
16027 TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
16028 i::FixedUint8ClampedArray, v8::SharedArrayBuffer>(
16029 i::kExternalUint8ClampedArray, 0, 0xFF);
16030}
16031
16032
16033THREADED_TEST(SharedDataView) {
16034 i::FLAG_harmony_sharedarraybuffer = true;
16035 const int kSize = 50;
16036
16037 i::ScopedVector<uint8_t> backing_store(kSize + 2);
16038
16039 LocalContext env;
16040 v8::Isolate* isolate = env->GetIsolate();
16041 v8::HandleScope handle_scope(isolate);
16042
16043 Local<v8::SharedArrayBuffer> ab =
16044 v8::SharedArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
16045 Local<v8::DataView> dv =
16046 v8::DataView::New(ab, 2, kSize);
16047 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
16048 CHECK_EQ(2u, dv->ByteOffset());
16049 CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
16050 CHECK(ab->Equals(env.local(), dv->Buffer()).FromJust());
16051}
16052
16053
16054#define IS_ARRAY_BUFFER_VIEW_TEST(View) \
16055 THREADED_TEST(Is##View) { \
16056 LocalContext env; \
16057 v8::Isolate* isolate = env->GetIsolate(); \
16058 v8::HandleScope handle_scope(isolate); \
16059 \
16060 Local<Value> result = CompileRun( \
16061 "var ab = new ArrayBuffer(128);" \
16062 "new " #View "(ab)"); \
16063 CHECK(result->IsArrayBufferView()); \
16064 CHECK(result->Is##View()); \
16065 CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>()); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016066 }
16067
16068IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
16069IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
16070IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
16071IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
16072IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
16073IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
16074IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
16075IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
16076IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
16077IS_ARRAY_BUFFER_VIEW_TEST(DataView)
16078
16079#undef IS_ARRAY_BUFFER_VIEW_TEST
16080
16081
16082
Steve Blocka7e24c12009-10-30 11:49:00 +000016083THREADED_TEST(ScriptContextDependence) {
Steve Blocka7e24c12009-10-30 11:49:00 +000016084 LocalContext c1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016085 v8::HandleScope scope(c1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000016086 const char *source = "foo";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016087 v8::Local<v8::Script> dep = v8_compile(source);
16088 v8::ScriptCompiler::Source script_source(
16089 v8::String::NewFromUtf8(c1->GetIsolate(), source,
16090 v8::NewStringType::kNormal)
16091 .ToLocalChecked());
16092 v8::Local<v8::UnboundScript> indep =
16093 v8::ScriptCompiler::CompileUnboundScript(c1->GetIsolate(), &script_source)
16094 .ToLocalChecked();
16095 c1->Global()
16096 ->Set(c1.local(), v8::String::NewFromUtf8(c1->GetIsolate(), "foo",
16097 v8::NewStringType::kNormal)
16098 .ToLocalChecked(),
16099 v8::Integer::New(c1->GetIsolate(), 100))
16100 .FromJust();
16101 CHECK_EQ(
16102 dep->Run(c1.local()).ToLocalChecked()->Int32Value(c1.local()).FromJust(),
16103 100);
16104 CHECK_EQ(indep->BindToCurrentContext()
16105 ->Run(c1.local())
16106 .ToLocalChecked()
16107 ->Int32Value(c1.local())
16108 .FromJust(),
16109 100);
Steve Blocka7e24c12009-10-30 11:49:00 +000016110 LocalContext c2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016111 c2->Global()
16112 ->Set(c2.local(), v8::String::NewFromUtf8(c2->GetIsolate(), "foo",
16113 v8::NewStringType::kNormal)
16114 .ToLocalChecked(),
16115 v8::Integer::New(c2->GetIsolate(), 101))
16116 .FromJust();
16117 CHECK_EQ(
16118 dep->Run(c2.local()).ToLocalChecked()->Int32Value(c2.local()).FromJust(),
16119 100);
16120 CHECK_EQ(indep->BindToCurrentContext()
16121 ->Run(c2.local())
16122 .ToLocalChecked()
16123 ->Int32Value(c2.local())
16124 .FromJust(),
16125 101);
Steve Blocka7e24c12009-10-30 11:49:00 +000016126}
16127
16128
16129THREADED_TEST(StackTrace) {
Steve Blocka7e24c12009-10-30 11:49:00 +000016130 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016131 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016132 v8::TryCatch try_catch(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000016133 const char *source = "function foo() { FAIL.FAIL; }; foo();";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016134 v8::Local<v8::String> src = v8_str(source);
16135 v8::Local<v8::String> origin = v8_str("stack-trace-test");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016136 v8::ScriptCompiler::Source script_source(src, v8::ScriptOrigin(origin));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016137 CHECK(v8::ScriptCompiler::CompileUnboundScript(context->GetIsolate(),
16138 &script_source)
16139 .ToLocalChecked()
16140 ->BindToCurrentContext()
16141 ->Run(context.local())
16142 .IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000016143 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016144 v8::String::Utf8Value stack(
16145 try_catch.StackTrace(context.local()).ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +000016146 CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
16147}
16148
16149
Kristian Monsen25f61362010-05-21 11:50:48 +010016150// Checks that a StackFrame has certain expected values.
16151void checkStackFrame(const char* expected_script_name,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016152 const char* expected_func_name, int expected_line_number,
16153 int expected_column, bool is_eval, bool is_constructor,
16154 v8::Local<v8::StackFrame> frame) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016155 v8::HandleScope scope(CcTest::isolate());
Kristian Monsen25f61362010-05-21 11:50:48 +010016156 v8::String::Utf8Value func_name(frame->GetFunctionName());
16157 v8::String::Utf8Value script_name(frame->GetScriptName());
16158 if (*script_name == NULL) {
16159 // The situation where there is no associated script, like for evals.
16160 CHECK(expected_script_name == NULL);
16161 } else {
16162 CHECK(strstr(*script_name, expected_script_name) != NULL);
16163 }
16164 CHECK(strstr(*func_name, expected_func_name) != NULL);
16165 CHECK_EQ(expected_line_number, frame->GetLineNumber());
16166 CHECK_EQ(expected_column, frame->GetColumn());
16167 CHECK_EQ(is_eval, frame->IsEval());
16168 CHECK_EQ(is_constructor, frame->IsConstructor());
16169}
16170
16171
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016172void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
16173 v8::HandleScope scope(args.GetIsolate());
Kristian Monsen25f61362010-05-21 11:50:48 +010016174 const char* origin = "capture-stack-trace-test";
16175 const int kOverviewTest = 1;
16176 const int kDetailedTest = 2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016177 const int kFunctionName = 3;
16178 const int kDisplayName = 4;
16179 const int kFunctionNameAndDisplayName = 5;
16180 const int kDisplayNameIsNotString = 6;
16181 const int kFunctionNameIsNotString = 7;
Kristian Monsen25f61362010-05-21 11:50:48 +010016182
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016183 CHECK(args.Length() == 1);
Kristian Monsen25f61362010-05-21 11:50:48 +010016184
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016185 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
16186 int testGroup = args[0]->Int32Value(context).FromJust();
Kristian Monsen25f61362010-05-21 11:50:48 +010016187 if (testGroup == kOverviewTest) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016188 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016189 args.GetIsolate(), 10, v8::StackTrace::kOverview);
Kristian Monsen25f61362010-05-21 11:50:48 +010016190 CHECK_EQ(4, stackTrace->GetFrameCount());
16191 checkStackFrame(origin, "bar", 2, 10, false, false,
16192 stackTrace->GetFrame(0));
16193 checkStackFrame(origin, "foo", 6, 3, false, false,
16194 stackTrace->GetFrame(1));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000016195 // This is the source string inside the eval which has the call to foo.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016196 checkStackFrame(NULL, "", 1, 1, false, false, stackTrace->GetFrame(2));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000016197 // The last frame is an anonymous function which has the initial eval call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016198 checkStackFrame(origin, "", 8, 7, false, false, stackTrace->GetFrame(3));
Kristian Monsen25f61362010-05-21 11:50:48 +010016199
16200 CHECK(stackTrace->AsArray()->IsArray());
16201 } else if (testGroup == kDetailedTest) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016202 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016203 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
Kristian Monsen25f61362010-05-21 11:50:48 +010016204 CHECK_EQ(4, stackTrace->GetFrameCount());
16205 checkStackFrame(origin, "bat", 4, 22, false, false,
16206 stackTrace->GetFrame(0));
16207 checkStackFrame(origin, "baz", 8, 3, false, true,
16208 stackTrace->GetFrame(1));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +010016209 bool is_eval = true;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000016210 // This is the source string inside the eval which has the call to baz.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016211 checkStackFrame(NULL, "", 1, 1, is_eval, false, stackTrace->GetFrame(2));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000016212 // The last frame is an anonymous function which has the initial eval call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016213 checkStackFrame(origin, "", 10, 1, false, false, stackTrace->GetFrame(3));
Kristian Monsen25f61362010-05-21 11:50:48 +010016214
16215 CHECK(stackTrace->AsArray()->IsArray());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016216 } else if (testGroup == kFunctionName) {
16217 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
16218 args.GetIsolate(), 5, v8::StackTrace::kOverview);
16219 CHECK_EQ(3, stackTrace->GetFrameCount());
16220 checkStackFrame(origin, "function.name", 2, 24, false, false,
16221 stackTrace->GetFrame(0));
16222 } else if (testGroup == kDisplayName) {
16223 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
16224 args.GetIsolate(), 5, v8::StackTrace::kOverview);
16225 CHECK_EQ(3, stackTrace->GetFrameCount());
16226 checkStackFrame(origin, "function.displayName", 2, 24, false, false,
16227 stackTrace->GetFrame(0));
16228 } else if (testGroup == kFunctionNameAndDisplayName) {
16229 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
16230 args.GetIsolate(), 5, v8::StackTrace::kOverview);
16231 CHECK_EQ(3, stackTrace->GetFrameCount());
16232 checkStackFrame(origin, "function.displayName", 2, 24, false, false,
16233 stackTrace->GetFrame(0));
16234 } else if (testGroup == kDisplayNameIsNotString) {
16235 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
16236 args.GetIsolate(), 5, v8::StackTrace::kOverview);
16237 CHECK_EQ(3, stackTrace->GetFrameCount());
16238 checkStackFrame(origin, "function.name", 2, 24, false, false,
16239 stackTrace->GetFrame(0));
16240 } else if (testGroup == kFunctionNameIsNotString) {
16241 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
16242 args.GetIsolate(), 5, v8::StackTrace::kOverview);
16243 CHECK_EQ(3, stackTrace->GetFrameCount());
16244 checkStackFrame(origin, "f", 2, 24, false, false, stackTrace->GetFrame(0));
Kristian Monsen25f61362010-05-21 11:50:48 +010016245 }
Kristian Monsen25f61362010-05-21 11:50:48 +010016246}
16247
16248
16249// Tests the C++ StackTrace API.
Ben Murdochb0fe1622011-05-05 13:52:32 +010016250// TODO(3074796): Reenable this as a THREADED_TEST once it passes.
16251// THREADED_TEST(CaptureStackTrace) {
16252TEST(CaptureStackTrace) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016253 v8::Isolate* isolate = CcTest::isolate();
16254 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016255 v8::Local<v8::String> origin = v8_str("capture-stack-trace-test");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016256 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Kristian Monsen25f61362010-05-21 11:50:48 +010016257 templ->Set(v8_str("AnalyzeStackInNativeCode"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016258 v8::FunctionTemplate::New(isolate, AnalyzeStackInNativeCode));
Kristian Monsen25f61362010-05-21 11:50:48 +010016259 LocalContext context(0, templ);
16260
16261 // Test getting OVERVIEW information. Should ignore information that is not
16262 // script name, function name, line number, and column offset.
16263 const char *overview_source =
16264 "function bar() {\n"
16265 " var y; AnalyzeStackInNativeCode(1);\n"
16266 "}\n"
16267 "function foo() {\n"
16268 "\n"
16269 " bar();\n"
16270 "}\n"
16271 "var x;eval('new foo();');";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016272 v8::Local<v8::String> overview_src = v8_str(overview_source);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016273 v8::ScriptCompiler::Source script_source(overview_src,
16274 v8::ScriptOrigin(origin));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016275 v8::Local<Value> overview_result(
16276 v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source)
16277 .ToLocalChecked()
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016278 ->BindToCurrentContext()
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016279 ->Run(context.local())
16280 .ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016281 CHECK(!overview_result.IsEmpty());
16282 CHECK(overview_result->IsObject());
Kristian Monsen25f61362010-05-21 11:50:48 +010016283
16284 // Test getting DETAILED information.
16285 const char *detailed_source =
16286 "function bat() {AnalyzeStackInNativeCode(2);\n"
16287 "}\n"
16288 "\n"
16289 "function baz() {\n"
16290 " bat();\n"
16291 "}\n"
16292 "eval('new baz();');";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016293 v8::Local<v8::String> detailed_src = v8_str(detailed_source);
Kristian Monsen25f61362010-05-21 11:50:48 +010016294 // Make the script using a non-zero line and column offset.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016295 v8::Local<v8::Integer> line_offset = v8::Integer::New(isolate, 3);
16296 v8::Local<v8::Integer> column_offset = v8::Integer::New(isolate, 5);
Kristian Monsen25f61362010-05-21 11:50:48 +010016297 v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016298 v8::ScriptCompiler::Source script_source2(detailed_src, detailed_origin);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016299 v8::Local<v8::UnboundScript> detailed_script(
16300 v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source2)
16301 .ToLocalChecked());
16302 v8::Local<Value> detailed_result(detailed_script->BindToCurrentContext()
16303 ->Run(context.local())
16304 .ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016305 CHECK(!detailed_result.IsEmpty());
16306 CHECK(detailed_result->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016307
16308 // Test using function.name and function.displayName in stack trace
16309 const char* function_name_source =
16310 "function bar(function_name, display_name, testGroup) {\n"
16311 " var f = function() { AnalyzeStackInNativeCode(testGroup); };\n"
16312 " if (function_name) {\n"
16313 " Object.defineProperty(f, 'name', { value: function_name });\n"
16314 " }\n"
16315 " if (display_name) {\n"
16316 " f.displayName = display_name;"
16317 " }\n"
16318 " f()\n"
16319 "}\n"
16320 "bar('function.name', undefined, 3);\n"
16321 "bar(undefined, 'function.displayName', 4);\n"
16322 "bar('function.name', 'function.displayName', 5);\n"
16323 "bar('function.name', 239, 6);\n"
16324 "bar(239, undefined, 7);\n";
16325 v8::Local<v8::String> function_name_src =
16326 v8::String::NewFromUtf8(isolate, function_name_source,
16327 v8::NewStringType::kNormal)
16328 .ToLocalChecked();
16329 v8::ScriptCompiler::Source script_source3(function_name_src,
16330 v8::ScriptOrigin(origin));
16331 v8::Local<Value> function_name_result(
16332 v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source3)
16333 .ToLocalChecked()
16334 ->BindToCurrentContext()
16335 ->Run(context.local())
16336 .ToLocalChecked());
16337 CHECK(!function_name_result.IsEmpty());
Kristian Monsen25f61362010-05-21 11:50:48 +010016338}
16339
16340
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016341static void StackTraceForUncaughtExceptionListener(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016342 v8::Local<v8::Message> message, v8::Local<Value>) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016343 report_count++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016344 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016345 CHECK_EQ(2, stack_trace->GetFrameCount());
16346 checkStackFrame("origin", "foo", 2, 3, false, false,
16347 stack_trace->GetFrame(0));
16348 checkStackFrame("origin", "bar", 5, 3, false, false,
16349 stack_trace->GetFrame(1));
16350}
16351
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016352
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016353TEST(CaptureStackTraceForUncaughtException) {
16354 report_count = 0;
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016355 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016356 v8::Isolate* isolate = env->GetIsolate();
16357 v8::HandleScope scope(isolate);
16358 isolate->AddMessageListener(StackTraceForUncaughtExceptionListener);
16359 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016360
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016361 CompileRunWithOrigin(
16362 "function foo() {\n"
16363 " throw 1;\n"
16364 "};\n"
16365 "function bar() {\n"
16366 " foo();\n"
16367 "};",
16368 "origin");
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016369 v8::Local<v8::Object> global = env->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016370 Local<Value> trouble =
16371 global->Get(env.local(), v8_str("bar")).ToLocalChecked();
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016372 CHECK(trouble->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016373 CHECK(Function::Cast(*trouble)->Call(env.local(), global, 0, NULL).IsEmpty());
16374 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
16375 isolate->RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016376 CHECK_EQ(1, report_count);
16377}
16378
16379
16380TEST(GetStackTraceForUncaughtExceptionFromSimpleStackTrace) {
16381 report_count = 0;
16382 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016383 v8::Isolate* isolate = env->GetIsolate();
16384 v8::HandleScope scope(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016385
16386 // Create an Error object first.
16387 CompileRunWithOrigin(
16388 "function foo() {\n"
16389 "e=new Error('err');\n"
16390 "};\n"
16391 "function bar() {\n"
16392 " foo();\n"
16393 "};\n"
16394 "var e;",
16395 "origin");
16396 v8::Local<v8::Object> global = env->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016397 Local<Value> trouble =
16398 global->Get(env.local(), v8_str("bar")).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016399 CHECK(trouble->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016400 Function::Cast(*trouble)->Call(env.local(), global, 0, NULL).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016401
16402 // Enable capturing detailed stack trace late, and throw the exception.
16403 // The detailed stack trace should be extracted from the simple stack.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016404 isolate->AddMessageListener(StackTraceForUncaughtExceptionListener);
16405 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016406 CompileRunWithOrigin("throw e", "origin");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016407 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
16408 isolate->RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016409 CHECK_EQ(1, report_count);
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016410}
16411
16412
Steve Block1e0659c2011-05-24 12:43:12 +010016413TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
Steve Block1e0659c2011-05-24 12:43:12 +010016414 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016415 v8::Isolate* isolate = env->GetIsolate();
16416 v8::HandleScope scope(isolate);
16417 isolate->SetCaptureStackTraceForUncaughtExceptions(true, 1024,
16418 v8::StackTrace::kDetailed);
Steve Block1e0659c2011-05-24 12:43:12 +010016419
16420 CompileRun(
16421 "var setters = ['column', 'lineNumber', 'scriptName',\n"
16422 " 'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
16423 " 'isConstructor'];\n"
16424 "for (var i = 0; i < setters.length; i++) {\n"
16425 " var prop = setters[i];\n"
16426 " Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
16427 "}\n");
16428 CompileRun("throw 'exception';");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016429 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
Steve Block1e0659c2011-05-24 12:43:12 +010016430}
16431
16432
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016433static void StackTraceFunctionNameListener(v8::Local<v8::Message> message,
16434 v8::Local<Value>) {
16435 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
16436 CHECK_EQ(5, stack_trace->GetFrameCount());
16437 checkStackFrame("origin", "foo:0", 4, 7, false, false,
16438 stack_trace->GetFrame(0));
16439 checkStackFrame("origin", "foo:1", 5, 27, false, false,
16440 stack_trace->GetFrame(1));
16441 checkStackFrame("origin", "foo", 5, 27, false, false,
16442 stack_trace->GetFrame(2));
16443 checkStackFrame("origin", "foo", 5, 27, false, false,
16444 stack_trace->GetFrame(3));
16445 checkStackFrame("origin", "", 1, 14, false, false, stack_trace->GetFrame(4));
16446}
16447
16448
16449TEST(GetStackTraceContainsFunctionsWithFunctionName) {
16450 LocalContext env;
16451 v8::Isolate* isolate = env->GetIsolate();
16452 v8::HandleScope scope(isolate);
16453
16454 CompileRunWithOrigin(
16455 "function gen(name, counter) {\n"
16456 " var f = function foo() {\n"
16457 " if (counter === 0)\n"
16458 " throw 1;\n"
16459 " gen(name, counter - 1)();\n"
16460 " };\n"
16461 " if (counter == 3) {\n"
16462 " Object.defineProperty(f, 'name', {get: function(){ throw 239; }});\n"
16463 " } else {\n"
16464 " Object.defineProperty(f, 'name', {writable:true});\n"
16465 " if (counter == 2)\n"
16466 " f.name = 42;\n"
16467 " else\n"
16468 " f.name = name + ':' + counter;\n"
16469 " }\n"
16470 " return f;\n"
16471 "};",
16472 "origin");
16473
16474 isolate->AddMessageListener(StackTraceFunctionNameListener);
16475 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
16476 CompileRunWithOrigin("gen('foo', 3)();", "origin");
16477 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
16478 isolate->RemoveMessageListeners(StackTraceFunctionNameListener);
16479}
16480
16481
16482static void RethrowStackTraceHandler(v8::Local<v8::Message> message,
16483 v8::Local<v8::Value> data) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016484 // Use the frame where JavaScript is called from.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016485 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016486 CHECK(!stack_trace.IsEmpty());
16487 int frame_count = stack_trace->GetFrameCount();
16488 CHECK_EQ(3, frame_count);
16489 int line_number[] = {1, 2, 5};
16490 for (int i = 0; i < frame_count; i++) {
16491 CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
16492 }
16493}
16494
16495
16496// Test that we only return the stack trace at the site where the exception
16497// is first thrown (not where it is rethrown).
16498TEST(RethrowStackTrace) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016499 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016500 v8::Isolate* isolate = env->GetIsolate();
16501 v8::HandleScope scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016502 // We make sure that
16503 // - the stack trace of the ReferenceError in g() is reported.
16504 // - the stack trace is not overwritten when e1 is rethrown by t().
16505 // - the stack trace of e2 does not overwrite that of e1.
16506 const char* source =
16507 "function g() { error; } \n"
16508 "function f() { g(); } \n"
16509 "function t(e) { throw e; } \n"
16510 "try { \n"
16511 " f(); \n"
16512 "} catch (e1) { \n"
16513 " try { \n"
16514 " error; \n"
16515 " } catch (e2) { \n"
16516 " t(e1); \n"
16517 " } \n"
16518 "} \n";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016519 isolate->AddMessageListener(RethrowStackTraceHandler);
16520 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016521 CompileRun(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016522 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
16523 isolate->RemoveMessageListeners(RethrowStackTraceHandler);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016524}
16525
16526
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016527static void RethrowPrimitiveStackTraceHandler(v8::Local<v8::Message> message,
16528 v8::Local<v8::Value> data) {
16529 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016530 CHECK(!stack_trace.IsEmpty());
16531 int frame_count = stack_trace->GetFrameCount();
16532 CHECK_EQ(2, frame_count);
16533 int line_number[] = {3, 7};
16534 for (int i = 0; i < frame_count; i++) {
16535 CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
16536 }
16537}
16538
16539
16540// Test that we do not recognize identity for primitive exceptions.
16541TEST(RethrowPrimitiveStackTrace) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016542 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016543 v8::Isolate* isolate = env->GetIsolate();
16544 v8::HandleScope scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016545 // We do not capture stack trace for non Error objects on creation time.
16546 // Instead, we capture the stack trace on last throw.
16547 const char* source =
16548 "function g() { throw 404; } \n"
16549 "function f() { g(); } \n"
16550 "function t(e) { throw e; } \n"
16551 "try { \n"
16552 " f(); \n"
16553 "} catch (e1) { \n"
16554 " t(e1) \n"
16555 "} \n";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016556 isolate->AddMessageListener(RethrowPrimitiveStackTraceHandler);
16557 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016558 CompileRun(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016559 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
16560 isolate->RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016561}
16562
16563
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016564static void RethrowExistingStackTraceHandler(v8::Local<v8::Message> message,
16565 v8::Local<v8::Value> data) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016566 // Use the frame where JavaScript is called from.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016567 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016568 CHECK(!stack_trace.IsEmpty());
16569 CHECK_EQ(1, stack_trace->GetFrameCount());
16570 CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
16571}
16572
16573
16574// Test that the stack trace is captured when the error object is created and
16575// not where it is thrown.
16576TEST(RethrowExistingStackTrace) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016577 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016578 v8::Isolate* isolate = env->GetIsolate();
16579 v8::HandleScope scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016580 const char* source =
16581 "var e = new Error(); \n"
16582 "throw e; \n";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016583 isolate->AddMessageListener(RethrowExistingStackTraceHandler);
16584 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016585 CompileRun(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016586 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
16587 isolate->RemoveMessageListeners(RethrowExistingStackTraceHandler);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016588}
16589
16590
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016591static void RethrowBogusErrorStackTraceHandler(v8::Local<v8::Message> message,
16592 v8::Local<v8::Value> data) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016593 // Use the frame where JavaScript is called from.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016594 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016595 CHECK(!stack_trace.IsEmpty());
16596 CHECK_EQ(1, stack_trace->GetFrameCount());
16597 CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
16598}
16599
16600
16601// Test that the stack trace is captured where the bogus Error object is thrown.
16602TEST(RethrowBogusErrorStackTrace) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016603 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016604 v8::Isolate* isolate = env->GetIsolate();
16605 v8::HandleScope scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016606 const char* source =
16607 "var e = {__proto__: new Error()} \n"
16608 "throw e; \n";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016609 isolate->AddMessageListener(RethrowBogusErrorStackTraceHandler);
16610 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016611 CompileRun(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016612 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
16613 isolate->RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016614}
16615
16616
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016617v8::PromiseRejectEvent reject_event = v8::kPromiseRejectWithNoHandler;
16618int promise_reject_counter = 0;
16619int promise_revoke_counter = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016620int promise_reject_msg_line_number = -1;
16621int promise_reject_msg_column_number = -1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016622int promise_reject_line_number = -1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016623int promise_reject_column_number = -1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016624int promise_reject_frame_count = -1;
16625
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016626void PromiseRejectCallback(v8::PromiseRejectMessage reject_message) {
16627 v8::Local<v8::Object> global = CcTest::global();
16628 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
16629 if (reject_message.GetEvent() == v8::kPromiseRejectWithNoHandler) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016630 promise_reject_counter++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016631 global->Set(context, v8_str("rejected"), reject_message.GetPromise())
16632 .FromJust();
16633 global->Set(context, v8_str("value"), reject_message.GetValue()).FromJust();
16634 v8::Local<v8::Message> message = v8::Exception::CreateMessage(
16635 CcTest::isolate(), reject_message.GetValue());
16636 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
16637
16638 promise_reject_msg_line_number = message->GetLineNumber(context).FromJust();
16639 promise_reject_msg_column_number =
16640 message->GetStartColumn(context).FromJust() + 1;
16641
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016642 if (!stack_trace.IsEmpty()) {
16643 promise_reject_frame_count = stack_trace->GetFrameCount();
16644 if (promise_reject_frame_count > 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016645 CHECK(stack_trace->GetFrame(0)
16646 ->GetScriptName()
16647 ->Equals(context, v8_str("pro"))
16648 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016649 promise_reject_line_number = stack_trace->GetFrame(0)->GetLineNumber();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016650 promise_reject_column_number = stack_trace->GetFrame(0)->GetColumn();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016651 } else {
16652 promise_reject_line_number = -1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016653 promise_reject_column_number = -1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016654 }
16655 }
16656 } else {
16657 promise_revoke_counter++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016658 global->Set(context, v8_str("revoked"), reject_message.GetPromise())
16659 .FromJust();
16660 CHECK(reject_message.GetValue().IsEmpty());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016661 }
16662}
16663
16664
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016665v8::Local<v8::Promise> GetPromise(const char* name) {
16666 return v8::Local<v8::Promise>::Cast(
16667 CcTest::global()
16668 ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(name))
16669 .ToLocalChecked());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016670}
16671
16672
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016673v8::Local<v8::Value> RejectValue() {
16674 return CcTest::global()
16675 ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value"))
16676 .ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016677}
16678
16679
16680void ResetPromiseStates() {
16681 promise_reject_counter = 0;
16682 promise_revoke_counter = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016683 promise_reject_msg_line_number = -1;
16684 promise_reject_msg_column_number = -1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016685 promise_reject_line_number = -1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016686 promise_reject_column_number = -1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016687 promise_reject_frame_count = -1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016688
16689 v8::Local<v8::Object> global = CcTest::global();
16690 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
16691 global->Set(context, v8_str("rejected"), v8_str("")).FromJust();
16692 global->Set(context, v8_str("value"), v8_str("")).FromJust();
16693 global->Set(context, v8_str("revoked"), v8_str("")).FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016694}
16695
16696
16697TEST(PromiseRejectCallback) {
16698 LocalContext env;
16699 v8::Isolate* isolate = env->GetIsolate();
16700 v8::HandleScope scope(isolate);
16701
16702 isolate->SetPromiseRejectCallback(PromiseRejectCallback);
16703
16704 ResetPromiseStates();
16705
16706 // Create promise p0.
16707 CompileRun(
16708 "var reject; \n"
16709 "var p0 = new Promise( \n"
16710 " function(res, rej) { \n"
16711 " reject = rej; \n"
16712 " } \n"
16713 "); \n");
16714 CHECK(!GetPromise("p0")->HasHandler());
16715 CHECK_EQ(0, promise_reject_counter);
16716 CHECK_EQ(0, promise_revoke_counter);
16717
16718 // Add resolve handler (and default reject handler) to p0.
16719 CompileRun("var p1 = p0.then(function(){});");
16720 CHECK(GetPromise("p0")->HasHandler());
16721 CHECK(!GetPromise("p1")->HasHandler());
16722 CHECK_EQ(0, promise_reject_counter);
16723 CHECK_EQ(0, promise_revoke_counter);
16724
16725 // Reject p0.
16726 CompileRun("reject('ppp');");
16727 CHECK(GetPromise("p0")->HasHandler());
16728 CHECK(!GetPromise("p1")->HasHandler());
16729 CHECK_EQ(1, promise_reject_counter);
16730 CHECK_EQ(0, promise_revoke_counter);
16731 CHECK_EQ(v8::kPromiseRejectWithNoHandler, reject_event);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016732 CHECK(
16733 GetPromise("rejected")->Equals(env.local(), GetPromise("p1")).FromJust());
16734 CHECK(RejectValue()->Equals(env.local(), v8_str("ppp")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016735
16736 // Reject p0 again. Callback is not triggered again.
16737 CompileRun("reject();");
16738 CHECK(GetPromise("p0")->HasHandler());
16739 CHECK(!GetPromise("p1")->HasHandler());
16740 CHECK_EQ(1, promise_reject_counter);
16741 CHECK_EQ(0, promise_revoke_counter);
16742
16743 // Add resolve handler to p1.
16744 CompileRun("var p2 = p1.then(function(){});");
16745 CHECK(GetPromise("p0")->HasHandler());
16746 CHECK(GetPromise("p1")->HasHandler());
16747 CHECK(!GetPromise("p2")->HasHandler());
16748 CHECK_EQ(2, promise_reject_counter);
16749 CHECK_EQ(1, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016750 CHECK(
16751 GetPromise("rejected")->Equals(env.local(), GetPromise("p2")).FromJust());
16752 CHECK(RejectValue()->Equals(env.local(), v8_str("ppp")).FromJust());
16753 CHECK(
16754 GetPromise("revoked")->Equals(env.local(), GetPromise("p1")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016755
16756 ResetPromiseStates();
16757
16758 // Create promise q0.
16759 CompileRun(
16760 "var q0 = new Promise( \n"
16761 " function(res, rej) { \n"
16762 " reject = rej; \n"
16763 " } \n"
16764 "); \n");
16765 CHECK(!GetPromise("q0")->HasHandler());
16766 CHECK_EQ(0, promise_reject_counter);
16767 CHECK_EQ(0, promise_revoke_counter);
16768
16769 // Add reject handler to q0.
16770 CompileRun("var q1 = q0.catch(function() {});");
16771 CHECK(GetPromise("q0")->HasHandler());
16772 CHECK(!GetPromise("q1")->HasHandler());
16773 CHECK_EQ(0, promise_reject_counter);
16774 CHECK_EQ(0, promise_revoke_counter);
16775
16776 // Reject q0.
16777 CompileRun("reject('qq')");
16778 CHECK(GetPromise("q0")->HasHandler());
16779 CHECK(!GetPromise("q1")->HasHandler());
16780 CHECK_EQ(0, promise_reject_counter);
16781 CHECK_EQ(0, promise_revoke_counter);
16782
16783 // Add a new reject handler, which rejects by returning Promise.reject().
16784 // The returned promise q_ triggers a reject callback at first, only to
16785 // revoke it when returning it causes q2 to be rejected.
16786 CompileRun(
16787 "var q_;"
16788 "var q2 = q0.catch( \n"
16789 " function() { \n"
16790 " q_ = Promise.reject('qqq'); \n"
16791 " return q_; \n"
16792 " } \n"
16793 "); \n");
16794 CHECK(GetPromise("q0")->HasHandler());
16795 CHECK(!GetPromise("q1")->HasHandler());
16796 CHECK(!GetPromise("q2")->HasHandler());
16797 CHECK(GetPromise("q_")->HasHandler());
16798 CHECK_EQ(2, promise_reject_counter);
16799 CHECK_EQ(1, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016800 CHECK(
16801 GetPromise("rejected")->Equals(env.local(), GetPromise("q2")).FromJust());
16802 CHECK(
16803 GetPromise("revoked")->Equals(env.local(), GetPromise("q_")).FromJust());
16804 CHECK(RejectValue()->Equals(env.local(), v8_str("qqq")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016805
16806 // Add a reject handler to the resolved q1, which rejects by throwing.
16807 CompileRun(
16808 "var q3 = q1.then( \n"
16809 " function() { \n"
16810 " throw 'qqqq'; \n"
16811 " } \n"
16812 "); \n");
16813 CHECK(GetPromise("q0")->HasHandler());
16814 CHECK(GetPromise("q1")->HasHandler());
16815 CHECK(!GetPromise("q2")->HasHandler());
16816 CHECK(!GetPromise("q3")->HasHandler());
16817 CHECK_EQ(3, promise_reject_counter);
16818 CHECK_EQ(1, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016819 CHECK(
16820 GetPromise("rejected")->Equals(env.local(), GetPromise("q3")).FromJust());
16821 CHECK(RejectValue()->Equals(env.local(), v8_str("qqqq")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016822
16823 ResetPromiseStates();
16824
16825 // Create promise r0, which has three handlers, two of which handle rejects.
16826 CompileRun(
16827 "var r0 = new Promise( \n"
16828 " function(res, rej) { \n"
16829 " reject = rej; \n"
16830 " } \n"
16831 "); \n"
16832 "var r1 = r0.catch(function() {}); \n"
16833 "var r2 = r0.then(function() {}); \n"
16834 "var r3 = r0.then(function() {}, \n"
16835 " function() {}); \n");
16836 CHECK(GetPromise("r0")->HasHandler());
16837 CHECK(!GetPromise("r1")->HasHandler());
16838 CHECK(!GetPromise("r2")->HasHandler());
16839 CHECK(!GetPromise("r3")->HasHandler());
16840 CHECK_EQ(0, promise_reject_counter);
16841 CHECK_EQ(0, promise_revoke_counter);
16842
16843 // Reject r0.
16844 CompileRun("reject('rrr')");
16845 CHECK(GetPromise("r0")->HasHandler());
16846 CHECK(!GetPromise("r1")->HasHandler());
16847 CHECK(!GetPromise("r2")->HasHandler());
16848 CHECK(!GetPromise("r3")->HasHandler());
16849 CHECK_EQ(1, promise_reject_counter);
16850 CHECK_EQ(0, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016851 CHECK(
16852 GetPromise("rejected")->Equals(env.local(), GetPromise("r2")).FromJust());
16853 CHECK(RejectValue()->Equals(env.local(), v8_str("rrr")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016854
16855 // Add reject handler to r2.
16856 CompileRun("var r4 = r2.catch(function() {});");
16857 CHECK(GetPromise("r0")->HasHandler());
16858 CHECK(!GetPromise("r1")->HasHandler());
16859 CHECK(GetPromise("r2")->HasHandler());
16860 CHECK(!GetPromise("r3")->HasHandler());
16861 CHECK(!GetPromise("r4")->HasHandler());
16862 CHECK_EQ(1, promise_reject_counter);
16863 CHECK_EQ(1, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016864 CHECK(
16865 GetPromise("revoked")->Equals(env.local(), GetPromise("r2")).FromJust());
16866 CHECK(RejectValue()->Equals(env.local(), v8_str("rrr")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016867
16868 // Add reject handlers to r4.
16869 CompileRun("var r5 = r4.then(function() {}, function() {});");
16870 CHECK(GetPromise("r0")->HasHandler());
16871 CHECK(!GetPromise("r1")->HasHandler());
16872 CHECK(GetPromise("r2")->HasHandler());
16873 CHECK(!GetPromise("r3")->HasHandler());
16874 CHECK(GetPromise("r4")->HasHandler());
16875 CHECK(!GetPromise("r5")->HasHandler());
16876 CHECK_EQ(1, promise_reject_counter);
16877 CHECK_EQ(1, promise_revoke_counter);
16878
16879 ResetPromiseStates();
16880
16881 // Create promise s0, which has three handlers, none of which handle rejects.
16882 CompileRun(
16883 "var s0 = new Promise( \n"
16884 " function(res, rej) { \n"
16885 " reject = rej; \n"
16886 " } \n"
16887 "); \n"
16888 "var s1 = s0.then(function() {}); \n"
16889 "var s2 = s0.then(function() {}); \n"
16890 "var s3 = s0.then(function() {}); \n");
16891 CHECK(GetPromise("s0")->HasHandler());
16892 CHECK(!GetPromise("s1")->HasHandler());
16893 CHECK(!GetPromise("s2")->HasHandler());
16894 CHECK(!GetPromise("s3")->HasHandler());
16895 CHECK_EQ(0, promise_reject_counter);
16896 CHECK_EQ(0, promise_revoke_counter);
16897
16898 // Reject s0.
16899 CompileRun("reject('sss')");
16900 CHECK(GetPromise("s0")->HasHandler());
16901 CHECK(!GetPromise("s1")->HasHandler());
16902 CHECK(!GetPromise("s2")->HasHandler());
16903 CHECK(!GetPromise("s3")->HasHandler());
16904 CHECK_EQ(3, promise_reject_counter);
16905 CHECK_EQ(0, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016906 CHECK(RejectValue()->Equals(env.local(), v8_str("sss")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016907
16908 // Test stack frames.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016909 env->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016910
16911 ResetPromiseStates();
16912
16913 // Create promise t0, which is rejected in the constructor with an error.
16914 CompileRunWithOrigin(
16915 "var t0 = new Promise( \n"
16916 " function(res, rej) { \n"
16917 " reference_error; \n"
16918 " } \n"
16919 "); \n",
16920 "pro", 0, 0);
16921 CHECK(!GetPromise("t0")->HasHandler());
16922 CHECK_EQ(1, promise_reject_counter);
16923 CHECK_EQ(0, promise_revoke_counter);
16924 CHECK_EQ(2, promise_reject_frame_count);
16925 CHECK_EQ(3, promise_reject_line_number);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016926 CHECK_EQ(5, promise_reject_column_number);
16927 CHECK_EQ(3, promise_reject_msg_line_number);
16928 CHECK_EQ(5, promise_reject_msg_column_number);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016929
16930 ResetPromiseStates();
16931
16932 // Create promise u0 and chain u1 to it, which is rejected via throw.
16933 CompileRunWithOrigin(
16934 "var u0 = Promise.resolve(); \n"
16935 "var u1 = u0.then( \n"
16936 " function() { \n"
16937 " (function() { \n"
16938 " throw new Error(); \n"
16939 " })(); \n"
16940 " } \n"
16941 " ); \n",
16942 "pro", 0, 0);
16943 CHECK(GetPromise("u0")->HasHandler());
16944 CHECK(!GetPromise("u1")->HasHandler());
16945 CHECK_EQ(1, promise_reject_counter);
16946 CHECK_EQ(0, promise_revoke_counter);
16947 CHECK_EQ(2, promise_reject_frame_count);
16948 CHECK_EQ(5, promise_reject_line_number);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016949 CHECK_EQ(23, promise_reject_column_number);
16950 CHECK_EQ(5, promise_reject_msg_line_number);
16951 CHECK_EQ(23, promise_reject_msg_column_number);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016952
16953 // Throw in u3, which handles u1's rejection.
16954 CompileRunWithOrigin(
16955 "function f() { \n"
16956 " return (function() { \n"
16957 " return new Error(); \n"
16958 " })(); \n"
16959 "} \n"
16960 "var u2 = Promise.reject(f()); \n"
16961 "var u3 = u1.catch( \n"
16962 " function() { \n"
16963 " return u2; \n"
16964 " } \n"
16965 " ); \n",
16966 "pro", 0, 0);
16967 CHECK(GetPromise("u0")->HasHandler());
16968 CHECK(GetPromise("u1")->HasHandler());
16969 CHECK(GetPromise("u2")->HasHandler());
16970 CHECK(!GetPromise("u3")->HasHandler());
16971 CHECK_EQ(3, promise_reject_counter);
16972 CHECK_EQ(2, promise_revoke_counter);
16973 CHECK_EQ(3, promise_reject_frame_count);
16974 CHECK_EQ(3, promise_reject_line_number);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016975 CHECK_EQ(12, promise_reject_column_number);
16976 CHECK_EQ(3, promise_reject_msg_line_number);
16977 CHECK_EQ(12, promise_reject_msg_column_number);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016978
16979 ResetPromiseStates();
16980
16981 // Create promise rejected promise v0, which is incorrectly handled by v1
16982 // via chaining cycle.
16983 CompileRunWithOrigin(
16984 "var v0 = Promise.reject(); \n"
16985 "var v1 = v0.catch( \n"
16986 " function() { \n"
16987 " return v1; \n"
16988 " } \n"
16989 " ); \n",
16990 "pro", 0, 0);
16991 CHECK(GetPromise("v0")->HasHandler());
16992 CHECK(!GetPromise("v1")->HasHandler());
16993 CHECK_EQ(2, promise_reject_counter);
16994 CHECK_EQ(1, promise_revoke_counter);
16995 CHECK_EQ(0, promise_reject_frame_count);
16996 CHECK_EQ(-1, promise_reject_line_number);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016997 CHECK_EQ(-1, promise_reject_column_number);
16998
16999 ResetPromiseStates();
17000
17001 // Create promise t1, which rejects by throwing syntax error from eval.
17002 CompileRunWithOrigin(
17003 "var t1 = new Promise( \n"
17004 " function(res, rej) { \n"
17005 " var content = '\\n\\\n"
17006 " }'; \n"
17007 " eval(content); \n"
17008 " } \n"
17009 "); \n",
17010 "pro", 0, 0);
17011 CHECK(!GetPromise("t1")->HasHandler());
17012 CHECK_EQ(1, promise_reject_counter);
17013 CHECK_EQ(0, promise_revoke_counter);
17014 CHECK_EQ(2, promise_reject_frame_count);
17015 CHECK_EQ(5, promise_reject_line_number);
17016 CHECK_EQ(10, promise_reject_column_number);
17017 CHECK_EQ(2, promise_reject_msg_line_number);
17018 CHECK_EQ(7, promise_reject_msg_column_number);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017019}
17020
17021
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017022void AnalyzeStackOfEvalWithSourceURL(
17023 const v8::FunctionCallbackInfo<v8::Value>& args) {
17024 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017025 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017026 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
Ben Murdochf87a2032010-10-22 12:50:53 +010017027 CHECK_EQ(5, stackTrace->GetFrameCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017028 v8::Local<v8::String> url = v8_str("eval_url");
Ben Murdochf87a2032010-10-22 12:50:53 +010017029 for (int i = 0; i < 3; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017030 v8::Local<v8::String> name =
Ben Murdochf87a2032010-10-22 12:50:53 +010017031 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17032 CHECK(!name.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017033 CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
Ben Murdochf87a2032010-10-22 12:50:53 +010017034 }
Ben Murdochf87a2032010-10-22 12:50:53 +010017035}
17036
17037
17038TEST(SourceURLInStackTrace) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017039 v8::Isolate* isolate = CcTest::isolate();
17040 v8::HandleScope scope(isolate);
17041 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdochf87a2032010-10-22 12:50:53 +010017042 templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017043 v8::FunctionTemplate::New(isolate,
17044 AnalyzeStackOfEvalWithSourceURL));
Ben Murdochf87a2032010-10-22 12:50:53 +010017045 LocalContext context(0, templ);
17046
17047 const char *source =
17048 "function outer() {\n"
17049 "function bar() {\n"
17050 " AnalyzeStackOfEvalWithSourceURL();\n"
17051 "}\n"
17052 "function foo() {\n"
17053 "\n"
17054 " bar();\n"
17055 "}\n"
17056 "foo();\n"
17057 "}\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017058 "eval('(' + outer +')()%s');";
17059
17060 i::ScopedVector<char> code(1024);
17061 i::SNPrintF(code, source, "//# sourceURL=eval_url");
17062 CHECK(CompileRun(code.start())->IsUndefined());
17063 i::SNPrintF(code, source, "//@ sourceURL=eval_url");
17064 CHECK(CompileRun(code.start())->IsUndefined());
17065}
17066
17067
17068static int scriptIdInStack[2];
17069
17070void AnalyzeScriptIdInStack(
17071 const v8::FunctionCallbackInfo<v8::Value>& args) {
17072 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017073 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017074 args.GetIsolate(), 10, v8::StackTrace::kScriptId);
17075 CHECK_EQ(2, stackTrace->GetFrameCount());
17076 for (int i = 0; i < 2; i++) {
17077 scriptIdInStack[i] = stackTrace->GetFrame(i)->GetScriptId();
17078 }
17079}
17080
17081
17082TEST(ScriptIdInStackTrace) {
17083 v8::Isolate* isolate = CcTest::isolate();
17084 v8::HandleScope scope(isolate);
17085 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17086 templ->Set(v8_str("AnalyzeScriptIdInStack"),
17087 v8::FunctionTemplate::New(isolate, AnalyzeScriptIdInStack));
17088 LocalContext context(0, templ);
17089
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017090 v8::Local<v8::String> scriptSource = v8_str(
17091 "function foo() {\n"
17092 " AnalyzeScriptIdInStack();"
17093 "}\n"
17094 "foo();\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017095 v8::Local<v8::Script> script = CompileWithOrigin(scriptSource, "test");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017096 script->Run(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017097 for (int i = 0; i < 2; i++) {
17098 CHECK(scriptIdInStack[i] != v8::Message::kNoScriptIdInfo);
17099 CHECK_EQ(scriptIdInStack[i], script->GetUnboundScript()->GetId());
17100 }
17101}
17102
17103
17104void AnalyzeStackOfInlineScriptWithSourceURL(
17105 const v8::FunctionCallbackInfo<v8::Value>& args) {
17106 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017107 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017108 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
17109 CHECK_EQ(4, stackTrace->GetFrameCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017110 v8::Local<v8::String> url = v8_str("source_url");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017111 for (int i = 0; i < 3; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017112 v8::Local<v8::String> name =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017113 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17114 CHECK(!name.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017115 CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017116 }
17117}
17118
17119
17120TEST(InlineScriptWithSourceURLInStackTrace) {
17121 v8::Isolate* isolate = CcTest::isolate();
17122 v8::HandleScope scope(isolate);
17123 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17124 templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
17125 v8::FunctionTemplate::New(
17126 CcTest::isolate(), AnalyzeStackOfInlineScriptWithSourceURL));
17127 LocalContext context(0, templ);
17128
17129 const char *source =
17130 "function outer() {\n"
17131 "function bar() {\n"
17132 " AnalyzeStackOfInlineScriptWithSourceURL();\n"
17133 "}\n"
17134 "function foo() {\n"
17135 "\n"
17136 " bar();\n"
17137 "}\n"
17138 "foo();\n"
17139 "}\n"
17140 "outer()\n%s";
17141
17142 i::ScopedVector<char> code(1024);
17143 i::SNPrintF(code, source, "//# sourceURL=source_url");
17144 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
17145 i::SNPrintF(code, source, "//@ sourceURL=source_url");
17146 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
17147}
17148
17149
17150void AnalyzeStackOfDynamicScriptWithSourceURL(
17151 const v8::FunctionCallbackInfo<v8::Value>& args) {
17152 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017153 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017154 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
17155 CHECK_EQ(4, stackTrace->GetFrameCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017156 v8::Local<v8::String> url = v8_str("source_url");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017157 for (int i = 0; i < 3; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017158 v8::Local<v8::String> name =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017159 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17160 CHECK(!name.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017161 CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017162 }
17163}
17164
17165
17166TEST(DynamicWithSourceURLInStackTrace) {
17167 v8::Isolate* isolate = CcTest::isolate();
17168 v8::HandleScope scope(isolate);
17169 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17170 templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
17171 v8::FunctionTemplate::New(
17172 CcTest::isolate(), AnalyzeStackOfDynamicScriptWithSourceURL));
17173 LocalContext context(0, templ);
17174
17175 const char *source =
17176 "function outer() {\n"
17177 "function bar() {\n"
17178 " AnalyzeStackOfDynamicScriptWithSourceURL();\n"
17179 "}\n"
17180 "function foo() {\n"
17181 "\n"
17182 " bar();\n"
17183 "}\n"
17184 "foo();\n"
17185 "}\n"
17186 "outer()\n%s";
17187
17188 i::ScopedVector<char> code(1024);
17189 i::SNPrintF(code, source, "//# sourceURL=source_url");
17190 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
17191 i::SNPrintF(code, source, "//@ sourceURL=source_url");
17192 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
17193}
17194
17195
17196TEST(DynamicWithSourceURLInStackTraceString) {
17197 LocalContext context;
17198 v8::HandleScope scope(context->GetIsolate());
17199
17200 const char *source =
17201 "function outer() {\n"
17202 " function foo() {\n"
17203 " FAIL.FAIL;\n"
17204 " }\n"
17205 " foo();\n"
17206 "}\n"
17207 "outer()\n%s";
17208
17209 i::ScopedVector<char> code(1024);
17210 i::SNPrintF(code, source, "//# sourceURL=source_url");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017211 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017212 CompileRunWithOrigin(code.start(), "", 0, 0);
17213 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017214 v8::String::Utf8Value stack(
17215 try_catch.StackTrace(context.local()).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017216 CHECK(strstr(*stack, "at foo (source_url:3:5)") != NULL);
17217}
17218
17219
17220TEST(EvalWithSourceURLInMessageScriptResourceNameOrSourceURL) {
17221 LocalContext context;
17222 v8::HandleScope scope(context->GetIsolate());
17223
17224 const char *source =
17225 "function outer() {\n"
17226 " var scriptContents = \"function foo() { FAIL.FAIL; }\\\n"
17227 " //# sourceURL=source_url\";\n"
17228 " eval(scriptContents);\n"
17229 " foo(); }\n"
17230 "outer();\n"
17231 "//# sourceURL=outer_url";
17232
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017233 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017234 CompileRun(source);
17235 CHECK(try_catch.HasCaught());
17236
17237 Local<v8::Message> message = try_catch.Message();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017238 Local<Value> sourceURL = message->GetScriptOrigin().ResourceName();
17239 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(sourceURL), "source_url"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017240}
17241
17242
17243TEST(RecursionWithSourceURLInMessageScriptResourceNameOrSourceURL) {
17244 LocalContext context;
17245 v8::HandleScope scope(context->GetIsolate());
17246
17247 const char *source =
17248 "function outer() {\n"
17249 " var scriptContents = \"function boo(){ boo(); }\\\n"
17250 " //# sourceURL=source_url\";\n"
17251 " eval(scriptContents);\n"
17252 " boo(); }\n"
17253 "outer();\n"
17254 "//# sourceURL=outer_url";
17255
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017256 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017257 CompileRun(source);
17258 CHECK(try_catch.HasCaught());
17259
17260 Local<v8::Message> message = try_catch.Message();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017261 Local<Value> sourceURL = message->GetScriptOrigin().ResourceName();
17262 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(sourceURL), "source_url"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017263}
17264
17265
17266static void CreateGarbageInOldSpace() {
17267 i::Factory* factory = CcTest::i_isolate()->factory();
17268 v8::HandleScope scope(CcTest::isolate());
17269 i::AlwaysAllocateScope always_allocate(CcTest::i_isolate());
17270 for (int i = 0; i < 1000; i++) {
17271 factory->NewFixedArray(1000, i::TENURED);
17272 }
Ben Murdochf87a2032010-10-22 12:50:53 +010017273}
17274
17275
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017276// Test that idle notification can be handled and eventually collects garbage.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017277TEST(TestIdleNotification) {
17278 if (!i::FLAG_incremental_marking) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017279 const intptr_t MB = 1024 * 1024;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017280 const double IdlePauseInSeconds = 1.0;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017281 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017282 v8::HandleScope scope(env->GetIsolate());
17283 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
17284 CreateGarbageInOldSpace();
17285 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
17286 CHECK_GT(size_with_garbage, initial_size + MB);
17287 bool finished = false;
17288 for (int i = 0; i < 200 && !finished; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017289 if (i < 10 && CcTest::heap()->incremental_marking()->IsStopped()) {
17290 CcTest::heap()->StartIdleIncrementalMarking();
17291 }
17292 finished = env->GetIsolate()->IdleNotificationDeadline(
17293 (v8::base::TimeTicks::HighResolutionNow().ToInternalValue() /
17294 static_cast<double>(v8::base::Time::kMicrosecondsPerSecond)) +
17295 IdlePauseInSeconds);
17296 if (CcTest::heap()->mark_compact_collector()->sweeping_in_progress()) {
17297 CcTest::heap()->mark_compact_collector()->EnsureSweepingCompleted();
17298 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017299 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017300 intptr_t final_size = CcTest::heap()->SizeOfObjects();
17301 CHECK(finished);
17302 CHECK_LT(final_size, initial_size + 1);
Ben Murdochc7cc0282012-03-05 14:35:55 +000017303}
17304
Steve Blocka7e24c12009-10-30 11:49:00 +000017305
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017306TEST(Regress2333) {
17307 LocalContext env;
17308 for (int i = 0; i < 3; i++) {
17309 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
17310 }
17311}
17312
Steve Blocka7e24c12009-10-30 11:49:00 +000017313static uint32_t* stack_limit;
17314
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017315static void GetStackLimitCallback(
17316 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Block44f0eee2011-05-26 01:26:41 +010017317 stack_limit = reinterpret_cast<uint32_t*>(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017318 CcTest::i_isolate()->stack_guard()->real_climit());
Steve Blocka7e24c12009-10-30 11:49:00 +000017319}
17320
17321
17322// Uses the address of a local variable to determine the stack top now.
17323// Given a size, returns an address that is that far from the current
17324// top of stack.
17325static uint32_t* ComputeStackLimit(uint32_t size) {
17326 uint32_t* answer = &size - (size / sizeof(size));
17327 // If the size is very large and the stack is very near the bottom of
17328 // memory then the calculation above may wrap around and give an address
17329 // that is above the (downwards-growing) stack. In that case we return
17330 // a very low address.
17331 if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
17332 return answer;
17333}
17334
17335
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017336// We need at least 165kB for an x64 debug build with clang and ASAN.
17337static const int stack_breathing_room = 256 * i::KB;
17338
17339
17340TEST(SetStackLimit) {
17341 uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
Steve Blocka7e24c12009-10-30 11:49:00 +000017342
17343 // Set stack limit.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017344 CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
Steve Blocka7e24c12009-10-30 11:49:00 +000017345
17346 // Execute a script.
Steve Blocka7e24c12009-10-30 11:49:00 +000017347 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017348 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000017349 Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017350 v8::FunctionTemplate::New(env->GetIsolate(), GetStackLimitCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017351 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
17352 CHECK(env->Global()
17353 ->Set(env.local(), v8_str("get_stack_limit"), fun)
17354 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000017355 CompileRun("get_stack_limit();");
17356
17357 CHECK(stack_limit == set_limit);
17358}
17359
17360
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017361TEST(SetStackLimitInThread) {
Steve Blocka7e24c12009-10-30 11:49:00 +000017362 uint32_t* set_limit;
17363 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017364 v8::Locker locker(CcTest::isolate());
17365 set_limit = ComputeStackLimit(stack_breathing_room);
Steve Blocka7e24c12009-10-30 11:49:00 +000017366
17367 // Set stack limit.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017368 CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
Steve Blocka7e24c12009-10-30 11:49:00 +000017369
17370 // Execute a script.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017371 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000017372 LocalContext env;
17373 Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017374 v8::FunctionTemplate::New(CcTest::isolate(), GetStackLimitCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017375 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
17376 CHECK(env->Global()
17377 ->Set(env.local(), v8_str("get_stack_limit"), fun)
17378 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000017379 CompileRun("get_stack_limit();");
17380
17381 CHECK(stack_limit == set_limit);
17382 }
17383 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017384 v8::Locker locker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000017385 CHECK(stack_limit == set_limit);
17386 }
17387}
Steve Block3ce2e202009-11-05 08:53:23 +000017388
17389
17390THREADED_TEST(GetHeapStatistics) {
Steve Block3ce2e202009-11-05 08:53:23 +000017391 LocalContext c1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017392 v8::HandleScope scope(c1->GetIsolate());
Steve Block3ce2e202009-11-05 08:53:23 +000017393 v8::HeapStatistics heap_statistics;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017394 CHECK_EQ(0u, heap_statistics.total_heap_size());
17395 CHECK_EQ(0u, heap_statistics.used_heap_size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017396 c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
Steve Blockd0582a62009-12-15 09:54:21 +000017397 CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
17398 CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
17399}
17400
17401
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017402class VisitorImpl : public v8::ExternalResourceVisitor {
17403 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017404 explicit VisitorImpl(TestResource** resource) {
17405 for (int i = 0; i < 4; i++) {
17406 resource_[i] = resource[i];
17407 found_resource_[i] = false;
17408 }
17409 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017410 virtual ~VisitorImpl() {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017411 virtual void VisitExternalString(v8::Local<v8::String> string) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017412 if (!string->IsExternal()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017413 CHECK(string->IsExternalOneByte());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017414 return;
17415 }
17416 v8::String::ExternalStringResource* resource =
17417 string->GetExternalStringResource();
17418 CHECK(resource);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017419 for (int i = 0; i < 4; i++) {
17420 if (resource_[i] == resource) {
17421 CHECK(!found_resource_[i]);
17422 found_resource_[i] = true;
17423 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017424 }
17425 }
17426 void CheckVisitedResources() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017427 for (int i = 0; i < 4; i++) {
17428 CHECK(found_resource_[i]);
17429 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017430 }
17431
17432 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017433 v8::String::ExternalStringResource* resource_[4];
17434 bool found_resource_[4];
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017435};
17436
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017437
17438TEST(ExternalizeOldSpaceTwoByteCons) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017439 v8::Isolate* isolate = CcTest::isolate();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017440 LocalContext env;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017441 v8::HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017442 v8::Local<v8::String> cons =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017443 CompileRun("'Romeo Montague ' + 'Juliet Capulet'")
17444 ->ToString(env.local())
17445 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017446 CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
17447 CcTest::heap()->CollectAllAvailableGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017448 CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017449
17450 TestResource* resource = new TestResource(
17451 AsciiToTwoByteString("Romeo Montague Juliet Capulet"));
17452 cons->MakeExternal(resource);
17453
17454 CHECK(cons->IsExternal());
17455 CHECK_EQ(resource, cons->GetExternalStringResource());
17456 String::Encoding encoding;
17457 CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
17458 CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
17459}
17460
17461
17462TEST(ExternalizeOldSpaceOneByteCons) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017463 v8::Isolate* isolate = CcTest::isolate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017464 LocalContext env;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017465 v8::HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017466 v8::Local<v8::String> cons =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017467 CompileRun("'Romeo Montague ' + 'Juliet Capulet'")
17468 ->ToString(env.local())
17469 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017470 CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
17471 CcTest::heap()->CollectAllAvailableGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017472 CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017473
17474 TestOneByteResource* resource =
17475 new TestOneByteResource(i::StrDup("Romeo Montague Juliet Capulet"));
17476 cons->MakeExternal(resource);
17477
17478 CHECK(cons->IsExternalOneByte());
17479 CHECK_EQ(resource, cons->GetExternalOneByteStringResource());
17480 String::Encoding encoding;
17481 CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
17482 CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
17483}
17484
17485
17486TEST(VisitExternalStrings) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017487 v8::Isolate* isolate = CcTest::isolate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017488 LocalContext env;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017489 v8::HandleScope scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017490 const char* string = "Some string";
17491 uint16_t* two_byte_string = AsciiToTwoByteString(string);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017492 TestResource* resource[4];
17493 resource[0] = new TestResource(two_byte_string);
17494 v8::Local<v8::String> string0 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017495 v8::String::NewExternalTwoByte(env->GetIsolate(), resource[0])
17496 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017497 resource[1] = new TestResource(two_byte_string, NULL, false);
17498 v8::Local<v8::String> string1 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017499 v8::String::NewExternalTwoByte(env->GetIsolate(), resource[1])
17500 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017501
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017502 // Externalized symbol.
17503 resource[2] = new TestResource(two_byte_string, NULL, false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017504 v8::Local<v8::String> string2 =
17505 v8::String::NewFromUtf8(env->GetIsolate(), string,
17506 v8::NewStringType::kInternalized)
17507 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017508 CHECK(string2->MakeExternal(resource[2]));
17509
17510 // Symbolized External.
17511 resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
17512 v8::Local<v8::String> string3 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017513 v8::String::NewExternalTwoByte(env->GetIsolate(), resource[3])
17514 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017515 CcTest::heap()->CollectAllAvailableGarbage(); // Tenure string.
17516 // Turn into a symbol.
17517 i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
17518 CHECK(!CcTest::i_isolate()->factory()->InternalizeString(
17519 string3_i).is_null());
17520 CHECK(string3_i->IsInternalizedString());
17521
17522 // We need to add usages for string* to avoid warnings in GCC 4.7
17523 CHECK(string0->IsExternal());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017524 CHECK(string1->IsExternal());
17525 CHECK(string2->IsExternal());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017526 CHECK(string3->IsExternal());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017527
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017528 VisitorImpl visitor(resource);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017529 isolate->VisitExternalResources(&visitor);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017530 visitor.CheckVisitedResources();
17531}
17532
17533
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017534TEST(ExternalStringCollectedAtTearDown) {
17535 int destroyed = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017536 v8::Isolate::CreateParams create_params;
17537 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
17538 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017539 { v8::Isolate::Scope isolate_scope(isolate);
17540 v8::HandleScope handle_scope(isolate);
17541 const char* s = "One string to test them all, one string to find them.";
17542 TestOneByteResource* inscription =
17543 new TestOneByteResource(i::StrDup(s), &destroyed);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017544 v8::Local<v8::String> ring =
17545 v8::String::NewExternalOneByte(isolate, inscription).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017546 // Ring is still alive. Orcs are roaming freely across our lands.
17547 CHECK_EQ(0, destroyed);
17548 USE(ring);
17549 }
17550
17551 isolate->Dispose();
17552 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
17553 CHECK_EQ(1, destroyed);
17554}
17555
17556
17557TEST(ExternalInternalizedStringCollectedAtTearDown) {
17558 int destroyed = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017559 v8::Isolate::CreateParams create_params;
17560 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
17561 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017562 { v8::Isolate::Scope isolate_scope(isolate);
17563 LocalContext env(isolate);
17564 v8::HandleScope handle_scope(isolate);
17565 CompileRun("var ring = 'One string to test them all';");
17566 const char* s = "One string to test them all";
17567 TestOneByteResource* inscription =
17568 new TestOneByteResource(i::StrDup(s), &destroyed);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017569 v8::Local<v8::String> ring =
17570 CompileRun("ring")->ToString(env.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017571 CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
17572 ring->MakeExternal(inscription);
17573 // Ring is still alive. Orcs are roaming freely across our lands.
17574 CHECK_EQ(0, destroyed);
17575 USE(ring);
17576 }
17577
17578 isolate->Dispose();
17579 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
17580 CHECK_EQ(1, destroyed);
17581}
17582
17583
17584TEST(ExternalInternalizedStringCollectedAtGC) {
17585 int destroyed = 0;
17586 { LocalContext env;
17587 v8::HandleScope handle_scope(env->GetIsolate());
17588 CompileRun("var ring = 'One string to test them all';");
17589 const char* s = "One string to test them all";
17590 TestOneByteResource* inscription =
17591 new TestOneByteResource(i::StrDup(s), &destroyed);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017592 v8::Local<v8::String> ring = CompileRun("ring").As<v8::String>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017593 CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
17594 ring->MakeExternal(inscription);
17595 // Ring is still alive. Orcs are roaming freely across our lands.
17596 CHECK_EQ(0, destroyed);
17597 USE(ring);
17598 }
17599
17600 // Garbage collector deals swift blows to evil.
17601 CcTest::i_isolate()->compilation_cache()->Clear();
17602 CcTest::heap()->CollectAllAvailableGarbage();
17603
17604 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
17605 CHECK_EQ(1, destroyed);
17606}
17607
17608
Steve Blockd0582a62009-12-15 09:54:21 +000017609static double DoubleFromBits(uint64_t value) {
17610 double target;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017611 i::MemCopy(&target, &value, sizeof(target));
Steve Blockd0582a62009-12-15 09:54:21 +000017612 return target;
17613}
17614
17615
17616static uint64_t DoubleToBits(double value) {
17617 uint64_t target;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017618 i::MemCopy(&target, &value, sizeof(target));
Steve Blockd0582a62009-12-15 09:54:21 +000017619 return target;
17620}
17621
17622
17623static double DoubleToDateTime(double input) {
17624 double date_limit = 864e13;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017625 if (std::isnan(input) || input < -date_limit || input > date_limit) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017626 return std::numeric_limits<double>::quiet_NaN();
Steve Blockd0582a62009-12-15 09:54:21 +000017627 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017628 return (input < 0) ? -(std::floor(-input)) : std::floor(input);
Steve Blockd0582a62009-12-15 09:54:21 +000017629}
17630
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017631
Steve Blockd0582a62009-12-15 09:54:21 +000017632// We don't have a consistent way to write 64-bit constants syntactically, so we
17633// split them into two 32-bit constants and combine them programmatically.
17634static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
17635 return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
17636}
17637
17638
17639THREADED_TEST(QuietSignalingNaNs) {
Steve Blockd0582a62009-12-15 09:54:21 +000017640 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017641 v8::Isolate* isolate = context->GetIsolate();
17642 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017643 v8::TryCatch try_catch(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000017644
17645 // Special double values.
17646 double snan = DoubleFromBits(0x7ff00000, 0x00000001);
17647 double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
17648 double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
17649 double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
17650 double min_normal = DoubleFromBits(0x00100000, 0x00000000);
17651 double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
17652 double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
17653
17654 // Date values are capped at +/-100000000 days (times 864e5 ms per day)
17655 // on either side of the epoch.
17656 double date_limit = 864e13;
17657
17658 double test_values[] = {
17659 snan,
17660 qnan,
17661 infinity,
17662 max_normal,
17663 date_limit + 1,
17664 date_limit,
17665 min_normal,
17666 max_denormal,
17667 min_denormal,
17668 0,
17669 -0,
17670 -min_denormal,
17671 -max_denormal,
17672 -min_normal,
17673 -date_limit,
17674 -date_limit - 1,
17675 -max_normal,
17676 -infinity,
17677 -qnan,
17678 -snan
17679 };
17680 int num_test_values = 20;
17681
17682 for (int i = 0; i < num_test_values; i++) {
17683 double test_value = test_values[i];
17684
17685 // Check that Number::New preserves non-NaNs and quiets SNaNs.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017686 v8::Local<v8::Value> number = v8::Number::New(isolate, test_value);
17687 double stored_number = number->NumberValue(context.local()).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017688 if (!std::isnan(test_value)) {
Steve Blockd0582a62009-12-15 09:54:21 +000017689 CHECK_EQ(test_value, stored_number);
17690 } else {
17691 uint64_t stored_bits = DoubleToBits(stored_number);
17692 // Check if quiet nan (bits 51..62 all set).
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017693#if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017694 !defined(_MIPS_ARCH_MIPS64R6) && !defined(_MIPS_ARCH_MIPS32R6) && \
17695 !defined(USE_SIMULATOR)
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017696 // Most significant fraction bit for quiet nan is set to 0
17697 // on MIPS architecture. Allowed by IEEE-754.
17698 CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
17699#else
Steve Blockd0582a62009-12-15 09:54:21 +000017700 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017701#endif
Steve Blockd0582a62009-12-15 09:54:21 +000017702 }
17703
17704 // Check that Date::New preserves non-NaNs in the date range and
17705 // quiets SNaNs.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017706 v8::Local<v8::Value> date =
17707 v8::Date::New(context.local(), test_value).ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +000017708 double expected_stored_date = DoubleToDateTime(test_value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017709 double stored_date = date->NumberValue(context.local()).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017710 if (!std::isnan(expected_stored_date)) {
Steve Blockd0582a62009-12-15 09:54:21 +000017711 CHECK_EQ(expected_stored_date, stored_date);
17712 } else {
17713 uint64_t stored_bits = DoubleToBits(stored_date);
17714 // Check if quiet nan (bits 51..62 all set).
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017715#if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017716 !defined(_MIPS_ARCH_MIPS64R6) && !defined(_MIPS_ARCH_MIPS32R6) && \
17717 !defined(USE_SIMULATOR)
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017718 // Most significant fraction bit for quiet nan is set to 0
17719 // on MIPS architecture. Allowed by IEEE-754.
17720 CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
17721#else
Steve Blockd0582a62009-12-15 09:54:21 +000017722 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017723#endif
Steve Blockd0582a62009-12-15 09:54:21 +000017724 }
17725 }
17726}
17727
17728
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017729static void SpaghettiIncident(
17730 const v8::FunctionCallbackInfo<v8::Value>& args) {
17731 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017732 v8::TryCatch tc(args.GetIsolate());
17733 v8::MaybeLocal<v8::String> str(
17734 args[0]->ToString(args.GetIsolate()->GetCurrentContext()));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017735 USE(str);
Steve Blockd0582a62009-12-15 09:54:21 +000017736 if (tc.HasCaught())
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017737 tc.ReThrow();
Steve Blockd0582a62009-12-15 09:54:21 +000017738}
17739
17740
17741// Test that an exception can be propagated down through a spaghetti
17742// stack using ReThrow.
17743THREADED_TEST(SpaghettiStackReThrow) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017744 v8::Isolate* isolate = CcTest::isolate();
17745 v8::HandleScope scope(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000017746 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017747 context->Global()
17748 ->Set(context.local(), v8_str("s"),
17749 v8::FunctionTemplate::New(isolate, SpaghettiIncident)
17750 ->GetFunction(context.local())
17751 .ToLocalChecked())
17752 .FromJust();
17753 v8::TryCatch try_catch(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000017754 CompileRun(
17755 "var i = 0;"
17756 "var o = {"
17757 " toString: function () {"
17758 " if (i == 10) {"
17759 " throw 'Hey!';"
17760 " } else {"
17761 " i++;"
17762 " return s(o);"
17763 " }"
17764 " }"
17765 "};"
17766 "s(o);");
17767 CHECK(try_catch.HasCaught());
17768 v8::String::Utf8Value value(try_catch.Exception());
17769 CHECK_EQ(0, strcmp(*value, "Hey!"));
17770}
17771
17772
Steve Blockd0582a62009-12-15 09:54:21 +000017773TEST(Regress528) {
17774 v8::V8::Initialize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017775 v8::Isolate* isolate = CcTest::isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017776 i::FLAG_retain_maps_for_n_gc = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017777 v8::HandleScope scope(isolate);
17778 v8::Local<Context> other_context;
Steve Blockd0582a62009-12-15 09:54:21 +000017779 int gc_count;
17780
17781 // Create a context used to keep the code from aging in the compilation
17782 // cache.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017783 other_context = Context::New(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000017784
17785 // Context-dependent context data creates reference from the compilation
17786 // cache to the global object.
17787 const char* source_simple = "1";
Steve Blockd0582a62009-12-15 09:54:21 +000017788 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017789 v8::HandleScope scope(isolate);
17790 v8::Local<Context> context = Context::New(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000017791
17792 context->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017793 Local<v8::String> obj = v8_str("");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017794 context->SetEmbedderData(0, obj);
Steve Blockd0582a62009-12-15 09:54:21 +000017795 CompileRun(source_simple);
17796 context->Exit();
17797 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017798 isolate->ContextDisposedNotification();
Steve Blockd0582a62009-12-15 09:54:21 +000017799 for (gc_count = 1; gc_count < 10; gc_count++) {
17800 other_context->Enter();
17801 CompileRun(source_simple);
17802 other_context->Exit();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017803 CcTest::heap()->CollectAllGarbage();
Steve Blockd0582a62009-12-15 09:54:21 +000017804 if (GetGlobalObjectsCount() == 1) break;
17805 }
17806 CHECK_GE(2, gc_count);
17807 CHECK_EQ(1, GetGlobalObjectsCount());
17808
17809 // Eval in a function creates reference from the compilation cache to the
17810 // global object.
17811 const char* source_eval = "function f(){eval('1')}; f()";
Steve Blockd0582a62009-12-15 09:54:21 +000017812 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017813 v8::HandleScope scope(isolate);
17814 v8::Local<Context> context = Context::New(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000017815
17816 context->Enter();
17817 CompileRun(source_eval);
17818 context->Exit();
17819 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017820 isolate->ContextDisposedNotification();
Steve Blockd0582a62009-12-15 09:54:21 +000017821 for (gc_count = 1; gc_count < 10; gc_count++) {
17822 other_context->Enter();
17823 CompileRun(source_eval);
17824 other_context->Exit();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017825 CcTest::heap()->CollectAllGarbage();
Steve Blockd0582a62009-12-15 09:54:21 +000017826 if (GetGlobalObjectsCount() == 1) break;
17827 }
17828 CHECK_GE(2, gc_count);
17829 CHECK_EQ(1, GetGlobalObjectsCount());
17830
17831 // Looking up the line number for an exception creates reference from the
17832 // compilation cache to the global object.
17833 const char* source_exception = "function f(){throw 1;} f()";
Steve Blockd0582a62009-12-15 09:54:21 +000017834 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017835 v8::HandleScope scope(isolate);
17836 v8::Local<Context> context = Context::New(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000017837
17838 context->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017839 v8::TryCatch try_catch(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000017840 CompileRun(source_exception);
17841 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017842 v8::Local<v8::Message> message = try_catch.Message();
Steve Blockd0582a62009-12-15 09:54:21 +000017843 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017844 CHECK_EQ(1, message->GetLineNumber(context).FromJust());
Steve Blockd0582a62009-12-15 09:54:21 +000017845 context->Exit();
17846 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017847 isolate->ContextDisposedNotification();
Steve Blockd0582a62009-12-15 09:54:21 +000017848 for (gc_count = 1; gc_count < 10; gc_count++) {
17849 other_context->Enter();
17850 CompileRun(source_exception);
17851 other_context->Exit();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017852 CcTest::heap()->CollectAllGarbage();
Steve Blockd0582a62009-12-15 09:54:21 +000017853 if (GetGlobalObjectsCount() == 1) break;
17854 }
17855 CHECK_GE(2, gc_count);
17856 CHECK_EQ(1, GetGlobalObjectsCount());
17857
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017858 isolate->ContextDisposedNotification();
Steve Block3ce2e202009-11-05 08:53:23 +000017859}
Andrei Popescu402d9372010-02-26 13:31:12 +000017860
17861
17862THREADED_TEST(ScriptOrigin) {
Andrei Popescu402d9372010-02-26 13:31:12 +000017863 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017864 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017865 v8::ScriptOrigin origin = v8::ScriptOrigin(
17866 v8_str("test"), v8::Integer::New(env->GetIsolate(), 1),
17867 v8::Integer::New(env->GetIsolate(), 1), v8::True(env->GetIsolate()),
17868 v8::Local<v8::Integer>(), v8::True(env->GetIsolate()),
17869 v8_str("http://sourceMapUrl"), v8::True(env->GetIsolate()));
17870 v8::Local<v8::String> script = v8_str("function f() {}\n\nfunction g() {}");
17871 v8::Script::Compile(env.local(), script, &origin)
17872 .ToLocalChecked()
17873 ->Run(env.local())
17874 .ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000017875 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017876 env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
Andrei Popescu402d9372010-02-26 13:31:12 +000017877 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017878 env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
Andrei Popescu402d9372010-02-26 13:31:12 +000017879
17880 v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017881 CHECK_EQ(0, strcmp("test",
17882 *v8::String::Utf8Value(script_origin_f.ResourceName())));
17883 CHECK_EQ(
17884 1,
17885 script_origin_f.ResourceLineOffset()->Int32Value(env.local()).FromJust());
17886 CHECK(script_origin_f.Options().IsSharedCrossOrigin());
17887 CHECK(script_origin_f.Options().IsEmbedderDebugScript());
17888 CHECK(script_origin_f.Options().IsOpaque());
17889 printf("is name = %d\n", script_origin_f.SourceMapUrl()->IsUndefined());
17890
17891 CHECK_EQ(0, strcmp("http://sourceMapUrl",
17892 *v8::String::Utf8Value(script_origin_f.SourceMapUrl())));
Andrei Popescu402d9372010-02-26 13:31:12 +000017893
17894 v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017895 CHECK_EQ(0, strcmp("test",
17896 *v8::String::Utf8Value(script_origin_g.ResourceName())));
17897 CHECK_EQ(
17898 1,
17899 script_origin_g.ResourceLineOffset()->Int32Value(env.local()).FromJust());
17900 CHECK(script_origin_g.Options().IsSharedCrossOrigin());
17901 CHECK(script_origin_g.Options().IsEmbedderDebugScript());
17902 CHECK(script_origin_g.Options().IsOpaque());
17903 CHECK_EQ(0, strcmp("http://sourceMapUrl",
17904 *v8::String::Utf8Value(script_origin_g.SourceMapUrl())));
Andrei Popescu402d9372010-02-26 13:31:12 +000017905}
17906
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017907
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017908THREADED_TEST(FunctionGetInferredName) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017909 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017910 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017911 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
17912 v8::Local<v8::String> script =
17913 v8_str("var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
17914 v8::Script::Compile(env.local(), script, &origin)
17915 .ToLocalChecked()
17916 ->Run(env.local())
17917 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017918 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017919 env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
17920 CHECK_EQ(0,
17921 strcmp("foo.bar.baz", *v8::String::Utf8Value(f->GetInferredName())));
17922}
17923
17924
17925THREADED_TEST(FunctionGetDebugName) {
17926 LocalContext env;
17927 v8::HandleScope scope(env->GetIsolate());
17928 const char* code =
17929 "var error = false;"
17930 "function a() { this.x = 1; };"
17931 "a.displayName = 'display_a';"
17932 "var b = (function() {"
17933 " var f = function() { this.x = 2; };"
17934 " f.displayName = 'display_b';"
17935 " return f;"
17936 "})();"
17937 "var c = function() {};"
17938 "c.__defineGetter__('displayName', function() {"
17939 " error = true;"
17940 " throw new Error();"
17941 "});"
17942 "function d() {};"
17943 "d.__defineGetter__('displayName', function() {"
17944 " error = true;"
17945 " return 'wrong_display_name';"
17946 "});"
17947 "function e() {};"
17948 "e.displayName = 'wrong_display_name';"
17949 "e.__defineSetter__('displayName', function() {"
17950 " error = true;"
17951 " throw new Error();"
17952 "});"
17953 "function f() {};"
17954 "f.displayName = { 'foo': 6, toString: function() {"
17955 " error = true;"
17956 " return 'wrong_display_name';"
17957 "}};"
17958 "var g = function() {"
17959 " arguments.callee.displayName = 'set_in_runtime';"
17960 "}; g();"
17961 "var h = function() {};"
17962 "h.displayName = 'displayName';"
17963 "Object.defineProperty(h, 'name', { value: 'function.name' });"
17964 "var i = function() {};"
17965 "i.displayName = 239;"
17966 "Object.defineProperty(i, 'name', { value: 'function.name' });"
17967 "var j = function() {};"
17968 "Object.defineProperty(j, 'name', { value: 'function.name' });"
17969 "var foo = { bar : { baz : function() {}}}; var k = foo.bar.baz;";
17970 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
17971 v8::Script::Compile(env.local(), v8_str(code), &origin)
17972 .ToLocalChecked()
17973 ->Run(env.local())
17974 .ToLocalChecked();
17975 v8::Local<v8::Value> error =
17976 env->Global()->Get(env.local(), v8_str("error")).ToLocalChecked();
17977 CHECK_EQ(false, error->BooleanValue(env.local()).FromJust());
17978 const char* functions[] = {"a", "display_a",
17979 "b", "display_b",
17980 "c", "c",
17981 "d", "d",
17982 "e", "e",
17983 "f", "f",
17984 "g", "set_in_runtime",
17985 "h", "displayName",
17986 "i", "function.name",
17987 "j", "function.name",
17988 "k", "foo.bar.baz"};
17989 for (size_t i = 0; i < sizeof(functions) / sizeof(functions[0]) / 2; ++i) {
17990 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
17991 env->Global()
17992 ->Get(env.local(),
17993 v8::String::NewFromUtf8(env->GetIsolate(), functions[i * 2],
17994 v8::NewStringType::kNormal)
17995 .ToLocalChecked())
17996 .ToLocalChecked());
17997 CHECK_EQ(0, strcmp(functions[i * 2 + 1],
17998 *v8::String::Utf8Value(f->GetDebugName())));
17999 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018000}
Andrei Popescu402d9372010-02-26 13:31:12 +000018001
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018002
18003THREADED_TEST(FunctionGetDisplayName) {
Andrei Popescu402d9372010-02-26 13:31:12 +000018004 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018005 v8::HandleScope scope(env->GetIsolate());
18006 const char* code = "var error = false;"
18007 "function a() { this.x = 1; };"
18008 "a.displayName = 'display_a';"
18009 "var b = (function() {"
18010 " var f = function() { this.x = 2; };"
18011 " f.displayName = 'display_b';"
18012 " return f;"
18013 "})();"
18014 "var c = function() {};"
18015 "c.__defineGetter__('displayName', function() {"
18016 " error = true;"
18017 " throw new Error();"
18018 "});"
18019 "function d() {};"
18020 "d.__defineGetter__('displayName', function() {"
18021 " error = true;"
18022 " return 'wrong_display_name';"
18023 "});"
18024 "function e() {};"
18025 "e.displayName = 'wrong_display_name';"
18026 "e.__defineSetter__('displayName', function() {"
18027 " error = true;"
18028 " throw new Error();"
18029 "});"
18030 "function f() {};"
18031 "f.displayName = { 'foo': 6, toString: function() {"
18032 " error = true;"
18033 " return 'wrong_display_name';"
18034 "}};"
18035 "var g = function() {"
18036 " arguments.callee.displayName = 'set_in_runtime';"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018037 "}; g();";
18038 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
18039 v8::Script::Compile(env.local(), v8_str(code), &origin)
18040 .ToLocalChecked()
18041 ->Run(env.local())
18042 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018043 v8::Local<v8::Value> error =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018044 env->Global()->Get(env.local(), v8_str("error")).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018045 v8::Local<v8::Function> a = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018046 env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018047 v8::Local<v8::Function> b = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018048 env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018049 v8::Local<v8::Function> c = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018050 env->Global()->Get(env.local(), v8_str("c")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018051 v8::Local<v8::Function> d = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018052 env->Global()->Get(env.local(), v8_str("d")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018053 v8::Local<v8::Function> e = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018054 env->Global()->Get(env.local(), v8_str("e")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018055 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018056 env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018057 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018058 env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
18059 CHECK_EQ(false, error->BooleanValue(env.local()).FromJust());
18060 CHECK_EQ(0, strcmp("display_a", *v8::String::Utf8Value(a->GetDisplayName())));
18061 CHECK_EQ(0, strcmp("display_b", *v8::String::Utf8Value(b->GetDisplayName())));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018062 CHECK(c->GetDisplayName()->IsUndefined());
18063 CHECK(d->GetDisplayName()->IsUndefined());
18064 CHECK(e->GetDisplayName()->IsUndefined());
18065 CHECK(f->GetDisplayName()->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018066 CHECK_EQ(
18067 0, strcmp("set_in_runtime", *v8::String::Utf8Value(g->GetDisplayName())));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018068}
18069
18070
18071THREADED_TEST(ScriptLineNumber) {
18072 LocalContext env;
18073 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018074 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
18075 v8::Local<v8::String> script = v8_str("function f() {}\n\nfunction g() {}");
18076 v8::Script::Compile(env.local(), script, &origin)
18077 .ToLocalChecked()
18078 ->Run(env.local())
18079 .ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000018080 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018081 env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
Andrei Popescu402d9372010-02-26 13:31:12 +000018082 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018083 env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
Andrei Popescu402d9372010-02-26 13:31:12 +000018084 CHECK_EQ(0, f->GetScriptLineNumber());
18085 CHECK_EQ(2, g->GetScriptLineNumber());
18086}
18087
18088
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018089THREADED_TEST(ScriptColumnNumber) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018090 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018091 v8::Isolate* isolate = env->GetIsolate();
18092 v8::HandleScope scope(isolate);
18093 v8::ScriptOrigin origin =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018094 v8::ScriptOrigin(v8_str("test"), v8::Integer::New(isolate, 3),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018095 v8::Integer::New(isolate, 2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018096 v8::Local<v8::String> script =
18097 v8_str("function foo() {}\n\n function bar() {}");
18098 v8::Script::Compile(env.local(), script, &origin)
18099 .ToLocalChecked()
18100 ->Run(env.local())
18101 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018102 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018103 env->Global()->Get(env.local(), v8_str("foo")).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018104 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018105 env->Global()->Get(env.local(), v8_str("bar")).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018106 CHECK_EQ(14, foo->GetScriptColumnNumber());
18107 CHECK_EQ(17, bar->GetScriptColumnNumber());
18108}
18109
18110
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018111THREADED_TEST(FunctionIsBuiltin) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018112 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018113 v8::Isolate* isolate = env->GetIsolate();
18114 v8::HandleScope scope(isolate);
18115 v8::Local<v8::Function> f;
18116 f = v8::Local<v8::Function>::Cast(CompileRun("Math.floor"));
18117 CHECK(f->IsBuiltin());
18118 f = v8::Local<v8::Function>::Cast(CompileRun("Object"));
18119 CHECK(f->IsBuiltin());
18120 f = v8::Local<v8::Function>::Cast(CompileRun("Object.__defineSetter__"));
18121 CHECK(f->IsBuiltin());
18122 f = v8::Local<v8::Function>::Cast(CompileRun("Array.prototype.toString"));
18123 CHECK(f->IsBuiltin());
18124 f = v8::Local<v8::Function>::Cast(CompileRun("function a() {}; a;"));
18125 CHECK(!f->IsBuiltin());
18126}
18127
18128
18129THREADED_TEST(FunctionGetScriptId) {
18130 LocalContext env;
18131 v8::Isolate* isolate = env->GetIsolate();
18132 v8::HandleScope scope(isolate);
18133 v8::ScriptOrigin origin =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018134 v8::ScriptOrigin(v8_str("test"), v8::Integer::New(isolate, 3),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018135 v8::Integer::New(isolate, 2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018136 v8::Local<v8::String> scriptSource =
18137 v8_str("function foo() {}\n\n function bar() {}");
18138 v8::Local<v8::Script> script(
18139 v8::Script::Compile(env.local(), scriptSource, &origin).ToLocalChecked());
18140 script->Run(env.local()).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018141 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018142 env->Global()->Get(env.local(), v8_str("foo")).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018143 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018144 env->Global()->Get(env.local(), v8_str("bar")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018145 CHECK_EQ(script->GetUnboundScript()->GetId(), foo->ScriptId());
18146 CHECK_EQ(script->GetUnboundScript()->GetId(), bar->ScriptId());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018147}
18148
18149
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018150THREADED_TEST(FunctionGetBoundFunction) {
18151 LocalContext env;
18152 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018153 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
18154 v8::Local<v8::String> script = v8_str(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018155 "var a = new Object();\n"
18156 "a.x = 1;\n"
18157 "function f () { return this.x };\n"
18158 "var g = f.bind(a);\n"
18159 "var b = g();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018160 v8::Script::Compile(env.local(), script, &origin)
18161 .ToLocalChecked()
18162 ->Run(env.local())
18163 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018164 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018165 env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018166 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018167 env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018168 CHECK(g->GetBoundFunction()->IsFunction());
18169 Local<v8::Function> original_function = Local<v8::Function>::Cast(
18170 g->GetBoundFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018171 CHECK(f->GetName()
18172 ->Equals(env.local(), original_function->GetName())
18173 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018174 CHECK_EQ(f->GetScriptLineNumber(), original_function->GetScriptLineNumber());
18175 CHECK_EQ(f->GetScriptColumnNumber(),
18176 original_function->GetScriptColumnNumber());
Andrei Popescu402d9372010-02-26 13:31:12 +000018177}
18178
18179
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018180static void GetterWhichReturns42(
18181 Local<String> name,
18182 const v8::PropertyCallbackInfo<v8::Value>& info) {
18183 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18184 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
18185 info.GetReturnValue().Set(v8_num(42));
18186}
18187
18188
18189static void SetterWhichSetsYOnThisTo23(
18190 Local<String> name,
18191 Local<Value> value,
18192 const v8::PropertyCallbackInfo<void>& info) {
18193 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18194 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018195 Local<Object>::Cast(info.This())
18196 ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
18197 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018198}
18199
18200
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018201void FooGetInterceptor(Local<Name> name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018202 const v8::PropertyCallbackInfo<v8::Value>& info) {
18203 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18204 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018205 if (!name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
18206 .FromJust()) {
18207 return;
18208 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018209 info.GetReturnValue().Set(v8_num(42));
18210}
18211
18212
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018213void FooSetInterceptor(Local<Name> name, Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018214 const v8::PropertyCallbackInfo<v8::Value>& info) {
18215 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18216 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018217 if (!name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
18218 .FromJust()) {
18219 return;
18220 }
18221 Local<Object>::Cast(info.This())
18222 ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
18223 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018224 info.GetReturnValue().Set(v8_num(23));
Andrei Popescu402d9372010-02-26 13:31:12 +000018225}
18226
18227
Steve Block6ded16b2010-05-10 14:33:55 +010018228TEST(SetterOnConstructorPrototype) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018229 v8::Isolate* isolate = CcTest::isolate();
18230 v8::HandleScope scope(isolate);
18231 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
18232 templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
Andrei Popescu402d9372010-02-26 13:31:12 +000018233 SetterWhichSetsYOnThisTo23);
18234 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018235 CHECK(context->Global()
18236 ->Set(context.local(), v8_str("P"),
18237 templ->NewInstance(context.local()).ToLocalChecked())
18238 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018239 CompileRun("function C1() {"
18240 " this.x = 23;"
18241 "};"
18242 "C1.prototype = P;"
18243 "function C2() {"
18244 " this.x = 23"
18245 "};"
18246 "C2.prototype = { };"
18247 "C2.prototype.__proto__ = P;");
18248
18249 v8::Local<v8::Script> script;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018250 script = v8_compile("new C1();");
Andrei Popescu402d9372010-02-26 13:31:12 +000018251 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018252 v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
18253 script->Run(context.local()).ToLocalChecked());
18254 CHECK_EQ(42, c1->Get(context.local(), v8_str("x"))
18255 .ToLocalChecked()
18256 ->Int32Value(context.local())
18257 .FromJust());
18258 CHECK_EQ(23, c1->Get(context.local(), v8_str("y"))
18259 .ToLocalChecked()
18260 ->Int32Value(context.local())
18261 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018262 }
18263
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018264 script = v8_compile("new C2();");
Andrei Popescu402d9372010-02-26 13:31:12 +000018265 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018266 v8::Local<v8::Object> c2 = v8::Local<v8::Object>::Cast(
18267 script->Run(context.local()).ToLocalChecked());
18268 CHECK_EQ(42, c2->Get(context.local(), v8_str("x"))
18269 .ToLocalChecked()
18270 ->Int32Value(context.local())
18271 .FromJust());
18272 CHECK_EQ(23, c2->Get(context.local(), v8_str("y"))
18273 .ToLocalChecked()
18274 ->Int32Value(context.local())
18275 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018276 }
18277}
18278
18279
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018280static void NamedPropertyGetterWhichReturns42(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018281 Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018282 info.GetReturnValue().Set(v8_num(42));
Andrei Popescu402d9372010-02-26 13:31:12 +000018283}
18284
18285
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018286static void NamedPropertySetterWhichSetsYOnThisTo23(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018287 Local<Name> name, Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018288 const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018289 if (name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("x"))
18290 .FromJust()) {
18291 Local<Object>::Cast(info.This())
18292 ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
18293 .FromJust();
Andrei Popescu402d9372010-02-26 13:31:12 +000018294 }
Andrei Popescu402d9372010-02-26 13:31:12 +000018295}
18296
18297
18298THREADED_TEST(InterceptorOnConstructorPrototype) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018299 v8::Isolate* isolate = CcTest::isolate();
18300 v8::HandleScope scope(isolate);
18301 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018302 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
18303 NamedPropertyGetterWhichReturns42,
18304 NamedPropertySetterWhichSetsYOnThisTo23));
Andrei Popescu402d9372010-02-26 13:31:12 +000018305 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018306 CHECK(context->Global()
18307 ->Set(context.local(), v8_str("P"),
18308 templ->NewInstance(context.local()).ToLocalChecked())
18309 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018310 CompileRun("function C1() {"
18311 " this.x = 23;"
18312 "};"
18313 "C1.prototype = P;"
18314 "function C2() {"
18315 " this.x = 23"
18316 "};"
18317 "C2.prototype = { };"
18318 "C2.prototype.__proto__ = P;");
18319
18320 v8::Local<v8::Script> script;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018321 script = v8_compile("new C1();");
Andrei Popescu402d9372010-02-26 13:31:12 +000018322 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018323 v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
18324 script->Run(context.local()).ToLocalChecked());
18325 CHECK_EQ(23, c1->Get(context.local(), v8_str("x"))
18326 .ToLocalChecked()
18327 ->Int32Value(context.local())
18328 .FromJust());
18329 CHECK_EQ(42, c1->Get(context.local(), v8_str("y"))
18330 .ToLocalChecked()
18331 ->Int32Value(context.local())
18332 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018333 }
18334
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018335 script = v8_compile("new C2();");
Andrei Popescu402d9372010-02-26 13:31:12 +000018336 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018337 v8::Local<v8::Object> c2 = v8::Local<v8::Object>::Cast(
18338 script->Run(context.local()).ToLocalChecked());
18339 CHECK_EQ(23, c2->Get(context.local(), v8_str("x"))
18340 .ToLocalChecked()
18341 ->Int32Value(context.local())
18342 .FromJust());
18343 CHECK_EQ(42, c2->Get(context.local(), v8_str("y"))
18344 .ToLocalChecked()
18345 ->Int32Value(context.local())
18346 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018347 }
18348}
Steve Block6ded16b2010-05-10 14:33:55 +010018349
18350
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018351TEST(Regress618) {
Steve Block6ded16b2010-05-10 14:33:55 +010018352 const char* source = "function C1() {"
18353 " this.x = 23;"
18354 "};"
18355 "C1.prototype = P;";
18356
Steve Block6ded16b2010-05-10 14:33:55 +010018357 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018358 v8::Isolate* isolate = context->GetIsolate();
18359 v8::HandleScope scope(isolate);
Steve Block6ded16b2010-05-10 14:33:55 +010018360 v8::Local<v8::Script> script;
18361
18362 // Use a simple object as prototype.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018363 v8::Local<v8::Object> prototype = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018364 prototype->Set(context.local(), v8_str("y"), v8_num(42)).FromJust();
18365 CHECK(context->Global()
18366 ->Set(context.local(), v8_str("P"), prototype)
18367 .FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +010018368
18369 // This compile will add the code to the compilation cache.
18370 CompileRun(source);
18371
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018372 script = v8_compile("new C1();");
Kristian Monsen0d5e1162010-09-30 15:31:59 +010018373 // Allow enough iterations for the inobject slack tracking logic
18374 // to finalize instance size and install the fast construct stub.
18375 for (int i = 0; i < 256; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018376 v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
18377 script->Run(context.local()).ToLocalChecked());
18378 CHECK_EQ(23, c1->Get(context.local(), v8_str("x"))
18379 .ToLocalChecked()
18380 ->Int32Value(context.local())
18381 .FromJust());
18382 CHECK_EQ(42, c1->Get(context.local(), v8_str("y"))
18383 .ToLocalChecked()
18384 ->Int32Value(context.local())
18385 .FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +010018386 }
18387
18388 // Use an API object with accessors as prototype.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018389 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
18390 templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
Steve Block6ded16b2010-05-10 14:33:55 +010018391 SetterWhichSetsYOnThisTo23);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018392 CHECK(context->Global()
18393 ->Set(context.local(), v8_str("P"),
18394 templ->NewInstance(context.local()).ToLocalChecked())
18395 .FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +010018396
18397 // This compile will get the code from the compilation cache.
18398 CompileRun(source);
18399
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018400 script = v8_compile("new C1();");
Steve Block6ded16b2010-05-10 14:33:55 +010018401 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018402 v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
18403 script->Run(context.local()).ToLocalChecked());
18404 CHECK_EQ(42, c1->Get(context.local(), v8_str("x"))
18405 .ToLocalChecked()
18406 ->Int32Value(context.local())
18407 .FromJust());
18408 CHECK_EQ(23, c1->Get(context.local(), v8_str("y"))
18409 .ToLocalChecked()
18410 ->Int32Value(context.local())
18411 .FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +010018412 }
18413}
18414
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018415v8::Isolate* gc_callbacks_isolate = NULL;
Steve Block6ded16b2010-05-10 14:33:55 +010018416int prologue_call_count = 0;
18417int epilogue_call_count = 0;
18418int prologue_call_count_second = 0;
18419int epilogue_call_count_second = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018420int prologue_call_count_alloc = 0;
18421int epilogue_call_count_alloc = 0;
Steve Block6ded16b2010-05-10 14:33:55 +010018422
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018423void PrologueCallback(v8::Isolate* isolate,
18424 v8::GCType,
18425 v8::GCCallbackFlags flags) {
18426 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18427 CHECK_EQ(gc_callbacks_isolate, isolate);
18428 ++prologue_call_count;
18429}
18430
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018431void EpilogueCallback(v8::Isolate* isolate,
18432 v8::GCType,
18433 v8::GCCallbackFlags flags) {
18434 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18435 CHECK_EQ(gc_callbacks_isolate, isolate);
18436 ++epilogue_call_count;
18437}
18438
18439
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018440void PrologueCallbackSecond(v8::Isolate* isolate,
18441 v8::GCType,
18442 v8::GCCallbackFlags flags) {
18443 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18444 CHECK_EQ(gc_callbacks_isolate, isolate);
18445 ++prologue_call_count_second;
18446}
18447
18448
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018449void EpilogueCallbackSecond(v8::Isolate* isolate,
18450 v8::GCType,
18451 v8::GCCallbackFlags flags) {
18452 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18453 CHECK_EQ(gc_callbacks_isolate, isolate);
18454 ++epilogue_call_count_second;
18455}
18456
18457
18458void PrologueCallbackAlloc(v8::Isolate* isolate,
18459 v8::GCType,
18460 v8::GCCallbackFlags flags) {
18461 v8::HandleScope scope(isolate);
18462
18463 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18464 CHECK_EQ(gc_callbacks_isolate, isolate);
18465 ++prologue_call_count_alloc;
18466
18467 // Simulate full heap to see if we will reenter this callback
18468 SimulateFullSpace(CcTest::heap()->new_space());
18469
18470 Local<Object> obj = Object::New(isolate);
18471 CHECK(!obj.IsEmpty());
18472
18473 CcTest::heap()->CollectAllGarbage(
18474 i::Heap::kAbortIncrementalMarkingMask);
18475}
18476
18477
18478void EpilogueCallbackAlloc(v8::Isolate* isolate,
18479 v8::GCType,
18480 v8::GCCallbackFlags flags) {
18481 v8::HandleScope scope(isolate);
18482
18483 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18484 CHECK_EQ(gc_callbacks_isolate, isolate);
18485 ++epilogue_call_count_alloc;
18486
18487 // Simulate full heap to see if we will reenter this callback
18488 SimulateFullSpace(CcTest::heap()->new_space());
18489
18490 Local<Object> obj = Object::New(isolate);
18491 CHECK(!obj.IsEmpty());
18492
18493 CcTest::heap()->CollectAllGarbage(
18494 i::Heap::kAbortIncrementalMarkingMask);
18495}
18496
18497
18498TEST(GCCallbacksOld) {
Steve Block6ded16b2010-05-10 14:33:55 +010018499 LocalContext context;
18500
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018501 gc_callbacks_isolate = context->GetIsolate();
18502
18503 context->GetIsolate()->AddGCPrologueCallback(PrologueCallback);
18504 context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallback);
Steve Block6ded16b2010-05-10 14:33:55 +010018505 CHECK_EQ(0, prologue_call_count);
18506 CHECK_EQ(0, epilogue_call_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018507 CcTest::heap()->CollectAllGarbage();
Steve Block6ded16b2010-05-10 14:33:55 +010018508 CHECK_EQ(1, prologue_call_count);
18509 CHECK_EQ(1, epilogue_call_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018510 context->GetIsolate()->AddGCPrologueCallback(PrologueCallbackSecond);
18511 context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallbackSecond);
18512 CcTest::heap()->CollectAllGarbage();
Steve Block6ded16b2010-05-10 14:33:55 +010018513 CHECK_EQ(2, prologue_call_count);
18514 CHECK_EQ(2, epilogue_call_count);
18515 CHECK_EQ(1, prologue_call_count_second);
18516 CHECK_EQ(1, epilogue_call_count_second);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018517 context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallback);
18518 context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallback);
18519 CcTest::heap()->CollectAllGarbage();
Steve Block6ded16b2010-05-10 14:33:55 +010018520 CHECK_EQ(2, prologue_call_count);
18521 CHECK_EQ(2, epilogue_call_count);
18522 CHECK_EQ(2, prologue_call_count_second);
18523 CHECK_EQ(2, epilogue_call_count_second);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018524 context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallbackSecond);
18525 context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
18526 CcTest::heap()->CollectAllGarbage();
Steve Block6ded16b2010-05-10 14:33:55 +010018527 CHECK_EQ(2, prologue_call_count);
18528 CHECK_EQ(2, epilogue_call_count);
18529 CHECK_EQ(2, prologue_call_count_second);
18530 CHECK_EQ(2, epilogue_call_count_second);
18531}
Kristian Monsen25f61362010-05-21 11:50:48 +010018532
18533
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018534TEST(GCCallbacks) {
18535 LocalContext context;
18536 v8::Isolate* isolate = context->GetIsolate();
18537 gc_callbacks_isolate = isolate;
18538 isolate->AddGCPrologueCallback(PrologueCallback);
18539 isolate->AddGCEpilogueCallback(EpilogueCallback);
18540 CHECK_EQ(0, prologue_call_count);
18541 CHECK_EQ(0, epilogue_call_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018542 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018543 CHECK_EQ(1, prologue_call_count);
18544 CHECK_EQ(1, epilogue_call_count);
18545 isolate->AddGCPrologueCallback(PrologueCallbackSecond);
18546 isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018547 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018548 CHECK_EQ(2, prologue_call_count);
18549 CHECK_EQ(2, epilogue_call_count);
18550 CHECK_EQ(1, prologue_call_count_second);
18551 CHECK_EQ(1, epilogue_call_count_second);
18552 isolate->RemoveGCPrologueCallback(PrologueCallback);
18553 isolate->RemoveGCEpilogueCallback(EpilogueCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018554 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018555 CHECK_EQ(2, prologue_call_count);
18556 CHECK_EQ(2, epilogue_call_count);
18557 CHECK_EQ(2, prologue_call_count_second);
18558 CHECK_EQ(2, epilogue_call_count_second);
18559 isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
18560 isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018561 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018562 CHECK_EQ(2, prologue_call_count);
18563 CHECK_EQ(2, epilogue_call_count);
18564 CHECK_EQ(2, prologue_call_count_second);
18565 CHECK_EQ(2, epilogue_call_count_second);
18566
18567 CHECK_EQ(0, prologue_call_count_alloc);
18568 CHECK_EQ(0, epilogue_call_count_alloc);
18569 isolate->AddGCPrologueCallback(PrologueCallbackAlloc);
18570 isolate->AddGCEpilogueCallback(EpilogueCallbackAlloc);
18571 CcTest::heap()->CollectAllGarbage(
18572 i::Heap::kAbortIncrementalMarkingMask);
18573 CHECK_EQ(1, prologue_call_count_alloc);
18574 CHECK_EQ(1, epilogue_call_count_alloc);
18575 isolate->RemoveGCPrologueCallback(PrologueCallbackAlloc);
18576 isolate->RemoveGCEpilogueCallback(EpilogueCallbackAlloc);
18577}
18578
18579
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018580THREADED_TEST(TwoByteStringInOneByteCons) {
Steve Block8defd9f2010-07-08 12:39:36 +010018581 // See Chromium issue 47824.
Steve Block8defd9f2010-07-08 12:39:36 +010018582 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018583 v8::HandleScope scope(context->GetIsolate());
18584
Steve Block8defd9f2010-07-08 12:39:36 +010018585 const char* init_code =
18586 "var str1 = 'abelspendabel';"
18587 "var str2 = str1 + str1 + str1;"
18588 "str2;";
18589 Local<Value> result = CompileRun(init_code);
18590
Ben Murdoch69a99ed2011-11-30 16:03:39 +000018591 Local<Value> indexof = CompileRun("str2.indexOf('els')");
18592 Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
18593
Steve Block8defd9f2010-07-08 12:39:36 +010018594 CHECK(result->IsString());
18595 i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
18596 int length = string->length();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018597 CHECK(string->IsOneByteRepresentation());
Steve Block8defd9f2010-07-08 12:39:36 +010018598
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018599 i::Handle<i::String> flat_string = i::String::Flatten(string);
Steve Block8defd9f2010-07-08 12:39:36 +010018600
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018601 CHECK(string->IsOneByteRepresentation());
18602 CHECK(flat_string->IsOneByteRepresentation());
Steve Block8defd9f2010-07-08 12:39:36 +010018603
18604 // Create external resource.
18605 uint16_t* uc16_buffer = new uint16_t[length + 1];
18606
18607 i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
18608 uc16_buffer[length] = 0;
18609
18610 TestResource resource(uc16_buffer);
18611
18612 flat_string->MakeExternal(&resource);
18613
18614 CHECK(flat_string->IsTwoByteRepresentation());
18615
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018616 // If the cons string has been short-circuited, skip the following checks.
18617 if (!string.is_identical_to(flat_string)) {
18618 // At this point, we should have a Cons string which is flat and one-byte,
18619 // with a first half that is a two-byte string (although it only contains
18620 // one-byte characters). This is a valid sequence of steps, and it can
18621 // happen in real pages.
18622 CHECK(string->IsOneByteRepresentation());
18623 i::ConsString* cons = i::ConsString::cast(*string);
18624 CHECK_EQ(0, cons->second()->length());
18625 CHECK(cons->first()->IsTwoByteRepresentation());
18626 }
Steve Block8defd9f2010-07-08 12:39:36 +010018627
18628 // Check that some string operations work.
18629
18630 // Atom RegExp.
18631 Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018632 CHECK_EQ(6, reresult->Int32Value(context.local()).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +010018633
18634 // Nonatom RegExp.
18635 reresult = CompileRun("str2.match(/abe./g).length;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018636 CHECK_EQ(6, reresult->Int32Value(context.local()).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +010018637
18638 reresult = CompileRun("str2.search(/bel/g);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018639 CHECK_EQ(1, reresult->Int32Value(context.local()).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +010018640
18641 reresult = CompileRun("str2.search(/be./g);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018642 CHECK_EQ(1, reresult->Int32Value(context.local()).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +010018643
18644 ExpectTrue("/bel/g.test(str2);");
18645
18646 ExpectTrue("/be./g.test(str2);");
18647
18648 reresult = CompileRun("/bel/g.exec(str2);");
18649 CHECK(!reresult->IsNull());
18650
18651 reresult = CompileRun("/be./g.exec(str2);");
18652 CHECK(!reresult->IsNull());
18653
18654 ExpectString("str2.substring(2, 10);", "elspenda");
18655
18656 ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
18657
18658 ExpectString("str2.charAt(2);", "e");
18659
Ben Murdoch69a99ed2011-11-30 16:03:39 +000018660 ExpectObject("str2.indexOf('els');", indexof);
18661
18662 ExpectObject("str2.lastIndexOf('dab');", lastindexof);
18663
Steve Block8defd9f2010-07-08 12:39:36 +010018664 reresult = CompileRun("str2.charCodeAt(2);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018665 CHECK_EQ(static_cast<int32_t>('e'),
18666 reresult->Int32Value(context.local()).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +010018667}
Iain Merrick75681382010-08-19 15:07:18 +010018668
18669
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018670TEST(ContainsOnlyOneByte) {
18671 v8::V8::Initialize();
18672 v8::Isolate* isolate = CcTest::isolate();
18673 v8::HandleScope scope(isolate);
18674 // Make a buffer long enough that it won't automatically be converted.
18675 const int length = 512;
18676 // Ensure word aligned assignment.
18677 const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018678 v8::base::SmartArrayPointer<uintptr_t> aligned_contents(
18679 new uintptr_t[aligned_length]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018680 uint16_t* string_contents =
18681 reinterpret_cast<uint16_t*>(aligned_contents.get());
18682 // Set to contain only one byte.
18683 for (int i = 0; i < length-1; i++) {
18684 string_contents[i] = 0x41;
18685 }
18686 string_contents[length-1] = 0;
18687 // Simple case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018688 Local<String> string =
18689 String::NewExternalTwoByte(isolate,
18690 new TestResource(string_contents, NULL, false))
18691 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018692 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
18693 // Counter example.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018694 string = String::NewFromTwoByte(isolate, string_contents,
18695 v8::NewStringType::kNormal)
18696 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018697 CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
18698 // Test left right and balanced cons strings.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018699 Local<String> base = v8_str("a");
18700 Local<String> left = base;
18701 Local<String> right = base;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018702 for (int i = 0; i < 1000; i++) {
18703 left = String::Concat(base, left);
18704 right = String::Concat(right, base);
18705 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018706 Local<String> balanced = String::Concat(left, base);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018707 balanced = String::Concat(balanced, right);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018708 Local<String> cons_strings[] = {left, balanced, right};
18709 Local<String> two_byte =
18710 String::NewExternalTwoByte(isolate,
18711 new TestResource(string_contents, NULL, false))
18712 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018713 USE(two_byte); USE(cons_strings);
18714 for (size_t i = 0; i < arraysize(cons_strings); i++) {
18715 // Base assumptions.
18716 string = cons_strings[i];
18717 CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
18718 // Test left and right concatentation.
18719 string = String::Concat(two_byte, cons_strings[i]);
18720 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
18721 string = String::Concat(cons_strings[i], two_byte);
18722 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
18723 }
18724 // Set bits in different positions
18725 // for strings of different lengths and alignments.
18726 for (int alignment = 0; alignment < 7; alignment++) {
18727 for (int size = 2; alignment + size < length; size *= 2) {
18728 int zero_offset = size + alignment;
18729 string_contents[zero_offset] = 0;
18730 for (int i = 0; i < size; i++) {
18731 int shift = 8 + (i % 7);
18732 string_contents[alignment + i] = 1 << shift;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018733 string = String::NewExternalTwoByte(
18734 isolate,
18735 new TestResource(string_contents + alignment, NULL, false))
18736 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018737 CHECK_EQ(size, string->Length());
18738 CHECK(!string->ContainsOnlyOneByte());
18739 string_contents[alignment + i] = 0x41;
18740 }
18741 string_contents[zero_offset] = 0x41;
18742 }
18743 }
18744}
18745
18746
Iain Merrick75681382010-08-19 15:07:18 +010018747// Failed access check callback that performs a GC on each invocation.
18748void FailedAccessCheckCallbackGC(Local<v8::Object> target,
18749 v8::AccessType type,
18750 Local<v8::Value> data) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018751 CcTest::heap()->CollectAllGarbage();
18752 CcTest::isolate()->ThrowException(
18753 v8::Exception::Error(v8_str("cross context")));
Iain Merrick75681382010-08-19 15:07:18 +010018754}
18755
18756
18757TEST(GCInFailedAccessCheckCallback) {
18758 // Install a failed access check callback that performs a GC on each
18759 // invocation. Then force the callback to be called from va
18760
18761 v8::V8::Initialize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018762 v8::Isolate* isolate = CcTest::isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018763
18764 isolate->SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
18765
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018766 v8::HandleScope scope(isolate);
Iain Merrick75681382010-08-19 15:07:18 +010018767
18768 // Create an ObjectTemplate for global objects and install access
18769 // check callbacks that will block access.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018770 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018771 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018772 global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Iain Merrick75681382010-08-19 15:07:18 +010018773
18774 // Create a context and set an x property on it's global object.
18775 LocalContext context0(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018776 CHECK(context0->Global()
18777 ->Set(context0.local(), v8_str("x"), v8_num(42))
18778 .FromJust());
18779 v8::Local<v8::Object> global0 = context0->Global();
Iain Merrick75681382010-08-19 15:07:18 +010018780
18781 // Create a context with a different security token so that the
18782 // failed access check callback will be called on each access.
18783 LocalContext context1(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018784 CHECK(context1->Global()
18785 ->Set(context1.local(), v8_str("other"), global0)
18786 .FromJust());
18787
18788 v8::TryCatch try_catch(isolate);
Iain Merrick75681382010-08-19 15:07:18 +010018789
18790 // Get property with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018791 CHECK(CompileRun("other.x").IsEmpty());
18792 CHECK(try_catch.HasCaught());
18793 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010018794
18795 // Get element with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018796 CHECK(CompileRun("other[0]").IsEmpty());
18797 CHECK(try_catch.HasCaught());
18798 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010018799
18800 // Set property with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018801 CHECK(CompileRun("other.x = new Object()").IsEmpty());
18802 CHECK(try_catch.HasCaught());
18803 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010018804
18805 // Set element with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018806 CHECK(CompileRun("other[0] = new Object()").IsEmpty());
18807 CHECK(try_catch.HasCaught());
18808 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010018809
18810 // Get property attribute with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018811 CHECK(CompileRun("\'x\' in other").IsEmpty());
18812 CHECK(try_catch.HasCaught());
18813 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010018814
18815 // Get property attribute for element with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018816 CHECK(CompileRun("0 in other").IsEmpty());
18817 CHECK(try_catch.HasCaught());
18818 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010018819
18820 // Delete property.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018821 CHECK(CompileRun("delete other.x").IsEmpty());
18822 CHECK(try_catch.HasCaught());
18823 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010018824
18825 // Delete element.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018826 CHECK(global0->Delete(context1.local(), 0).IsNothing());
18827 CHECK(try_catch.HasCaught());
18828 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010018829
18830 // DefineAccessor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018831 CHECK(global0->SetAccessor(context1.local(), v8_str("x"), GetXValue, NULL,
18832 v8_str("x"))
18833 .IsNothing());
18834 CHECK(try_catch.HasCaught());
18835 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010018836
18837 // Define JavaScript accessor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018838 CHECK(CompileRun(
18839 "Object.prototype.__defineGetter__.call("
18840 " other, \'x\', function() { return 42; })").IsEmpty());
18841 CHECK(try_catch.HasCaught());
18842 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010018843
18844 // LookupAccessor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018845 CHECK(CompileRun(
18846 "Object.prototype.__lookupGetter__.call("
18847 " other, \'x\')").IsEmpty());
18848 CHECK(try_catch.HasCaught());
18849 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010018850
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018851 // HasOwnElement.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018852 CHECK(CompileRun(
18853 "Object.prototype.hasOwnProperty.call("
18854 "other, \'0\')").IsEmpty());
18855 CHECK(try_catch.HasCaught());
18856 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010018857
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018858 CHECK(global0->HasRealIndexedProperty(context1.local(), 0).IsNothing());
18859 CHECK(try_catch.HasCaught());
18860 try_catch.Reset();
18861
18862 CHECK(
18863 global0->HasRealNamedProperty(context1.local(), v8_str("x")).IsNothing());
18864 CHECK(try_catch.HasCaught());
18865 try_catch.Reset();
18866
18867 CHECK(global0->HasRealNamedCallbackProperty(context1.local(), v8_str("x"))
18868 .IsNothing());
18869 CHECK(try_catch.HasCaught());
18870 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010018871
18872 // Reset the failed access check callback so it does not influence
18873 // the other tests.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018874 isolate->SetFailedAccessCheckCallbackFunction(NULL);
Iain Merrick75681382010-08-19 15:07:18 +010018875}
Kristian Monsen0d5e1162010-09-30 15:31:59 +010018876
Steve Block44f0eee2011-05-26 01:26:41 +010018877
18878TEST(IsolateNewDispose) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018879 v8::Isolate* current_isolate = CcTest::isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018880 v8::Isolate::CreateParams create_params;
18881 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
18882 v8::Isolate* isolate = v8::Isolate::New(create_params);
Steve Block44f0eee2011-05-26 01:26:41 +010018883 CHECK(isolate != NULL);
Steve Block44f0eee2011-05-26 01:26:41 +010018884 CHECK(current_isolate != isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018885 CHECK(current_isolate == CcTest::isolate());
Steve Block44f0eee2011-05-26 01:26:41 +010018886
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018887 isolate->SetFatalErrorHandler(StoringErrorCallback);
Steve Block44f0eee2011-05-26 01:26:41 +010018888 last_location = last_message = NULL;
18889 isolate->Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018890 CHECK(!last_location);
18891 CHECK(!last_message);
Steve Block44f0eee2011-05-26 01:26:41 +010018892}
18893
Steve Block44f0eee2011-05-26 01:26:41 +010018894
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018895UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018896 v8::Isolate::CreateParams create_params;
18897 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
18898 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018899 {
18900 v8::Isolate::Scope i_scope(isolate);
18901 v8::HandleScope scope(isolate);
18902 LocalContext context(isolate);
18903 // Run something in this isolate.
18904 ExpectTrue("true");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018905 isolate->SetFatalErrorHandler(StoringErrorCallback);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018906 last_location = last_message = NULL;
18907 // Still entered, should fail.
18908 isolate->Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018909 CHECK(last_location);
18910 CHECK(last_message);
Steve Block44f0eee2011-05-26 01:26:41 +010018911 }
Steve Block44f0eee2011-05-26 01:26:41 +010018912 isolate->Dispose();
Steve Block44f0eee2011-05-26 01:26:41 +010018913}
18914
Steve Block44f0eee2011-05-26 01:26:41 +010018915
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018916static void BreakArrayGuarantees(const char* script) {
18917 v8::Isolate::CreateParams create_params;
18918 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
18919 v8::Isolate* isolate1 = v8::Isolate::New(create_params);
18920 isolate1->Enter();
18921 v8::Persistent<v8::Context> context1;
18922 {
18923 v8::HandleScope scope(isolate1);
18924 context1.Reset(isolate1, Context::New(isolate1));
18925 }
18926
18927 {
18928 v8::HandleScope scope(isolate1);
18929 v8::Local<v8::Context> context =
18930 v8::Local<v8::Context>::New(isolate1, context1);
18931 v8::Context::Scope context_scope(context);
18932 v8::internal::Isolate* i_isolate =
18933 reinterpret_cast<v8::internal::Isolate*>(isolate1);
18934 CHECK_EQ(true, i_isolate->IsFastArrayConstructorPrototypeChainIntact());
18935 // Run something in new isolate.
18936 CompileRun(script);
18937 CHECK_EQ(false, i_isolate->IsFastArrayConstructorPrototypeChainIntact());
18938 }
18939 isolate1->Exit();
18940 isolate1->Dispose();
18941}
18942
18943
18944TEST(VerifyArrayPrototypeGuarantees) {
18945 // Break fast array hole handling by element changes.
18946 BreakArrayGuarantees("[].__proto__[1] = 3;");
18947 BreakArrayGuarantees("Object.prototype[3] = 'three';");
18948 BreakArrayGuarantees("Array.prototype.push(1);");
18949 BreakArrayGuarantees("Array.prototype.unshift(1);");
18950 // Break fast array hole handling by changing length.
18951 BreakArrayGuarantees("Array.prototype.length = 30;");
18952 // Break fast array hole handling by prototype structure changes.
18953 BreakArrayGuarantees("[].__proto__.__proto__ = { funny: true };");
18954 // By sending elements to dictionary mode.
18955 BreakArrayGuarantees(
18956 "Object.defineProperty(Array.prototype, 0, {"
18957 " get: function() { return 3; }});");
18958 BreakArrayGuarantees(
18959 "Object.defineProperty(Object.prototype, 0, {"
18960 " get: function() { return 3; }});");
18961}
18962
18963
Steve Block44f0eee2011-05-26 01:26:41 +010018964TEST(RunTwoIsolatesOnSingleThread) {
18965 // Run isolate 1.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018966 v8::Isolate::CreateParams create_params;
18967 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
18968 v8::Isolate* isolate1 = v8::Isolate::New(create_params);
Steve Block44f0eee2011-05-26 01:26:41 +010018969 isolate1->Enter();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018970 v8::Persistent<v8::Context> context1;
18971 {
18972 v8::HandleScope scope(isolate1);
18973 context1.Reset(isolate1, Context::New(isolate1));
18974 }
Steve Block44f0eee2011-05-26 01:26:41 +010018975
18976 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018977 v8::HandleScope scope(isolate1);
18978 v8::Local<v8::Context> context =
18979 v8::Local<v8::Context>::New(isolate1, context1);
18980 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010018981 // Run something in new isolate.
18982 CompileRun("var foo = 'isolate 1';");
18983 ExpectString("function f() { return foo; }; f()", "isolate 1");
18984 }
18985
18986 // Run isolate 2.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018987 v8::Isolate* isolate2 = v8::Isolate::New(create_params);
Steve Block44f0eee2011-05-26 01:26:41 +010018988 v8::Persistent<v8::Context> context2;
18989
18990 {
18991 v8::Isolate::Scope iscope(isolate2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018992 v8::HandleScope scope(isolate2);
18993 context2.Reset(isolate2, Context::New(isolate2));
18994 v8::Local<v8::Context> context =
18995 v8::Local<v8::Context>::New(isolate2, context2);
18996 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010018997
18998 // Run something in new isolate.
18999 CompileRun("var foo = 'isolate 2';");
19000 ExpectString("function f() { return foo; }; f()", "isolate 2");
19001 }
19002
19003 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019004 v8::HandleScope scope(isolate1);
19005 v8::Local<v8::Context> context =
19006 v8::Local<v8::Context>::New(isolate1, context1);
19007 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019008 // Now again in isolate 1
19009 ExpectString("function f() { return foo; }; f()", "isolate 1");
19010 }
19011
19012 isolate1->Exit();
19013
19014 // Run some stuff in default isolate.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019015 v8::Persistent<v8::Context> context_default;
19016 {
19017 v8::Isolate* isolate = CcTest::isolate();
19018 v8::Isolate::Scope iscope(isolate);
19019 v8::HandleScope scope(isolate);
19020 context_default.Reset(isolate, Context::New(isolate));
19021 }
Steve Block44f0eee2011-05-26 01:26:41 +010019022
19023 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019024 v8::HandleScope scope(CcTest::isolate());
19025 v8::Local<v8::Context> context =
19026 v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
19027 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019028 // Variables in other isolates should be not available, verify there
19029 // is an exception.
19030 ExpectTrue("function f() {"
19031 " try {"
19032 " foo;"
19033 " return false;"
19034 " } catch(e) {"
19035 " return true;"
19036 " }"
19037 "};"
19038 "var isDefaultIsolate = true;"
19039 "f()");
19040 }
19041
19042 isolate1->Enter();
19043
19044 {
19045 v8::Isolate::Scope iscope(isolate2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019046 v8::HandleScope scope(isolate2);
19047 v8::Local<v8::Context> context =
19048 v8::Local<v8::Context>::New(isolate2, context2);
19049 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019050 ExpectString("function f() { return foo; }; f()", "isolate 2");
19051 }
19052
19053 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019054 v8::HandleScope scope(v8::Isolate::GetCurrent());
19055 v8::Local<v8::Context> context =
19056 v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
19057 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019058 ExpectString("function f() { return foo; }; f()", "isolate 1");
19059 }
19060
19061 {
19062 v8::Isolate::Scope iscope(isolate2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019063 context2.Reset();
Steve Block44f0eee2011-05-26 01:26:41 +010019064 }
19065
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019066 context1.Reset();
Steve Block44f0eee2011-05-26 01:26:41 +010019067 isolate1->Exit();
19068
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019069 isolate2->SetFatalErrorHandler(StoringErrorCallback);
Steve Block44f0eee2011-05-26 01:26:41 +010019070 last_location = last_message = NULL;
19071
19072 isolate1->Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019073 CHECK(!last_location);
19074 CHECK(!last_message);
Steve Block44f0eee2011-05-26 01:26:41 +010019075
19076 isolate2->Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019077 CHECK(!last_location);
19078 CHECK(!last_message);
Steve Block44f0eee2011-05-26 01:26:41 +010019079
19080 // Check that default isolate still runs.
19081 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019082 v8::HandleScope scope(CcTest::isolate());
19083 v8::Local<v8::Context> context =
19084 v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
19085 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019086 ExpectTrue("function f() { return isDefaultIsolate; }; f()");
19087 }
19088}
19089
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019090
Steve Block44f0eee2011-05-26 01:26:41 +010019091static int CalcFibonacci(v8::Isolate* isolate, int limit) {
19092 v8::Isolate::Scope isolate_scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019093 v8::HandleScope scope(isolate);
19094 LocalContext context(isolate);
Steve Block44f0eee2011-05-26 01:26:41 +010019095 i::ScopedVector<char> code(1024);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019096 i::SNPrintF(code, "function fib(n) {"
19097 " if (n <= 2) return 1;"
19098 " return fib(n-1) + fib(n-2);"
19099 "}"
19100 "fib(%d)", limit);
Steve Block44f0eee2011-05-26 01:26:41 +010019101 Local<Value> value = CompileRun(code.start());
19102 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019103 return static_cast<int>(value->NumberValue(context.local()).FromJust());
Steve Block44f0eee2011-05-26 01:26:41 +010019104}
19105
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019106class IsolateThread : public v8::base::Thread {
Steve Block44f0eee2011-05-26 01:26:41 +010019107 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019108 explicit IsolateThread(int fib_limit)
19109 : Thread(Options("IsolateThread")), fib_limit_(fib_limit), result_(0) {}
Steve Block44f0eee2011-05-26 01:26:41 +010019110
19111 void Run() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019112 v8::Isolate::CreateParams create_params;
19113 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19114 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019115 result_ = CalcFibonacci(isolate, fib_limit_);
19116 isolate->Dispose();
Steve Block44f0eee2011-05-26 01:26:41 +010019117 }
19118
19119 int result() { return result_; }
19120
19121 private:
Steve Block44f0eee2011-05-26 01:26:41 +010019122 int fib_limit_;
19123 int result_;
19124};
19125
Steve Block44f0eee2011-05-26 01:26:41 +010019126
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019127TEST(MultipleIsolatesOnIndividualThreads) {
19128 IsolateThread thread1(21);
19129 IsolateThread thread2(12);
Steve Block44f0eee2011-05-26 01:26:41 +010019130
19131 // Compute some fibonacci numbers on 3 threads in 3 isolates.
19132 thread1.Start();
19133 thread2.Start();
19134
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019135 int result1 = CalcFibonacci(CcTest::isolate(), 21);
19136 int result2 = CalcFibonacci(CcTest::isolate(), 12);
Steve Block44f0eee2011-05-26 01:26:41 +010019137
19138 thread1.Join();
19139 thread2.Join();
19140
19141 // Compare results. The actual fibonacci numbers for 12 and 21 are taken
19142 // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
19143 CHECK_EQ(result1, 10946);
19144 CHECK_EQ(result2, 144);
19145 CHECK_EQ(result1, thread1.result());
19146 CHECK_EQ(result2, thread2.result());
Steve Block44f0eee2011-05-26 01:26:41 +010019147}
19148
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019149
Ben Murdoch257744e2011-11-30 15:57:28 +000019150TEST(IsolateDifferentContexts) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019151 v8::Isolate::CreateParams create_params;
19152 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19153 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019154 Local<v8::Context> context;
Ben Murdoch257744e2011-11-30 15:57:28 +000019155 {
19156 v8::Isolate::Scope isolate_scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019157 v8::HandleScope handle_scope(isolate);
19158 context = v8::Context::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000019159 v8::Context::Scope context_scope(context);
19160 Local<Value> v = CompileRun("2");
19161 CHECK(v->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019162 CHECK_EQ(2, static_cast<int>(v->NumberValue(context).FromJust()));
Ben Murdoch257744e2011-11-30 15:57:28 +000019163 }
19164 {
19165 v8::Isolate::Scope isolate_scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019166 v8::HandleScope handle_scope(isolate);
19167 context = v8::Context::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000019168 v8::Context::Scope context_scope(context);
19169 Local<Value> v = CompileRun("22");
19170 CHECK(v->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019171 CHECK_EQ(22, static_cast<int>(v->NumberValue(context).FromJust()));
Ben Murdoch257744e2011-11-30 15:57:28 +000019172 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019173 isolate->Dispose();
Ben Murdoch257744e2011-11-30 15:57:28 +000019174}
Steve Block44f0eee2011-05-26 01:26:41 +010019175
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019176class InitDefaultIsolateThread : public v8::base::Thread {
Steve Block44f0eee2011-05-26 01:26:41 +010019177 public:
19178 enum TestCase {
Steve Block44f0eee2011-05-26 01:26:41 +010019179 SetResourceConstraints,
19180 SetFatalHandler,
19181 SetCounterFunction,
19182 SetCreateHistogramFunction,
19183 SetAddHistogramSampleFunction
19184 };
19185
19186 explicit InitDefaultIsolateThread(TestCase testCase)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019187 : Thread(Options("InitDefaultIsolateThread")),
Steve Block44f0eee2011-05-26 01:26:41 +010019188 testCase_(testCase),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019189 result_(false) {}
Steve Block44f0eee2011-05-26 01:26:41 +010019190
19191 void Run() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019192 v8::Isolate::CreateParams create_params;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019193 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19194 const intptr_t pageSizeMult =
19195 v8::internal::Page::kPageSize / v8::internal::MB;
Steve Block44f0eee2011-05-26 01:26:41 +010019196 switch (testCase_) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019197 case SetResourceConstraints: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019198 create_params.constraints.set_max_semi_space_size(1 * pageSizeMult);
19199 create_params.constraints.set_max_old_space_size(4 * pageSizeMult);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019200 break;
19201 }
19202 default:
19203 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019204 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019205 v8::Isolate* isolate = v8::Isolate::New(create_params);
19206 isolate->Enter();
19207 switch (testCase_) {
19208 case SetResourceConstraints:
19209 // Already handled in pre-Isolate-creation block.
19210 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019211
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019212 case SetFatalHandler:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019213 isolate->SetFatalErrorHandler(NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019214 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019215
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019216 case SetCounterFunction:
19217 CcTest::isolate()->SetCounterFunction(NULL);
19218 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019219
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019220 case SetCreateHistogramFunction:
19221 CcTest::isolate()->SetCreateHistogramFunction(NULL);
19222 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019223
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019224 case SetAddHistogramSampleFunction:
19225 CcTest::isolate()->SetAddHistogramSampleFunction(NULL);
19226 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019227 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019228 isolate->Exit();
19229 isolate->Dispose();
Steve Block44f0eee2011-05-26 01:26:41 +010019230 result_ = true;
19231 }
19232
19233 bool result() { return result_; }
19234
19235 private:
19236 TestCase testCase_;
19237 bool result_;
19238};
19239
19240
19241static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
19242 InitDefaultIsolateThread thread(testCase);
19243 thread.Start();
19244 thread.Join();
19245 CHECK_EQ(thread.result(), true);
19246}
19247
Steve Block44f0eee2011-05-26 01:26:41 +010019248
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019249TEST(InitializeDefaultIsolateOnSecondaryThread1) {
Steve Block44f0eee2011-05-26 01:26:41 +010019250 InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
19251}
19252
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019253
19254TEST(InitializeDefaultIsolateOnSecondaryThread2) {
Steve Block44f0eee2011-05-26 01:26:41 +010019255 InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
19256}
19257
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019258
19259TEST(InitializeDefaultIsolateOnSecondaryThread3) {
Steve Block44f0eee2011-05-26 01:26:41 +010019260 InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
19261}
19262
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019263
19264TEST(InitializeDefaultIsolateOnSecondaryThread4) {
Steve Block44f0eee2011-05-26 01:26:41 +010019265 InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
19266}
19267
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019268
19269TEST(InitializeDefaultIsolateOnSecondaryThread5) {
Steve Block44f0eee2011-05-26 01:26:41 +010019270 InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
19271}
19272
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019273
19274TEST(StringCheckMultipleContexts) {
19275 const char* code =
19276 "(function() { return \"a\".charAt(0); })()";
19277
19278 {
19279 // Run the code twice in the first context to initialize the call IC.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019280 LocalContext context1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019281 v8::HandleScope scope(context1->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019282 ExpectString(code, "a");
19283 ExpectString(code, "a");
19284 }
19285
19286 {
19287 // Change the String.prototype in the second context and check
19288 // that the right function gets called.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019289 LocalContext context2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019290 v8::HandleScope scope(context2->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019291 CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
19292 ExpectString(code, "not a");
19293 }
19294}
19295
19296
19297TEST(NumberCheckMultipleContexts) {
19298 const char* code =
19299 "(function() { return (42).toString(); })()";
19300
19301 {
19302 // Run the code twice in the first context to initialize the call IC.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019303 LocalContext context1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019304 v8::HandleScope scope(context1->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019305 ExpectString(code, "42");
19306 ExpectString(code, "42");
19307 }
19308
19309 {
19310 // Change the Number.prototype in the second context and check
19311 // that the right function gets called.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019312 LocalContext context2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019313 v8::HandleScope scope(context2->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019314 CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
19315 ExpectString(code, "not 42");
19316 }
19317}
19318
19319
19320TEST(BooleanCheckMultipleContexts) {
19321 const char* code =
19322 "(function() { return true.toString(); })()";
19323
19324 {
19325 // Run the code twice in the first context to initialize the call IC.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019326 LocalContext context1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019327 v8::HandleScope scope(context1->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019328 ExpectString(code, "true");
19329 ExpectString(code, "true");
19330 }
19331
19332 {
19333 // Change the Boolean.prototype in the second context and check
19334 // that the right function gets called.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019335 LocalContext context2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019336 v8::HandleScope scope(context2->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019337 CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
19338 ExpectString(code, "");
19339 }
19340}
Ben Murdochf87a2032010-10-22 12:50:53 +010019341
19342
19343TEST(DontDeleteCellLoadIC) {
19344 const char* function_code =
19345 "function readCell() { while (true) { return cell; } }";
19346
19347 {
19348 // Run the code twice in the first context to initialize the load
19349 // IC for a don't delete cell.
Ben Murdochf87a2032010-10-22 12:50:53 +010019350 LocalContext context1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019351 v8::HandleScope scope(context1->GetIsolate());
Ben Murdochf87a2032010-10-22 12:50:53 +010019352 CompileRun("var cell = \"first\";");
19353 ExpectBoolean("delete cell", false);
19354 CompileRun(function_code);
19355 ExpectString("readCell()", "first");
19356 ExpectString("readCell()", "first");
19357 }
19358
19359 {
19360 // Use a deletable cell in the second context.
Ben Murdochf87a2032010-10-22 12:50:53 +010019361 LocalContext context2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019362 v8::HandleScope scope(context2->GetIsolate());
Ben Murdochf87a2032010-10-22 12:50:53 +010019363 CompileRun("cell = \"second\";");
19364 CompileRun(function_code);
19365 ExpectString("readCell()", "second");
19366 ExpectBoolean("delete cell", true);
19367 ExpectString("(function() {"
19368 " try {"
19369 " return readCell();"
19370 " } catch(e) {"
19371 " return e.toString();"
19372 " }"
19373 "})()",
19374 "ReferenceError: cell is not defined");
19375 CompileRun("cell = \"new_second\";");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019376 CcTest::heap()->CollectAllGarbage();
Ben Murdochf87a2032010-10-22 12:50:53 +010019377 ExpectString("readCell()", "new_second");
19378 ExpectString("readCell()", "new_second");
19379 }
19380}
19381
19382
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019383class Visitor42 : public v8::PersistentHandleVisitor {
19384 public:
19385 explicit Visitor42(v8::Persistent<v8::Object>* object)
19386 : counter_(0), object_(object) { }
19387
19388 virtual void VisitPersistentHandle(Persistent<Value>* value,
19389 uint16_t class_id) {
19390 if (class_id != 42) return;
19391 CHECK_EQ(42, value->WrapperClassId());
19392 v8::Isolate* isolate = CcTest::isolate();
19393 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019394 v8::Local<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
19395 v8::Local<v8::Value> object = v8::Local<v8::Object>::New(isolate, *object_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019396 CHECK(handle->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019397 CHECK(Local<Object>::Cast(handle)
19398 ->Equals(isolate->GetCurrentContext(), object)
19399 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019400 ++counter_;
19401 }
19402
19403 int counter_;
19404 v8::Persistent<v8::Object>* object_;
19405};
19406
19407
19408TEST(PersistentHandleVisitor) {
Ben Murdochf87a2032010-10-22 12:50:53 +010019409 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019410 v8::Isolate* isolate = context->GetIsolate();
19411 v8::HandleScope scope(isolate);
19412 v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
19413 CHECK_EQ(0, object.WrapperClassId());
19414 object.SetWrapperClassId(42);
19415 CHECK_EQ(42, object.WrapperClassId());
19416
19417 Visitor42 visitor(&object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019418 isolate->VisitHandlesWithClassIds(&visitor);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019419 CHECK_EQ(1, visitor.counter_);
19420
19421 object.Reset();
19422}
19423
19424
19425TEST(WrapperClassId) {
19426 LocalContext context;
19427 v8::Isolate* isolate = context->GetIsolate();
19428 v8::HandleScope scope(isolate);
19429 v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
19430 CHECK_EQ(0, object.WrapperClassId());
19431 object.SetWrapperClassId(65535);
19432 CHECK_EQ(65535, object.WrapperClassId());
19433 object.Reset();
19434}
19435
19436
19437TEST(PersistentHandleInNewSpaceVisitor) {
19438 LocalContext context;
19439 v8::Isolate* isolate = context->GetIsolate();
19440 v8::HandleScope scope(isolate);
19441 v8::Persistent<v8::Object> object1(isolate, v8::Object::New(isolate));
19442 CHECK_EQ(0, object1.WrapperClassId());
19443 object1.SetWrapperClassId(42);
19444 CHECK_EQ(42, object1.WrapperClassId());
19445
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019446 CcTest::heap()->CollectAllGarbage();
19447 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019448
19449 v8::Persistent<v8::Object> object2(isolate, v8::Object::New(isolate));
19450 CHECK_EQ(0, object2.WrapperClassId());
19451 object2.SetWrapperClassId(42);
19452 CHECK_EQ(42, object2.WrapperClassId());
19453
19454 Visitor42 visitor(&object2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019455 isolate->VisitHandlesForPartialDependence(&visitor);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019456 CHECK_EQ(1, visitor.counter_);
19457
19458 object1.Reset();
19459 object2.Reset();
19460}
19461
19462
19463TEST(RegExp) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019464 i::FLAG_harmony_regexps = true;
19465 i::FLAG_harmony_unicode_regexps = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019466 LocalContext context;
19467 v8::HandleScope scope(context->GetIsolate());
Ben Murdochf87a2032010-10-22 12:50:53 +010019468
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019469 v8::Local<v8::RegExp> re =
19470 v8::RegExp::New(context.local(), v8_str("foo"), v8::RegExp::kNone)
19471 .ToLocalChecked();
Ben Murdochf87a2032010-10-22 12:50:53 +010019472 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019473 CHECK(re->GetSource()->Equals(context.local(), v8_str("foo")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019474 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
Ben Murdochf87a2032010-10-22 12:50:53 +010019475
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019476 re = v8::RegExp::New(context.local(), v8_str("bar"),
Ben Murdochf87a2032010-10-22 12:50:53 +010019477 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019478 v8::RegExp::kGlobal))
19479 .ToLocalChecked();
Ben Murdochf87a2032010-10-22 12:50:53 +010019480 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019481 CHECK(re->GetSource()->Equals(context.local(), v8_str("bar")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019482 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
19483 static_cast<int>(re->GetFlags()));
Ben Murdochf87a2032010-10-22 12:50:53 +010019484
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019485 re = v8::RegExp::New(context.local(), v8_str("baz"),
Ben Murdochf87a2032010-10-22 12:50:53 +010019486 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019487 v8::RegExp::kMultiline))
19488 .ToLocalChecked();
Ben Murdochf87a2032010-10-22 12:50:53 +010019489 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019490 CHECK(re->GetSource()->Equals(context.local(), v8_str("baz")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019491 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
19492 static_cast<int>(re->GetFlags()));
Ben Murdochf87a2032010-10-22 12:50:53 +010019493
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019494 re = v8::RegExp::New(context.local(), v8_str("baz"),
19495 static_cast<v8::RegExp::Flags>(v8::RegExp::kUnicode |
19496 v8::RegExp::kSticky))
19497 .ToLocalChecked();
19498 CHECK(re->IsRegExp());
19499 CHECK(re->GetSource()->Equals(context.local(), v8_str("baz")).FromJust());
19500 CHECK_EQ(v8::RegExp::kUnicode | v8::RegExp::kSticky,
19501 static_cast<int>(re->GetFlags()));
19502
Ben Murdochf87a2032010-10-22 12:50:53 +010019503 re = CompileRun("/quux/").As<v8::RegExp>();
19504 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019505 CHECK(re->GetSource()->Equals(context.local(), v8_str("quux")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019506 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
Ben Murdochf87a2032010-10-22 12:50:53 +010019507
19508 re = CompileRun("/quux/gm").As<v8::RegExp>();
19509 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019510 CHECK(re->GetSource()->Equals(context.local(), v8_str("quux")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019511 CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
19512 static_cast<int>(re->GetFlags()));
Ben Murdochf87a2032010-10-22 12:50:53 +010019513
19514 // Override the RegExp constructor and check the API constructor
19515 // still works.
19516 CompileRun("RegExp = function() {}");
19517
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019518 re = v8::RegExp::New(context.local(), v8_str("foobar"), v8::RegExp::kNone)
19519 .ToLocalChecked();
Ben Murdochf87a2032010-10-22 12:50:53 +010019520 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019521 CHECK(re->GetSource()->Equals(context.local(), v8_str("foobar")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019522 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
Ben Murdochf87a2032010-10-22 12:50:53 +010019523
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019524 re = v8::RegExp::New(context.local(), v8_str("foobarbaz"),
Ben Murdochf87a2032010-10-22 12:50:53 +010019525 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019526 v8::RegExp::kMultiline))
19527 .ToLocalChecked();
Ben Murdochf87a2032010-10-22 12:50:53 +010019528 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019529 CHECK(
19530 re->GetSource()->Equals(context.local(), v8_str("foobarbaz")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019531 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
19532 static_cast<int>(re->GetFlags()));
Ben Murdochf87a2032010-10-22 12:50:53 +010019533
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019534 CHECK(context->Global()->Set(context.local(), v8_str("re"), re).FromJust());
Ben Murdochf87a2032010-10-22 12:50:53 +010019535 ExpectTrue("re.test('FoobarbaZ')");
19536
Ben Murdoch257744e2011-11-30 15:57:28 +000019537 // RegExps are objects on which you can set properties.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019538 re->Set(context.local(), v8_str("property"),
19539 v8::Integer::New(context->GetIsolate(), 32))
19540 .FromJust();
19541 v8::Local<v8::Value> value(CompileRun("re.property"));
19542 CHECK_EQ(32, value->Int32Value(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000019543
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019544 v8::TryCatch try_catch(context->GetIsolate());
19545 CHECK(v8::RegExp::New(context.local(), v8_str("foo["), v8::RegExp::kNone)
19546 .IsEmpty());
Ben Murdochf87a2032010-10-22 12:50:53 +010019547 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019548 CHECK(context->Global()
19549 ->Set(context.local(), v8_str("ex"), try_catch.Exception())
19550 .FromJust());
Ben Murdochf87a2032010-10-22 12:50:53 +010019551 ExpectTrue("ex instanceof SyntaxError");
19552}
19553
19554
Steve Block1e0659c2011-05-24 12:43:12 +010019555THREADED_TEST(Equals) {
Steve Block1e0659c2011-05-24 12:43:12 +010019556 LocalContext localContext;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019557 v8::HandleScope handleScope(localContext->GetIsolate());
Steve Block1e0659c2011-05-24 12:43:12 +010019558
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019559 v8::Local<v8::Object> globalProxy = localContext->Global();
19560 v8::Local<Value> global = globalProxy->GetPrototype();
Steve Block1e0659c2011-05-24 12:43:12 +010019561
19562 CHECK(global->StrictEquals(global));
19563 CHECK(!global->StrictEquals(globalProxy));
19564 CHECK(!globalProxy->StrictEquals(global));
19565 CHECK(globalProxy->StrictEquals(globalProxy));
19566
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019567 CHECK(global->Equals(localContext.local(), global).FromJust());
19568 CHECK(!global->Equals(localContext.local(), globalProxy).FromJust());
19569 CHECK(!globalProxy->Equals(localContext.local(), global).FromJust());
19570 CHECK(globalProxy->Equals(localContext.local(), globalProxy).FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +010019571}
19572
19573
Emily Bernierd0a1eb72015-03-24 16:35:39 -040019574static void Getter(v8::Local<v8::Name> property,
19575 const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019576 info.GetReturnValue().Set(v8_str("42!"));
Ben Murdochf87a2032010-10-22 12:50:53 +010019577}
19578
19579
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019580static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019581 v8::Local<v8::Array> result = v8::Array::New(info.GetIsolate());
19582 result->Set(info.GetIsolate()->GetCurrentContext(), 0,
19583 v8_str("universalAnswer"))
19584 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019585 info.GetReturnValue().Set(result);
Ben Murdochf87a2032010-10-22 12:50:53 +010019586}
19587
19588
19589TEST(NamedEnumeratorAndForIn) {
Ben Murdochf87a2032010-10-22 12:50:53 +010019590 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019591 v8::Isolate* isolate = context->GetIsolate();
19592 v8::HandleScope handle_scope(isolate);
Ben Murdochf87a2032010-10-22 12:50:53 +010019593 v8::Context::Scope context_scope(context.local());
19594
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019595 v8::Local<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040019596 tmpl->SetHandler(v8::NamedPropertyHandlerConfiguration(Getter, NULL, NULL,
19597 NULL, Enumerator));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019598 CHECK(context->Global()
19599 ->Set(context.local(), v8_str("o"),
19600 tmpl->NewInstance(context.local()).ToLocalChecked())
19601 .FromJust());
19602 v8::Local<v8::Array> result = v8::Local<v8::Array>::Cast(
19603 CompileRun("var result = []; for (var k in o) result.push(k); result"));
19604 CHECK_EQ(1u, result->Length());
19605 CHECK(v8_str("universalAnswer")
19606 ->Equals(context.local(),
19607 result->Get(context.local(), 0).ToLocalChecked())
19608 .FromJust());
Ben Murdochf87a2032010-10-22 12:50:53 +010019609}
Steve Block1e0659c2011-05-24 12:43:12 +010019610
19611
19612TEST(DefinePropertyPostDetach) {
Steve Block1e0659c2011-05-24 12:43:12 +010019613 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019614 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019615 v8::Local<v8::Object> proxy = context->Global();
19616 v8::Local<v8::Function> define_property =
19617 CompileRun(
19618 "(function() {"
19619 " Object.defineProperty("
19620 " this,"
19621 " 1,"
19622 " { configurable: true, enumerable: true, value: 3 });"
19623 "})")
19624 .As<Function>();
Steve Block1e0659c2011-05-24 12:43:12 +010019625 context->DetachGlobal();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019626 CHECK(define_property->Call(context.local(), proxy, 0, NULL).IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +010019627}
Ben Murdoch8b112d22011-06-08 16:22:53 +010019628
19629
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019630static void InstallContextId(v8::Local<Context> context, int id) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010019631 Context::Scope scope(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019632 CHECK(CompileRun("Object.prototype")
19633 .As<Object>()
19634 ->Set(context, v8_str("context_id"),
19635 v8::Integer::New(context->GetIsolate(), id))
19636 .FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010019637}
19638
19639
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019640static void CheckContextId(v8::Local<Object> object, int expected) {
19641 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
19642 CHECK_EQ(expected, object->Get(context, v8_str("context_id"))
19643 .ToLocalChecked()
19644 ->Int32Value(context)
19645 .FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010019646}
19647
19648
19649THREADED_TEST(CreationContext) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019650 v8::Isolate* isolate = CcTest::isolate();
19651 HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019652 Local<Context> context1 = Context::New(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +010019653 InstallContextId(context1, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019654 Local<Context> context2 = Context::New(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +010019655 InstallContextId(context2, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019656 Local<Context> context3 = Context::New(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +010019657 InstallContextId(context3, 3);
19658
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019659 Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +010019660
19661 Local<Object> object1;
19662 Local<Function> func1;
19663 {
19664 Context::Scope scope(context1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019665 object1 = Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019666 func1 = tmpl->GetFunction(context1).ToLocalChecked();
Ben Murdoch8b112d22011-06-08 16:22:53 +010019667 }
19668
19669 Local<Object> object2;
19670 Local<Function> func2;
19671 {
19672 Context::Scope scope(context2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019673 object2 = Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019674 func2 = tmpl->GetFunction(context2).ToLocalChecked();
Ben Murdoch8b112d22011-06-08 16:22:53 +010019675 }
19676
19677 Local<Object> instance1;
19678 Local<Object> instance2;
19679
19680 {
19681 Context::Scope scope(context3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019682 instance1 = func1->NewInstance(context3).ToLocalChecked();
19683 instance2 = func2->NewInstance(context3).ToLocalChecked();
Ben Murdoch8b112d22011-06-08 16:22:53 +010019684 }
19685
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019686 {
19687 Local<Context> other_context = Context::New(isolate);
19688 Context::Scope scope(other_context);
19689 CHECK(object1->CreationContext() == context1);
19690 CheckContextId(object1, 1);
19691 CHECK(func1->CreationContext() == context1);
19692 CheckContextId(func1, 1);
19693 CHECK(instance1->CreationContext() == context1);
19694 CheckContextId(instance1, 1);
19695 CHECK(object2->CreationContext() == context2);
19696 CheckContextId(object2, 2);
19697 CHECK(func2->CreationContext() == context2);
19698 CheckContextId(func2, 2);
19699 CHECK(instance2->CreationContext() == context2);
19700 CheckContextId(instance2, 2);
19701 }
Ben Murdoch8b112d22011-06-08 16:22:53 +010019702
19703 {
19704 Context::Scope scope(context1);
19705 CHECK(object1->CreationContext() == context1);
19706 CheckContextId(object1, 1);
19707 CHECK(func1->CreationContext() == context1);
19708 CheckContextId(func1, 1);
19709 CHECK(instance1->CreationContext() == context1);
19710 CheckContextId(instance1, 1);
19711 CHECK(object2->CreationContext() == context2);
19712 CheckContextId(object2, 2);
19713 CHECK(func2->CreationContext() == context2);
19714 CheckContextId(func2, 2);
19715 CHECK(instance2->CreationContext() == context2);
19716 CheckContextId(instance2, 2);
19717 }
19718
19719 {
19720 Context::Scope scope(context2);
19721 CHECK(object1->CreationContext() == context1);
19722 CheckContextId(object1, 1);
19723 CHECK(func1->CreationContext() == context1);
19724 CheckContextId(func1, 1);
19725 CHECK(instance1->CreationContext() == context1);
19726 CheckContextId(instance1, 1);
19727 CHECK(object2->CreationContext() == context2);
19728 CheckContextId(object2, 2);
19729 CHECK(func2->CreationContext() == context2);
19730 CheckContextId(func2, 2);
19731 CHECK(instance2->CreationContext() == context2);
19732 CheckContextId(instance2, 2);
19733 }
Ben Murdoch8b112d22011-06-08 16:22:53 +010019734}
Ben Murdoch257744e2011-11-30 15:57:28 +000019735
19736
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019737THREADED_TEST(CreationContextOfJsFunction) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019738 HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019739 Local<Context> context = Context::New(CcTest::isolate());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019740 InstallContextId(context, 1);
19741
19742 Local<Object> function;
19743 {
19744 Context::Scope scope(context);
19745 function = CompileRun("function foo() {}; foo").As<Object>();
19746 }
19747
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019748 Local<Context> other_context = Context::New(CcTest::isolate());
19749 Context::Scope scope(other_context);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019750 CHECK(function->CreationContext() == context);
19751 CheckContextId(function, 1);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019752}
19753
19754
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019755THREADED_TEST(CreationContextOfJsBoundFunction) {
19756 HandleScope handle_scope(CcTest::isolate());
19757 Local<Context> context1 = Context::New(CcTest::isolate());
19758 InstallContextId(context1, 1);
19759 Local<Context> context2 = Context::New(CcTest::isolate());
19760 InstallContextId(context2, 2);
19761
19762 Local<Function> target_function;
19763 {
19764 Context::Scope scope(context1);
19765 target_function = CompileRun("function foo() {}; foo").As<Function>();
19766 }
19767
19768 Local<Function> bound_function1, bound_function2;
19769 {
19770 Context::Scope scope(context2);
19771 CHECK(context2->Global()
19772 ->Set(context2, v8_str("foo"), target_function)
19773 .FromJust());
19774 bound_function1 = CompileRun("foo.bind(1)").As<Function>();
19775 bound_function2 =
19776 CompileRun("Function.prototype.bind.call(foo, 2)").As<Function>();
19777 }
19778
19779 Local<Context> other_context = Context::New(CcTest::isolate());
19780 Context::Scope scope(other_context);
19781 CHECK(bound_function1->CreationContext() == context1);
19782 CheckContextId(bound_function1, 1);
19783 CHECK(bound_function2->CreationContext() == context2);
19784 CheckContextId(bound_function2, 1);
19785}
19786
19787
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019788void HasOwnPropertyIndexedPropertyGetter(
19789 uint32_t index,
19790 const v8::PropertyCallbackInfo<v8::Value>& info) {
19791 if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
Ben Murdoch257744e2011-11-30 15:57:28 +000019792}
19793
19794
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019795void HasOwnPropertyNamedPropertyGetter(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040019796 Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019797 if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
19798 .FromJust()) {
19799 info.GetReturnValue().Set(v8_str("yes"));
19800 }
Ben Murdoch257744e2011-11-30 15:57:28 +000019801}
19802
19803
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019804void HasOwnPropertyIndexedPropertyQuery(
19805 uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
19806 if (index == 42) info.GetReturnValue().Set(1);
Ben Murdoch257744e2011-11-30 15:57:28 +000019807}
19808
19809
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019810void HasOwnPropertyNamedPropertyQuery(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040019811 Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019812 if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
19813 .FromJust()) {
19814 info.GetReturnValue().Set(1);
19815 }
Ben Murdoch257744e2011-11-30 15:57:28 +000019816}
19817
19818
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019819void HasOwnPropertyNamedPropertyQuery2(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040019820 Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019821 if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("bar"))
19822 .FromJust()) {
19823 info.GetReturnValue().Set(1);
19824 }
Ben Murdoch257744e2011-11-30 15:57:28 +000019825}
19826
19827
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019828void HasOwnPropertyAccessorGetter(
19829 Local<String> property,
19830 const v8::PropertyCallbackInfo<v8::Value>& info) {
19831 info.GetReturnValue().Set(v8_str("yes"));
Ben Murdoch257744e2011-11-30 15:57:28 +000019832}
19833
19834
19835TEST(HasOwnProperty) {
Ben Murdoch257744e2011-11-30 15:57:28 +000019836 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019837 v8::Isolate* isolate = env->GetIsolate();
19838 v8::HandleScope scope(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000019839 { // Check normal properties and defined getters.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019840 Local<Value> value = CompileRun(
Ben Murdoch257744e2011-11-30 15:57:28 +000019841 "function Foo() {"
19842 " this.foo = 11;"
19843 " this.__defineGetter__('baz', function() { return 1; });"
19844 "};"
19845 "function Bar() { "
19846 " this.bar = 13;"
19847 " this.__defineGetter__('bla', function() { return 2; });"
19848 "};"
19849 "Bar.prototype = new Foo();"
19850 "new Bar();");
19851 CHECK(value->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019852 Local<Object> object = value->ToObject(env.local()).ToLocalChecked();
19853 CHECK(object->Has(env.local(), v8_str("foo")).FromJust());
19854 CHECK(!object->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
19855 CHECK(object->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
19856 CHECK(object->Has(env.local(), v8_str("baz")).FromJust());
19857 CHECK(!object->HasOwnProperty(env.local(), v8_str("baz")).FromJust());
19858 CHECK(object->HasOwnProperty(env.local(), v8_str("bla")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000019859 }
19860 { // Check named getter interceptors.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019861 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040019862 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
19863 HasOwnPropertyNamedPropertyGetter));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019864 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
19865 CHECK(!instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
19866 CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
19867 CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000019868 }
19869 { // Check indexed getter interceptors.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019870 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040019871 templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
19872 HasOwnPropertyIndexedPropertyGetter));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019873 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
19874 CHECK(instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
19875 CHECK(!instance->HasOwnProperty(env.local(), v8_str("43")).FromJust());
19876 CHECK(!instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000019877 }
19878 { // Check named query interceptors.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019879 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040019880 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
19881 0, 0, HasOwnPropertyNamedPropertyQuery));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019882 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
19883 CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
19884 CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000019885 }
19886 { // Check indexed query interceptors.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019887 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040019888 templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
19889 0, 0, HasOwnPropertyIndexedPropertyQuery));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019890 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
19891 CHECK(instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
19892 CHECK(!instance->HasOwnProperty(env.local(), v8_str("41")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000019893 }
19894 { // Check callbacks.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019895 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000019896 templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019897 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
19898 CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
19899 CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000019900 }
19901 { // Check that query wins on disagreement.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019902 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040019903 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
19904 HasOwnPropertyNamedPropertyGetter, 0,
19905 HasOwnPropertyNamedPropertyQuery2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019906 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
19907 CHECK(!instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
19908 CHECK(instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000019909 }
19910}
19911
19912
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019913TEST(IndexedInterceptorWithStringProto) {
19914 v8::Isolate* isolate = CcTest::isolate();
19915 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019916 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040019917 templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
19918 NULL, NULL, HasOwnPropertyIndexedPropertyQuery));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019919 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019920 CHECK(context->Global()
19921 ->Set(context.local(), v8_str("obj"),
19922 templ->NewInstance(context.local()).ToLocalChecked())
19923 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019924 CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
19925 // These should be intercepted.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019926 CHECK(CompileRun("42 in obj")->BooleanValue(context.local()).FromJust());
19927 CHECK(CompileRun("'42' in obj")->BooleanValue(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019928 // These should fall through to the String prototype.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019929 CHECK(CompileRun("0 in obj")->BooleanValue(context.local()).FromJust());
19930 CHECK(CompileRun("'0' in obj")->BooleanValue(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019931 // And these should both fail.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019932 CHECK(!CompileRun("32 in obj")->BooleanValue(context.local()).FromJust());
19933 CHECK(!CompileRun("'32' in obj")->BooleanValue(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019934}
19935
19936
Ben Murdoch257744e2011-11-30 15:57:28 +000019937void CheckCodeGenerationAllowed() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019938 Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
19939 Local<Value> result = CompileRun("eval('42')");
19940 CHECK_EQ(42, result->Int32Value(context).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000019941 result = CompileRun("(function(e) { return e('42'); })(eval)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019942 CHECK_EQ(42, result->Int32Value(context).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000019943 result = CompileRun("var f = new Function('return 42'); f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019944 CHECK_EQ(42, result->Int32Value(context).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000019945}
19946
19947
19948void CheckCodeGenerationDisallowed() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019949 TryCatch try_catch(CcTest::isolate());
Ben Murdoch257744e2011-11-30 15:57:28 +000019950
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019951 Local<Value> result = CompileRun("eval('42')");
Ben Murdoch257744e2011-11-30 15:57:28 +000019952 CHECK(result.IsEmpty());
19953 CHECK(try_catch.HasCaught());
19954 try_catch.Reset();
19955
19956 result = CompileRun("(function(e) { return e('42'); })(eval)");
19957 CHECK(result.IsEmpty());
19958 CHECK(try_catch.HasCaught());
19959 try_catch.Reset();
19960
19961 result = CompileRun("var f = new Function('return 42'); f()");
19962 CHECK(result.IsEmpty());
19963 CHECK(try_catch.HasCaught());
19964}
19965
19966
19967bool CodeGenerationAllowed(Local<Context> context) {
19968 ApiTestFuzzer::Fuzz();
19969 return true;
19970}
19971
19972
19973bool CodeGenerationDisallowed(Local<Context> context) {
19974 ApiTestFuzzer::Fuzz();
19975 return false;
19976}
19977
19978
19979THREADED_TEST(AllowCodeGenFromStrings) {
Ben Murdoch257744e2011-11-30 15:57:28 +000019980 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019981 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch257744e2011-11-30 15:57:28 +000019982
19983 // eval and the Function constructor allowed by default.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010019984 CHECK(context->IsCodeGenerationFromStringsAllowed());
Ben Murdoch257744e2011-11-30 15:57:28 +000019985 CheckCodeGenerationAllowed();
19986
19987 // Disallow eval and the Function constructor.
19988 context->AllowCodeGenerationFromStrings(false);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010019989 CHECK(!context->IsCodeGenerationFromStringsAllowed());
Ben Murdoch257744e2011-11-30 15:57:28 +000019990 CheckCodeGenerationDisallowed();
19991
19992 // Allow again.
19993 context->AllowCodeGenerationFromStrings(true);
19994 CheckCodeGenerationAllowed();
19995
19996 // Disallow but setting a global callback that will allow the calls.
19997 context->AllowCodeGenerationFromStrings(false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019998 context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
19999 &CodeGenerationAllowed);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020000 CHECK(!context->IsCodeGenerationFromStringsAllowed());
Ben Murdoch257744e2011-11-30 15:57:28 +000020001 CheckCodeGenerationAllowed();
20002
20003 // Set a callback that disallows the code generation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020004 context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
20005 &CodeGenerationDisallowed);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020006 CHECK(!context->IsCodeGenerationFromStringsAllowed());
Ben Murdoch257744e2011-11-30 15:57:28 +000020007 CheckCodeGenerationDisallowed();
20008}
20009
20010
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020011TEST(SetErrorMessageForCodeGenFromStrings) {
20012 LocalContext context;
20013 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020014 TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020015
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020016 Local<String> message = v8_str("Message");
20017 Local<String> expected_message = v8_str("Uncaught EvalError: Message");
20018 context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
20019 &CodeGenerationDisallowed);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020020 context->AllowCodeGenerationFromStrings(false);
20021 context->SetErrorMessageForCodeGenerationFromStrings(message);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020022 Local<Value> result = CompileRun("eval('42')");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020023 CHECK(result.IsEmpty());
20024 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020025 Local<String> actual_message = try_catch.Message()->Get();
20026 CHECK(expected_message->Equals(context.local(), actual_message).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020027}
20028
20029
20030static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch257744e2011-11-30 15:57:28 +000020031}
20032
20033
20034THREADED_TEST(CallAPIFunctionOnNonObject) {
Ben Murdoch257744e2011-11-30 15:57:28 +000020035 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020036 v8::Isolate* isolate = context->GetIsolate();
20037 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020038 Local<FunctionTemplate> templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020039 v8::FunctionTemplate::New(isolate, NonObjectThis);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020040 Local<Function> function =
20041 templ->GetFunction(context.local()).ToLocalChecked();
20042 CHECK(context->Global()
20043 ->Set(context.local(), v8_str("f"), function)
20044 .FromJust());
20045 TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000020046 CompileRun("f.call(2)");
20047}
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020048
20049
20050// Regression test for issue 1470.
20051THREADED_TEST(ReadOnlyIndexedProperties) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020052 v8::Isolate* isolate = CcTest::isolate();
20053 v8::HandleScope scope(isolate);
20054 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020055
20056 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020057 Local<v8::Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
20058 CHECK(context->Global()->Set(context.local(), v8_str("obj"), obj).FromJust());
20059 obj->DefineOwnProperty(context.local(), v8_str("1"), v8_str("DONT_CHANGE"),
20060 v8::ReadOnly)
20061 .FromJust();
20062 obj->Set(context.local(), v8_str("1"), v8_str("foobar")).FromJust();
20063 CHECK(v8_str("DONT_CHANGE")
20064 ->Equals(context.local(),
20065 obj->Get(context.local(), v8_str("1")).ToLocalChecked())
20066 .FromJust());
20067 obj->DefineOwnProperty(context.local(), v8_str("2"), v8_str("DONT_CHANGE"),
20068 v8::ReadOnly)
20069 .FromJust();
20070 obj->Set(context.local(), v8_num(2), v8_str("foobar")).FromJust();
20071 CHECK(v8_str("DONT_CHANGE")
20072 ->Equals(context.local(),
20073 obj->Get(context.local(), v8_num(2)).ToLocalChecked())
20074 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020075
20076 // Test non-smi case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020077 obj->DefineOwnProperty(context.local(), v8_str("2000000000"),
20078 v8_str("DONT_CHANGE"), v8::ReadOnly)
20079 .FromJust();
20080 obj->Set(context.local(), v8_str("2000000000"), v8_str("foobar")).FromJust();
20081 CHECK(v8_str("DONT_CHANGE")
20082 ->Equals(context.local(),
20083 obj->Get(context.local(), v8_str("2000000000"))
20084 .ToLocalChecked())
20085 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020086}
20087
20088
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020089static int CountLiveMapsInMapCache(i::Context* context) {
20090 i::FixedArray* map_cache = i::FixedArray::cast(context->map_cache());
20091 int length = map_cache->length();
20092 int count = 0;
20093 for (int i = 0; i < length; i++) {
20094 i::Object* value = map_cache->get(i);
20095 if (value->IsWeakCell() && !i::WeakCell::cast(value)->cleared()) count++;
20096 }
20097 return count;
20098}
20099
20100
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020101THREADED_TEST(Regress1516) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020102 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020103 v8::HandleScope scope(context->GetIsolate());
20104
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020105 // Object with 20 properties is not a common case, so it should be removed
20106 // from the cache after GC.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020107 { v8::HandleScope temp_scope(context->GetIsolate());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020108 CompileRun(
20109 "({"
20110 "'a00': 0, 'a01': 0, 'a02': 0, 'a03': 0, 'a04': 0, "
20111 "'a05': 0, 'a06': 0, 'a07': 0, 'a08': 0, 'a09': 0, "
20112 "'a10': 0, 'a11': 0, 'a12': 0, 'a13': 0, 'a14': 0, "
20113 "'a15': 0, 'a16': 0, 'a17': 0, 'a18': 0, 'a19': 0, "
20114 "})");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020115 }
20116
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020117 int elements = CountLiveMapsInMapCache(CcTest::i_isolate()->context());
20118 CHECK_LE(1, elements);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020119
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020120 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020121
20122 CHECK_GT(elements, CountLiveMapsInMapCache(CcTest::i_isolate()->context()));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020123}
20124
20125
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020126THREADED_TEST(Regress93759) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020127 v8::Isolate* isolate = CcTest::isolate();
20128 HandleScope scope(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020129
20130 // Template for object with security check.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020131 Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020132 no_proto_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020133
20134 // Templates for objects with hidden prototypes and possibly security check.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020135 Local<FunctionTemplate> hidden_proto_template =
20136 v8::FunctionTemplate::New(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020137 hidden_proto_template->SetHiddenPrototype(true);
20138
20139 Local<FunctionTemplate> protected_hidden_proto_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020140 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020141 protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallback(
20142 AccessAlwaysBlocked);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020143 protected_hidden_proto_template->SetHiddenPrototype(true);
20144
20145 // Context for "foreign" objects used in test.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020146 Local<Context> context = v8::Context::New(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020147 context->Enter();
20148
20149 // Plain object, no security check.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020150 Local<Object> simple_object = Object::New(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020151
20152 // Object with explicit security check.
20153 Local<Object> protected_object =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020154 no_proto_template->NewInstance(context).ToLocalChecked();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020155
20156 // JSGlobalProxy object, always have security check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020157 Local<Object> proxy_object = context->Global();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020158
20159 // Global object, the prototype of proxy_object. No security checks.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020160 Local<Object> global_object =
20161 proxy_object->GetPrototype()->ToObject(context).ToLocalChecked();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020162
20163 // Hidden prototype without security check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020164 Local<Object> hidden_prototype = hidden_proto_template->GetFunction(context)
20165 .ToLocalChecked()
20166 ->NewInstance(context)
20167 .ToLocalChecked();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020168 Local<Object> object_with_hidden =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020169 Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020170 object_with_hidden->SetPrototype(context, hidden_prototype).FromJust();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020171
20172 context->Exit();
20173
20174 // Template for object for second context. Values to test are put on it as
20175 // properties.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020176 Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020177 global_template->Set(v8_str("simple"), simple_object);
20178 global_template->Set(v8_str("protected"), protected_object);
20179 global_template->Set(v8_str("global"), global_object);
20180 global_template->Set(v8_str("proxy"), proxy_object);
20181 global_template->Set(v8_str("hidden"), object_with_hidden);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020182
20183 LocalContext context2(NULL, global_template);
20184
20185 Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020186 CHECK(result1->Equals(context2.local(), simple_object->GetPrototype())
20187 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020188
20189 Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020190 CHECK(result2->IsNull());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020191
20192 Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020193 CHECK(result3->Equals(context2.local(), global_object->GetPrototype())
20194 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020195
20196 Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020197 CHECK(result4->IsNull());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020198
20199 Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020200 CHECK(result5->Equals(context2.local(), object_with_hidden->GetPrototype()
20201 ->ToObject(context2.local())
20202 .ToLocalChecked()
20203 ->GetPrototype())
20204 .FromJust());
Ben Murdoch5710cea2012-05-21 14:52:42 +010020205}
20206
20207
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020208static void TestReceiver(Local<Value> expected_result,
20209 Local<Value> expected_receiver,
20210 const char* code) {
20211 Local<Value> result = CompileRun(code);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020212 Local<Context> context = CcTest::isolate()->GetCurrentContext();
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020213 CHECK(result->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020214 CHECK(expected_receiver
20215 ->Equals(context,
20216 result.As<v8::Object>()->Get(context, 1).ToLocalChecked())
20217 .FromJust());
20218 CHECK(expected_result
20219 ->Equals(context,
20220 result.As<v8::Object>()->Get(context, 0).ToLocalChecked())
20221 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020222}
20223
20224
20225THREADED_TEST(ForeignFunctionReceiver) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020226 v8::Isolate* isolate = CcTest::isolate();
20227 HandleScope scope(isolate);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020228
20229 // Create two contexts with different "id" properties ('i' and 'o').
20230 // Call a function both from its own context and from a the foreign
20231 // context, and see what "this" is bound to (returning both "this"
20232 // and "this.id" for comparison).
20233
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020234 Local<Context> foreign_context = v8::Context::New(isolate);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020235 foreign_context->Enter();
20236 Local<Value> foreign_function =
20237 CompileRun("function func() { return { 0: this.id, "
20238 " 1: this, "
20239 " toString: function() { "
20240 " return this[0];"
20241 " }"
20242 " };"
20243 "}"
20244 "var id = 'i';"
20245 "func;");
20246 CHECK(foreign_function->IsFunction());
20247 foreign_context->Exit();
20248
20249 LocalContext context;
20250
20251 Local<String> password = v8_str("Password");
20252 // Don't get hit by security checks when accessing foreign_context's
20253 // global receiver (aka. global proxy).
20254 context->SetSecurityToken(password);
20255 foreign_context->SetSecurityToken(password);
20256
20257 Local<String> i = v8_str("i");
20258 Local<String> o = v8_str("o");
20259 Local<String> id = v8_str("id");
20260
20261 CompileRun("function ownfunc() { return { 0: this.id, "
20262 " 1: this, "
20263 " toString: function() { "
20264 " return this[0];"
20265 " }"
20266 " };"
20267 "}"
20268 "var id = 'o';"
20269 "ownfunc");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020270 CHECK(context->Global()
20271 ->Set(context.local(), v8_str("func"), foreign_function)
20272 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020273
20274 // Sanity check the contexts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020275 CHECK(
20276 i->Equals(
20277 context.local(),
20278 foreign_context->Global()->Get(context.local(), id).ToLocalChecked())
20279 .FromJust());
20280 CHECK(o->Equals(context.local(),
20281 context->Global()->Get(context.local(), id).ToLocalChecked())
20282 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020283
20284 // Checking local function's receiver.
20285 // Calling function using its call/apply methods.
20286 TestReceiver(o, context->Global(), "ownfunc.call()");
20287 TestReceiver(o, context->Global(), "ownfunc.apply()");
20288 // Making calls through built-in functions.
20289 TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020290 CHECK(
20291 o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/,ownfunc)[1]"))
20292 .FromJust());
20293 CHECK(
20294 o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]"))
20295 .FromJust());
20296 CHECK(
20297 o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]"))
20298 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020299 // Calling with environment record as base.
20300 TestReceiver(o, context->Global(), "ownfunc()");
20301 // Calling with no base.
20302 TestReceiver(o, context->Global(), "(1,ownfunc)()");
20303
20304 // Checking foreign function return value.
20305 // Calling function using its call/apply methods.
20306 TestReceiver(i, foreign_context->Global(), "func.call()");
20307 TestReceiver(i, foreign_context->Global(), "func.apply()");
20308 // Calling function using another context's call/apply methods.
20309 TestReceiver(i, foreign_context->Global(),
20310 "Function.prototype.call.call(func)");
20311 TestReceiver(i, foreign_context->Global(),
20312 "Function.prototype.call.apply(func)");
20313 TestReceiver(i, foreign_context->Global(),
20314 "Function.prototype.apply.call(func)");
20315 TestReceiver(i, foreign_context->Global(),
20316 "Function.prototype.apply.apply(func)");
20317 // Making calls through built-in functions.
20318 TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
20319 // ToString(func()) is func()[0], i.e., the returned this.id.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020320 CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/,func)[1]"))
20321 .FromJust());
20322 CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,func)[1]"))
20323 .FromJust());
20324 CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,func)[3]"))
20325 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020326
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020327 // Calling with environment record as base.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020328 TestReceiver(i, foreign_context->Global(), "func()");
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020329 // Calling with no base.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020330 TestReceiver(i, foreign_context->Global(), "(1,func)()");
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020331}
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020332
20333
20334uint8_t callback_fired = 0;
20335
20336
20337void CallCompletedCallback1() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020338 v8::base::OS::Print("Firing callback 1.\n");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020339 callback_fired ^= 1; // Toggle first bit.
20340}
20341
20342
20343void CallCompletedCallback2() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020344 v8::base::OS::Print("Firing callback 2.\n");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020345 callback_fired ^= 2; // Toggle second bit.
20346}
20347
20348
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020349void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020350 int32_t level =
20351 args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020352 if (level < 3) {
20353 level++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020354 v8::base::OS::Print("Entering recursion level %d.\n", level);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020355 char script[64];
20356 i::Vector<char> script_vector(script, sizeof(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020357 i::SNPrintF(script_vector, "recursion(%d)", level);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020358 CompileRun(script_vector.start());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020359 v8::base::OS::Print("Leaving recursion level %d.\n", level);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020360 CHECK_EQ(0, callback_fired);
20361 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020362 v8::base::OS::Print("Recursion ends.\n");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020363 CHECK_EQ(0, callback_fired);
20364 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020365}
20366
20367
20368TEST(CallCompletedCallback) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020369 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020370 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020371 v8::Local<v8::FunctionTemplate> recursive_runtime =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020372 v8::FunctionTemplate::New(env->GetIsolate(), RecursiveCall);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020373 env->Global()
20374 ->Set(env.local(), v8_str("recursion"),
20375 recursive_runtime->GetFunction(env.local()).ToLocalChecked())
20376 .FromJust();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020377 // Adding the same callback a second time has no effect.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020378 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
20379 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
20380 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback2);
20381 v8::base::OS::Print("--- Script (1) ---\n");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020382 Local<Script> script =
20383 v8::Script::Compile(env.local(), v8_str("recursion(0)")).ToLocalChecked();
20384 script->Run(env.local()).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020385 CHECK_EQ(3, callback_fired);
20386
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020387 v8::base::OS::Print("\n--- Script (2) ---\n");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020388 callback_fired = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020389 env->GetIsolate()->RemoveCallCompletedCallback(CallCompletedCallback1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020390 script->Run(env.local()).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020391 CHECK_EQ(2, callback_fired);
20392
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020393 v8::base::OS::Print("\n--- Function ---\n");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020394 callback_fired = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020395 Local<Function> recursive_function = Local<Function>::Cast(
20396 env->Global()->Get(env.local(), v8_str("recursion")).ToLocalChecked());
20397 v8::Local<Value> args[] = {v8_num(0)};
20398 recursive_function->Call(env.local(), env->Global(), 1, args)
20399 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020400 CHECK_EQ(2, callback_fired);
20401}
20402
20403
20404void CallCompletedCallbackNoException() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020405 v8::HandleScope scope(CcTest::isolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020406 CompileRun("1+1;");
20407}
20408
20409
20410void CallCompletedCallbackException() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020411 v8::HandleScope scope(CcTest::isolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020412 CompileRun("throw 'second exception';");
20413}
20414
20415
20416TEST(CallCompletedCallbackOneException) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020417 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020418 v8::HandleScope scope(env->GetIsolate());
20419 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackNoException);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020420 CompileRun("throw 'exception';");
20421}
20422
20423
20424TEST(CallCompletedCallbackTwoExceptions) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020425 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020426 v8::HandleScope scope(env->GetIsolate());
20427 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackException);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020428 CompileRun("throw 'first exception';");
20429}
20430
20431
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020432static void MicrotaskOne(const v8::FunctionCallbackInfo<Value>& info) {
20433 v8::HandleScope scope(info.GetIsolate());
20434 CompileRun("ext1Calls++;");
20435}
20436
20437
20438static void MicrotaskTwo(const v8::FunctionCallbackInfo<Value>& info) {
20439 v8::HandleScope scope(info.GetIsolate());
20440 CompileRun("ext2Calls++;");
20441}
20442
20443
20444void* g_passed_to_three = NULL;
20445
20446
20447static void MicrotaskThree(void* data) {
20448 g_passed_to_three = data;
20449}
20450
20451
20452TEST(EnqueueMicrotask) {
20453 LocalContext env;
20454 v8::HandleScope scope(env->GetIsolate());
20455 CompileRun(
20456 "var ext1Calls = 0;"
20457 "var ext2Calls = 0;");
20458 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020459 CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20460 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020461
20462 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020463 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020464 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020465 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20466 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020467
20468 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020469 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020470 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020471 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020472 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020473 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20474 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020475
20476 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020477 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020478 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020479 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20480 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020481
20482 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020483 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20484 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020485
20486 g_passed_to_three = NULL;
20487 env->GetIsolate()->EnqueueMicrotask(MicrotaskThree);
20488 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020489 CHECK(!g_passed_to_three);
20490 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20491 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020492
20493 int dummy;
20494 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020495 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020496 env->GetIsolate()->EnqueueMicrotask(MicrotaskThree, &dummy);
20497 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020498 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020499 CompileRun("1+1;");
20500 CHECK_EQ(&dummy, g_passed_to_three);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020501 CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20502 CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020503 g_passed_to_three = NULL;
20504}
20505
20506
20507static void MicrotaskExceptionOne(
20508 const v8::FunctionCallbackInfo<Value>& info) {
20509 v8::HandleScope scope(info.GetIsolate());
20510 CompileRun("exception1Calls++;");
20511 info.GetIsolate()->ThrowException(
20512 v8::Exception::Error(v8_str("first")));
20513}
20514
20515
20516static void MicrotaskExceptionTwo(
20517 const v8::FunctionCallbackInfo<Value>& info) {
20518 v8::HandleScope scope(info.GetIsolate());
20519 CompileRun("exception2Calls++;");
20520 info.GetIsolate()->ThrowException(
20521 v8::Exception::Error(v8_str("second")));
20522}
20523
20524
20525TEST(RunMicrotasksIgnoresThrownExceptions) {
20526 LocalContext env;
20527 v8::Isolate* isolate = env->GetIsolate();
20528 v8::HandleScope scope(isolate);
20529 CompileRun(
20530 "var exception1Calls = 0;"
20531 "var exception2Calls = 0;");
20532 isolate->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020533 Function::New(env.local(), MicrotaskExceptionOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020534 isolate->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020535 Function::New(env.local(), MicrotaskExceptionTwo).ToLocalChecked());
20536 TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020537 CompileRun("1+1;");
20538 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020539 CHECK_EQ(1,
20540 CompileRun("exception1Calls")->Int32Value(env.local()).FromJust());
20541 CHECK_EQ(1,
20542 CompileRun("exception2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020543}
20544
20545
20546TEST(SetAutorunMicrotasks) {
20547 LocalContext env;
20548 v8::HandleScope scope(env->GetIsolate());
20549 CompileRun(
20550 "var ext1Calls = 0;"
20551 "var ext2Calls = 0;");
20552 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020553 CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20554 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020555
20556 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020557 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020558 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020559 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20560 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020561
20562 env->GetIsolate()->SetAutorunMicrotasks(false);
20563 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020564 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020565 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020566 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020567 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020568 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20569 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020570
20571 env->GetIsolate()->RunMicrotasks();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020572 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20573 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020574
20575 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020576 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020577 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020578 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20579 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020580
20581 env->GetIsolate()->RunMicrotasks();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020582 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20583 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020584
20585 env->GetIsolate()->SetAutorunMicrotasks(true);
20586 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020587 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020588 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020589 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20590 CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020591
20592 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020593 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020594 {
20595 v8::Isolate::SuppressMicrotaskExecutionScope scope(env->GetIsolate());
20596 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020597 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20598 CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020599 }
20600
20601 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020602 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
20603 CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020604}
20605
20606
20607TEST(RunMicrotasksWithoutEnteringContext) {
20608 v8::Isolate* isolate = CcTest::isolate();
20609 HandleScope handle_scope(isolate);
20610 isolate->SetAutorunMicrotasks(false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020611 Local<Context> context = Context::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020612 {
20613 Context::Scope context_scope(context);
20614 CompileRun("var ext1Calls = 0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020615 isolate->EnqueueMicrotask(
20616 Function::New(context, MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020617 }
20618 isolate->RunMicrotasks();
20619 {
20620 Context::Scope context_scope(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020621 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020622 }
20623 isolate->SetAutorunMicrotasks(true);
20624}
20625
20626
20627static void DebugEventInObserver(const v8::Debug::EventDetails& event_details) {
20628 v8::DebugEvent event = event_details.GetEvent();
20629 if (event != v8::Break) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020630 Local<Object> exec_state = event_details.GetExecutionState();
20631 Local<Context> context = CcTest::isolate()->GetCurrentContext();
20632 Local<Value> break_id =
20633 exec_state->Get(context, v8_str("break_id")).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020634 CompileRun("function f(id) { new FrameDetails(id, 0); }");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020635 Local<Function> fun = Local<Function>::Cast(
20636 CcTest::global()->Get(context, v8_str("f")).ToLocalChecked());
20637 fun->Call(context, CcTest::global(), 1, &break_id).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020638}
20639
20640
20641TEST(Regress385349) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020642 i::FLAG_harmony_object_observe = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020643 i::FLAG_allow_natives_syntax = true;
20644 v8::Isolate* isolate = CcTest::isolate();
20645 HandleScope handle_scope(isolate);
20646 isolate->SetAutorunMicrotasks(false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020647 Local<Context> context = Context::New(isolate);
20648 v8::Debug::SetDebugEventListener(isolate, DebugEventInObserver);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020649 {
20650 Context::Scope context_scope(context);
20651 CompileRun("var obj = {};"
20652 "Object.observe(obj, function(changes) { debugger; });"
20653 "obj.a = 0;");
20654 }
20655 isolate->RunMicrotasks();
20656 isolate->SetAutorunMicrotasks(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020657 v8::Debug::SetDebugEventListener(isolate, nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020658}
20659
20660
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020661#ifdef ENABLE_DISASSEMBLER
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020662static int probes_counter = 0;
20663static int misses_counter = 0;
20664static int updates_counter = 0;
20665
20666
20667static int* LookupCounter(const char* name) {
20668 if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
20669 return &probes_counter;
20670 } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
20671 return &misses_counter;
20672 } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
20673 return &updates_counter;
20674 }
20675 return NULL;
20676}
20677
20678
20679static const char* kMegamorphicTestProgram =
20680 "function ClassA() { };"
20681 "function ClassB() { };"
20682 "ClassA.prototype.foo = function() { };"
20683 "ClassB.prototype.foo = function() { };"
20684 "function fooify(obj) { obj.foo(); };"
20685 "var a = new ClassA();"
20686 "var b = new ClassB();"
20687 "for (var i = 0; i < 10000; i++) {"
20688 " fooify(a);"
20689 " fooify(b);"
20690 "}";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020691#endif
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020692
20693
20694static void StubCacheHelper(bool primary) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020695#ifdef ENABLE_DISASSEMBLER
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020696 i::FLAG_native_code_counters = true;
20697 if (primary) {
20698 i::FLAG_test_primary_stub_cache = true;
20699 } else {
20700 i::FLAG_test_secondary_stub_cache = true;
20701 }
20702 i::FLAG_crankshaft = false;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020703 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020704 env->GetIsolate()->SetCounterFunction(LookupCounter);
20705 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020706 int initial_probes = probes_counter;
20707 int initial_misses = misses_counter;
20708 int initial_updates = updates_counter;
20709 CompileRun(kMegamorphicTestProgram);
20710 int probes = probes_counter - initial_probes;
20711 int misses = misses_counter - initial_misses;
20712 int updates = updates_counter - initial_updates;
20713 CHECK_LT(updates, 10);
20714 CHECK_LT(misses, 10);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020715 // TODO(verwaest): Update this test to overflow the degree of polymorphism
20716 // before megamorphism. The number of probes will only work once we teach the
20717 // serializer to embed references to counters in the stubs, given that the
20718 // megamorphic_stub_cache_probes is updated in a snapshot-generated stub.
20719 CHECK_GE(probes, 0);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020720#endif
20721}
20722
20723
20724TEST(SecondaryStubCache) {
20725 StubCacheHelper(true);
20726}
20727
20728
20729TEST(PrimaryStubCache) {
20730 StubCacheHelper(false);
20731}
20732
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020733
20734#ifdef DEBUG
20735static int cow_arrays_created_runtime = 0;
20736
20737
20738static int* LookupCounterCOWArrays(const char* name) {
20739 if (strcmp(name, "c:V8.COWArraysCreatedRuntime") == 0) {
20740 return &cow_arrays_created_runtime;
20741 }
20742 return NULL;
20743}
20744#endif
20745
20746
20747TEST(CheckCOWArraysCreatedRuntimeCounter) {
20748#ifdef DEBUG
20749 i::FLAG_native_code_counters = true;
20750 LocalContext env;
20751 env->GetIsolate()->SetCounterFunction(LookupCounterCOWArrays);
20752 v8::HandleScope scope(env->GetIsolate());
20753 int initial_cow_arrays = cow_arrays_created_runtime;
20754 CompileRun("var o = [1, 2, 3];");
20755 CHECK_EQ(1, cow_arrays_created_runtime - initial_cow_arrays);
20756 CompileRun("var o = {foo: [4, 5, 6], bar: [3, 0]};");
20757 CHECK_EQ(3, cow_arrays_created_runtime - initial_cow_arrays);
20758 CompileRun("var o = {foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'};");
20759 CHECK_EQ(4, cow_arrays_created_runtime - initial_cow_arrays);
20760#endif
20761}
20762
20763
20764TEST(StaticGetters) {
20765 LocalContext context;
20766 i::Factory* factory = CcTest::i_isolate()->factory();
20767 v8::Isolate* isolate = CcTest::isolate();
20768 v8::HandleScope scope(isolate);
20769 i::Handle<i::Object> undefined_value = factory->undefined_value();
20770 CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
20771 i::Handle<i::Object> null_value = factory->null_value();
20772 CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
20773 i::Handle<i::Object> true_value = factory->true_value();
20774 CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
20775 i::Handle<i::Object> false_value = factory->false_value();
20776 CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
20777}
20778
20779
20780UNINITIALIZED_TEST(IsolateEmbedderData) {
20781 CcTest::DisableAutomaticDispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020782 v8::Isolate::CreateParams create_params;
20783 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
20784 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020785 isolate->Enter();
20786 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
20787 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020788 CHECK(!isolate->GetData(slot));
20789 CHECK(!i_isolate->GetData(slot));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020790 }
20791 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20792 void* data = reinterpret_cast<void*>(0xacce55ed + slot);
20793 isolate->SetData(slot, data);
20794 }
20795 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20796 void* data = reinterpret_cast<void*>(0xacce55ed + slot);
20797 CHECK_EQ(data, isolate->GetData(slot));
20798 CHECK_EQ(data, i_isolate->GetData(slot));
20799 }
20800 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20801 void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
20802 isolate->SetData(slot, data);
20803 }
20804 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20805 void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
20806 CHECK_EQ(data, isolate->GetData(slot));
20807 CHECK_EQ(data, i_isolate->GetData(slot));
20808 }
20809 isolate->Exit();
20810 isolate->Dispose();
20811}
20812
20813
20814TEST(StringEmpty) {
20815 LocalContext context;
20816 i::Factory* factory = CcTest::i_isolate()->factory();
20817 v8::Isolate* isolate = CcTest::isolate();
20818 v8::HandleScope scope(isolate);
20819 i::Handle<i::Object> empty_string = factory->empty_string();
20820 CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
20821}
20822
20823
20824static int instance_checked_getter_count = 0;
20825static void InstanceCheckedGetter(
20826 Local<String> name,
20827 const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020828 CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
20829 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020830 instance_checked_getter_count++;
20831 info.GetReturnValue().Set(v8_num(11));
20832}
20833
20834
20835static int instance_checked_setter_count = 0;
20836static void InstanceCheckedSetter(Local<String> name,
20837 Local<Value> value,
20838 const v8::PropertyCallbackInfo<void>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020839 CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
20840 .FromJust());
20841 CHECK(value->Equals(info.GetIsolate()->GetCurrentContext(), v8_num(23))
20842 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020843 instance_checked_setter_count++;
20844}
20845
20846
20847static void CheckInstanceCheckedResult(int getters, int setters,
20848 bool expects_callbacks,
20849 TryCatch* try_catch) {
20850 if (expects_callbacks) {
20851 CHECK(!try_catch->HasCaught());
20852 CHECK_EQ(getters, instance_checked_getter_count);
20853 CHECK_EQ(setters, instance_checked_setter_count);
20854 } else {
20855 CHECK(try_catch->HasCaught());
20856 CHECK_EQ(0, instance_checked_getter_count);
20857 CHECK_EQ(0, instance_checked_setter_count);
20858 }
20859 try_catch->Reset();
20860}
20861
20862
20863static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
20864 instance_checked_getter_count = 0;
20865 instance_checked_setter_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020866 TryCatch try_catch(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020867
20868 // Test path through generic runtime code.
20869 CompileRun("obj.foo");
20870 CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
20871 CompileRun("obj.foo = 23");
20872 CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
20873
20874 // Test path through generated LoadIC and StoredIC.
20875 CompileRun("function test_get(o) { o.foo; }"
20876 "test_get(obj);");
20877 CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
20878 CompileRun("test_get(obj);");
20879 CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
20880 CompileRun("test_get(obj);");
20881 CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
20882 CompileRun("function test_set(o) { o.foo = 23; }"
20883 "test_set(obj);");
20884 CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
20885 CompileRun("test_set(obj);");
20886 CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
20887 CompileRun("test_set(obj);");
20888 CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
20889
20890 // Test path through optimized code.
20891 CompileRun("%OptimizeFunctionOnNextCall(test_get);"
20892 "test_get(obj);");
20893 CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
20894 CompileRun("%OptimizeFunctionOnNextCall(test_set);"
20895 "test_set(obj);");
20896 CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
20897
20898 // Cleanup so that closures start out fresh in next check.
20899 CompileRun("%DeoptimizeFunction(test_get);"
20900 "%ClearFunctionTypeFeedback(test_get);"
20901 "%DeoptimizeFunction(test_set);"
20902 "%ClearFunctionTypeFeedback(test_set);");
20903}
20904
20905
20906THREADED_TEST(InstanceCheckOnInstanceAccessor) {
20907 v8::internal::FLAG_allow_natives_syntax = true;
20908 LocalContext context;
20909 v8::HandleScope scope(context->GetIsolate());
20910
20911 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
20912 Local<ObjectTemplate> inst = templ->InstanceTemplate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020913 inst->SetAccessor(v8_str("foo"), InstanceCheckedGetter, InstanceCheckedSetter,
20914 Local<Value>(), v8::DEFAULT, v8::None,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020915 v8::AccessorSignature::New(context->GetIsolate(), templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020916 CHECK(context->Global()
20917 ->Set(context.local(), v8_str("f"),
20918 templ->GetFunction(context.local()).ToLocalChecked())
20919 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020920
20921 printf("Testing positive ...\n");
20922 CompileRun("var obj = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020923 CHECK(templ->HasInstance(
20924 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020925 CheckInstanceCheckedAccessors(true);
20926
20927 printf("Testing negative ...\n");
20928 CompileRun("var obj = {};"
20929 "obj.__proto__ = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020930 CHECK(!templ->HasInstance(
20931 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020932 CheckInstanceCheckedAccessors(false);
20933}
20934
20935
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020936static void EmptyInterceptorGetter(
20937 Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {}
20938
20939
20940static void EmptyInterceptorSetter(
20941 Local<String> name, Local<Value> value,
20942 const v8::PropertyCallbackInfo<v8::Value>& info) {}
20943
20944
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020945THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
20946 v8::internal::FLAG_allow_natives_syntax = true;
20947 LocalContext context;
20948 v8::HandleScope scope(context->GetIsolate());
20949
20950 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
20951 Local<ObjectTemplate> inst = templ->InstanceTemplate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020952 templ->InstanceTemplate()->SetNamedPropertyHandler(EmptyInterceptorGetter,
20953 EmptyInterceptorSetter);
20954 inst->SetAccessor(v8_str("foo"), InstanceCheckedGetter, InstanceCheckedSetter,
20955 Local<Value>(), v8::DEFAULT, v8::None,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020956 v8::AccessorSignature::New(context->GetIsolate(), templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020957 CHECK(context->Global()
20958 ->Set(context.local(), v8_str("f"),
20959 templ->GetFunction(context.local()).ToLocalChecked())
20960 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020961
20962 printf("Testing positive ...\n");
20963 CompileRun("var obj = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020964 CHECK(templ->HasInstance(
20965 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020966 CheckInstanceCheckedAccessors(true);
20967
20968 printf("Testing negative ...\n");
20969 CompileRun("var obj = {};"
20970 "obj.__proto__ = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020971 CHECK(!templ->HasInstance(
20972 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020973 CheckInstanceCheckedAccessors(false);
20974}
20975
20976
20977THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
20978 v8::internal::FLAG_allow_natives_syntax = true;
20979 LocalContext context;
20980 v8::HandleScope scope(context->GetIsolate());
20981
20982 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
20983 Local<ObjectTemplate> proto = templ->PrototypeTemplate();
20984 proto->SetAccessor(v8_str("foo"), InstanceCheckedGetter,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020985 InstanceCheckedSetter, Local<Value>(), v8::DEFAULT,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020986 v8::None,
20987 v8::AccessorSignature::New(context->GetIsolate(), templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020988 CHECK(context->Global()
20989 ->Set(context.local(), v8_str("f"),
20990 templ->GetFunction(context.local()).ToLocalChecked())
20991 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020992
20993 printf("Testing positive ...\n");
20994 CompileRun("var obj = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020995 CHECK(templ->HasInstance(
20996 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020997 CheckInstanceCheckedAccessors(true);
20998
20999 printf("Testing negative ...\n");
21000 CompileRun("var obj = {};"
21001 "obj.__proto__ = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021002 CHECK(!templ->HasInstance(
21003 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021004 CheckInstanceCheckedAccessors(false);
21005
21006 printf("Testing positive with modified prototype chain ...\n");
21007 CompileRun("var obj = new f();"
21008 "var pro = {};"
21009 "pro.__proto__ = obj.__proto__;"
21010 "obj.__proto__ = pro;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021011 CHECK(templ->HasInstance(
21012 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021013 CheckInstanceCheckedAccessors(true);
21014}
21015
21016
21017TEST(TryFinallyMessage) {
21018 LocalContext context;
21019 v8::HandleScope scope(context->GetIsolate());
21020 {
21021 // Test that the original error message is not lost if there is a
21022 // recursive call into Javascript is done in the finally block, e.g. to
21023 // initialize an IC. (crbug.com/129171)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021024 TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021025 const char* trigger_ic =
21026 "try { \n"
21027 " throw new Error('test'); \n"
21028 "} finally { \n"
21029 " var x = 0; \n"
21030 " x++; \n" // Trigger an IC initialization here.
21031 "} \n";
21032 CompileRun(trigger_ic);
21033 CHECK(try_catch.HasCaught());
21034 Local<Message> message = try_catch.Message();
21035 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021036 CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021037 }
21038
21039 {
21040 // Test that the original exception message is indeed overwritten if
21041 // a new error is thrown in the finally block.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021042 TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021043 const char* throw_again =
21044 "try { \n"
21045 " throw new Error('test'); \n"
21046 "} finally { \n"
21047 " var x = 0; \n"
21048 " x++; \n"
21049 " throw new Error('again'); \n" // This is the new uncaught error.
21050 "} \n";
21051 CompileRun(throw_again);
21052 CHECK(try_catch.HasCaught());
21053 Local<Message> message = try_catch.Message();
21054 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021055 CHECK_EQ(6, message->GetLineNumber(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021056 }
21057}
21058
21059
21060static void Helper137002(bool do_store,
21061 bool polymorphic,
21062 bool remove_accessor,
21063 bool interceptor) {
21064 LocalContext context;
21065 Local<ObjectTemplate> templ = ObjectTemplate::New(context->GetIsolate());
21066 if (interceptor) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040021067 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(FooGetInterceptor,
21068 FooSetInterceptor));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021069 } else {
21070 templ->SetAccessor(v8_str("foo"),
21071 GetterWhichReturns42,
21072 SetterWhichSetsYOnThisTo23);
21073 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021074 CHECK(context->Global()
21075 ->Set(context.local(), v8_str("obj"),
21076 templ->NewInstance(context.local()).ToLocalChecked())
21077 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021078
21079 // Turn monomorphic on slow object with native accessor, then turn
21080 // polymorphic, finally optimize to create negative lookup and fail.
21081 CompileRun(do_store ?
21082 "function f(x) { x.foo = void 0; }" :
21083 "function f(x) { return x.foo; }");
21084 CompileRun("obj.y = void 0;");
21085 if (!interceptor) {
21086 CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
21087 }
21088 CompileRun("obj.__proto__ = null;"
21089 "f(obj); f(obj); f(obj);");
21090 if (polymorphic) {
21091 CompileRun("f({});");
21092 }
21093 CompileRun("obj.y = void 0;"
21094 "%OptimizeFunctionOnNextCall(f);");
21095 if (remove_accessor) {
21096 CompileRun("delete obj.foo;");
21097 }
21098 CompileRun("var result = f(obj);");
21099 if (do_store) {
21100 CompileRun("result = obj.y;");
21101 }
21102 if (remove_accessor && !interceptor) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021103 CHECK(context->Global()
21104 ->Get(context.local(), v8_str("result"))
21105 .ToLocalChecked()
21106 ->IsUndefined());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021107 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021108 CHECK_EQ(do_store ? 23 : 42, context->Global()
21109 ->Get(context.local(), v8_str("result"))
21110 .ToLocalChecked()
21111 ->Int32Value(context.local())
21112 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021113 }
21114}
21115
21116
21117THREADED_TEST(Regress137002a) {
21118 i::FLAG_allow_natives_syntax = true;
21119 i::FLAG_compilation_cache = false;
21120 v8::HandleScope scope(CcTest::isolate());
21121 for (int i = 0; i < 16; i++) {
21122 Helper137002(i & 8, i & 4, i & 2, i & 1);
21123 }
21124}
21125
21126
21127THREADED_TEST(Regress137002b) {
21128 i::FLAG_allow_natives_syntax = true;
21129 LocalContext context;
21130 v8::Isolate* isolate = context->GetIsolate();
21131 v8::HandleScope scope(isolate);
21132 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
21133 templ->SetAccessor(v8_str("foo"),
21134 GetterWhichReturns42,
21135 SetterWhichSetsYOnThisTo23);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021136 CHECK(context->Global()
21137 ->Set(context.local(), v8_str("obj"),
21138 templ->NewInstance(context.local()).ToLocalChecked())
21139 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021140
21141 // Turn monomorphic on slow object with native accessor, then just
21142 // delete the property and fail.
21143 CompileRun("function load(x) { return x.foo; }"
21144 "function store(x) { x.foo = void 0; }"
21145 "function keyed_load(x, key) { return x[key]; }"
21146 // Second version of function has a different source (add void 0)
21147 // so that it does not share code with the first version. This
21148 // ensures that the ICs are monomorphic.
21149 "function load2(x) { void 0; return x.foo; }"
21150 "function store2(x) { void 0; x.foo = void 0; }"
21151 "function keyed_load2(x, key) { void 0; return x[key]; }"
21152
21153 "obj.y = void 0;"
21154 "obj.__proto__ = null;"
21155 "var subobj = {};"
21156 "subobj.y = void 0;"
21157 "subobj.__proto__ = obj;"
21158 "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
21159
21160 // Make the ICs monomorphic.
21161 "load(obj); load(obj);"
21162 "load2(subobj); load2(subobj);"
21163 "store(obj); store(obj);"
21164 "store2(subobj); store2(subobj);"
21165 "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
21166 "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
21167
21168 // Actually test the shiny new ICs and better not crash. This
21169 // serves as a regression test for issue 142088 as well.
21170 "load(obj);"
21171 "load2(subobj);"
21172 "store(obj);"
21173 "store2(subobj);"
21174 "keyed_load(obj, 'foo');"
21175 "keyed_load2(subobj, 'foo');"
21176
21177 // Delete the accessor. It better not be called any more now.
21178 "delete obj.foo;"
21179 "obj.y = void 0;"
21180 "subobj.y = void 0;"
21181
21182 "var load_result = load(obj);"
21183 "var load_result2 = load2(subobj);"
21184 "var keyed_load_result = keyed_load(obj, 'foo');"
21185 "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
21186 "store(obj);"
21187 "store2(subobj);"
21188 "var y_from_obj = obj.y;"
21189 "var y_from_subobj = subobj.y;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021190 CHECK(context->Global()
21191 ->Get(context.local(), v8_str("load_result"))
21192 .ToLocalChecked()
21193 ->IsUndefined());
21194 CHECK(context->Global()
21195 ->Get(context.local(), v8_str("load_result2"))
21196 .ToLocalChecked()
21197 ->IsUndefined());
21198 CHECK(context->Global()
21199 ->Get(context.local(), v8_str("keyed_load_result"))
21200 .ToLocalChecked()
21201 ->IsUndefined());
21202 CHECK(context->Global()
21203 ->Get(context.local(), v8_str("keyed_load_result2"))
21204 .ToLocalChecked()
21205 ->IsUndefined());
21206 CHECK(context->Global()
21207 ->Get(context.local(), v8_str("y_from_obj"))
21208 .ToLocalChecked()
21209 ->IsUndefined());
21210 CHECK(context->Global()
21211 ->Get(context.local(), v8_str("y_from_subobj"))
21212 .ToLocalChecked()
21213 ->IsUndefined());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021214}
21215
21216
21217THREADED_TEST(Regress142088) {
21218 i::FLAG_allow_natives_syntax = true;
21219 LocalContext context;
21220 v8::Isolate* isolate = context->GetIsolate();
21221 v8::HandleScope scope(isolate);
21222 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
21223 templ->SetAccessor(v8_str("foo"),
21224 GetterWhichReturns42,
21225 SetterWhichSetsYOnThisTo23);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021226 CHECK(context->Global()
21227 ->Set(context.local(), v8_str("obj"),
21228 templ->NewInstance(context.local()).ToLocalChecked())
21229 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021230
21231 CompileRun("function load(x) { return x.foo; }"
21232 "var o = Object.create(obj);"
21233 "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
21234 "load(o); load(o); load(o); load(o);");
21235}
21236
21237
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021238THREADED_TEST(Regress137496) {
21239 i::FLAG_expose_gc = true;
21240 LocalContext context;
21241 v8::HandleScope scope(context->GetIsolate());
21242
21243 // Compile a try-finally clause where the finally block causes a GC
21244 // while there still is a message pending for external reporting.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021245 TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021246 try_catch.SetVerbose(true);
21247 CompileRun("try { throw new Error(); } finally { gc(); }");
21248 CHECK(try_catch.HasCaught());
21249}
21250
21251
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021252THREADED_TEST(Regress157124) {
21253 LocalContext context;
21254 v8::Isolate* isolate = context->GetIsolate();
21255 v8::HandleScope scope(isolate);
21256 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021257 Local<Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021258 obj->GetIdentityHash();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021259 obj->DeletePrivate(context.local(),
21260 v8::Private::ForApi(isolate, v8_str("Bug")))
21261 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021262}
21263
21264
21265THREADED_TEST(Regress2535) {
21266 LocalContext context;
21267 v8::HandleScope scope(context->GetIsolate());
21268 Local<Value> set_value = CompileRun("new Set();");
21269 Local<Object> set_object(Local<Object>::Cast(set_value));
21270 CHECK_EQ(0, set_object->InternalFieldCount());
21271 Local<Value> map_value = CompileRun("new Map();");
21272 Local<Object> map_object(Local<Object>::Cast(map_value));
21273 CHECK_EQ(0, map_object->InternalFieldCount());
21274}
21275
21276
21277THREADED_TEST(Regress2746) {
21278 LocalContext context;
21279 v8::Isolate* isolate = context->GetIsolate();
21280 v8::HandleScope scope(isolate);
21281 Local<Object> obj = Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021282 Local<v8::Private> key = v8::Private::New(isolate, v8_str("key"));
21283 CHECK(
21284 obj->SetPrivate(context.local(), key, v8::Undefined(isolate)).FromJust());
21285 Local<Value> value = obj->GetPrivate(context.local(), key).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021286 CHECK(!value.IsEmpty());
21287 CHECK(value->IsUndefined());
21288}
21289
21290
21291THREADED_TEST(Regress260106) {
21292 LocalContext context;
21293 v8::Isolate* isolate = context->GetIsolate();
21294 v8::HandleScope scope(isolate);
21295 Local<FunctionTemplate> templ = FunctionTemplate::New(isolate,
21296 DummyCallHandler);
21297 CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021298 Local<Function> function =
21299 templ->GetFunction(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021300 CHECK(!function.IsEmpty());
21301 CHECK(function->IsFunction());
21302}
21303
21304
21305THREADED_TEST(JSONParseObject) {
21306 LocalContext context;
21307 HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021308 Local<Value> obj =
21309 v8::JSON::Parse(context->GetIsolate(), v8_str("{\"x\":42}"))
21310 .ToLocalChecked();
21311 Local<Object> global = context->Global();
21312 global->Set(context.local(), v8_str("obj"), obj).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021313 ExpectString("JSON.stringify(obj)", "{\"x\":42}");
21314}
21315
21316
21317THREADED_TEST(JSONParseNumber) {
21318 LocalContext context;
21319 HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021320 Local<Value> obj =
21321 v8::JSON::Parse(context->GetIsolate(), v8_str("42")).ToLocalChecked();
21322 Local<Object> global = context->Global();
21323 global->Set(context.local(), v8_str("obj"), obj).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021324 ExpectString("JSON.stringify(obj)", "42");
21325}
21326
21327
21328#if V8_OS_POSIX && !V8_OS_NACL
21329class ThreadInterruptTest {
21330 public:
21331 ThreadInterruptTest() : sem_(0), sem_value_(0) { }
21332 ~ThreadInterruptTest() {}
21333
21334 void RunTest() {
21335 InterruptThread i_thread(this);
21336 i_thread.Start();
21337
21338 sem_.Wait();
21339 CHECK_EQ(kExpectedValue, sem_value_);
21340 }
21341
21342 private:
21343 static const int kExpectedValue = 1;
21344
21345 class InterruptThread : public v8::base::Thread {
21346 public:
21347 explicit InterruptThread(ThreadInterruptTest* test)
21348 : Thread(Options("InterruptThread")), test_(test) {}
21349
21350 virtual void Run() {
21351 struct sigaction action;
21352
21353 // Ensure that we'll enter waiting condition
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021354 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021355
21356 // Setup signal handler
21357 memset(&action, 0, sizeof(action));
21358 action.sa_handler = SignalHandler;
21359 sigaction(SIGCHLD, &action, NULL);
21360
21361 // Send signal
21362 kill(getpid(), SIGCHLD);
21363
21364 // Ensure that if wait has returned because of error
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021365 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021366
21367 // Set value and signal semaphore
21368 test_->sem_value_ = 1;
21369 test_->sem_.Signal();
21370 }
21371
21372 static void SignalHandler(int signal) {
21373 }
21374
21375 private:
21376 ThreadInterruptTest* test_;
21377 };
21378
21379 v8::base::Semaphore sem_;
21380 volatile int sem_value_;
21381};
21382
21383
21384THREADED_TEST(SemaphoreInterruption) {
21385 ThreadInterruptTest().RunTest();
21386}
21387
21388
21389#endif // V8_OS_POSIX
21390
21391
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021392void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
21393 CHECK(false);
21394}
21395
21396
21397TEST(JSONStringifyAccessCheck) {
21398 v8::V8::Initialize();
21399 v8::Isolate* isolate = CcTest::isolate();
21400 v8::HandleScope scope(isolate);
21401
21402 // Create an ObjectTemplate for global objects and install access
21403 // check callbacks that will block access.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021404 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021405 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021406 global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021407
21408 // Create a context and set an x property on it's global object.
21409 LocalContext context0(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021410 v8::Local<v8::Object> global0 = context0->Global();
21411 global0->Set(context0.local(), v8_str("x"), v8_num(42)).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021412 ExpectString("JSON.stringify(this)", "{\"x\":42}");
21413
21414 for (int i = 0; i < 2; i++) {
21415 if (i == 1) {
21416 // Install a toJSON function on the second run.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021417 v8::Local<v8::FunctionTemplate> toJSON =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021418 v8::FunctionTemplate::New(isolate, UnreachableCallback);
21419
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021420 global0->Set(context0.local(), v8_str("toJSON"),
21421 toJSON->GetFunction(context0.local()).ToLocalChecked())
21422 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021423 }
21424 // Create a context with a different security token so that the
21425 // failed access check callback will be called on each access.
21426 LocalContext context1(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021427 CHECK(context1->Global()
21428 ->Set(context1.local(), v8_str("other"), global0)
21429 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021430
21431 CHECK(CompileRun("JSON.stringify(other)").IsEmpty());
21432 CHECK(CompileRun("JSON.stringify({ 'a' : other, 'b' : ['c'] })").IsEmpty());
21433 CHECK(CompileRun("JSON.stringify([other, 'b', 'c'])").IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021434 }
21435}
21436
21437
21438bool access_check_fail_thrown = false;
21439bool catch_callback_called = false;
21440
21441
21442// Failed access check callback that performs a GC on each invocation.
21443void FailedAccessCheckThrows(Local<v8::Object> target,
21444 v8::AccessType type,
21445 Local<v8::Value> data) {
21446 access_check_fail_thrown = true;
21447 i::PrintF("Access check failed. Error thrown.\n");
21448 CcTest::isolate()->ThrowException(
21449 v8::Exception::Error(v8_str("cross context")));
21450}
21451
21452
21453void CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
21454 for (int i = 0; i < args.Length(); i++) {
21455 i::PrintF("%s\n", *String::Utf8Value(args[i]));
21456 }
21457 catch_callback_called = true;
21458}
21459
21460
21461void HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021462 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
21463 CHECK(
21464 args[0]
21465 ->ToObject(context)
21466 .ToLocalChecked()
21467 ->HasOwnProperty(context, args[1]->ToString(context).ToLocalChecked())
21468 .IsNothing());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021469}
21470
21471
21472void CheckCorrectThrow(const char* script) {
21473 // Test that the script, when wrapped into a try-catch, triggers the catch
21474 // clause due to failed access check throwing an exception.
21475 // The subsequent try-catch should run without any exception.
21476 access_check_fail_thrown = false;
21477 catch_callback_called = false;
21478 i::ScopedVector<char> source(1024);
21479 i::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
21480 CompileRun(source.start());
21481 CHECK(access_check_fail_thrown);
21482 CHECK(catch_callback_called);
21483
21484 access_check_fail_thrown = false;
21485 catch_callback_called = false;
21486 CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
21487 CHECK(!access_check_fail_thrown);
21488 CHECK(!catch_callback_called);
21489}
21490
21491
21492TEST(AccessCheckThrows) {
21493 i::FLAG_allow_natives_syntax = true;
21494 v8::V8::Initialize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021495 v8::Isolate* isolate = CcTest::isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021496 isolate->SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021497 v8::HandleScope scope(isolate);
21498
21499 // Create an ObjectTemplate for global objects and install access
21500 // check callbacks that will block access.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021501 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021502 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021503 global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021504
21505 // Create a context and set an x property on it's global object.
21506 LocalContext context0(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021507 v8::Local<v8::Object> global0 = context0->Global();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021508
21509 // Create a context with a different security token so that the
21510 // failed access check callback will be called on each access.
21511 LocalContext context1(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021512 CHECK(context1->Global()
21513 ->Set(context1.local(), v8_str("other"), global0)
21514 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021515
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021516 v8::Local<v8::FunctionTemplate> catcher_fun =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021517 v8::FunctionTemplate::New(isolate, CatcherCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021518 CHECK(context1->Global()
21519 ->Set(context1.local(), v8_str("catcher"),
21520 catcher_fun->GetFunction(context1.local()).ToLocalChecked())
21521 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021522
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021523 v8::Local<v8::FunctionTemplate> has_own_property_fun =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021524 v8::FunctionTemplate::New(isolate, HasOwnPropertyCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021525 CHECK(context1->Global()
21526 ->Set(context1.local(), v8_str("has_own_property"),
21527 has_own_property_fun->GetFunction(context1.local())
21528 .ToLocalChecked())
21529 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021530
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021531 {
21532 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021533 access_check_fail_thrown = false;
21534 CompileRun("other.x;");
21535 CHECK(access_check_fail_thrown);
21536 CHECK(try_catch.HasCaught());
21537 }
21538
21539 CheckCorrectThrow("other.x");
21540 CheckCorrectThrow("other[1]");
21541 CheckCorrectThrow("JSON.stringify(other)");
21542 CheckCorrectThrow("has_own_property(other, 'x')");
21543 CheckCorrectThrow("%GetProperty(other, 'x')");
21544 CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 0)");
21545 CheckCorrectThrow("%AddNamedProperty(other, 'x', 'foo', 1)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021546 CheckCorrectThrow("%DeleteProperty_Sloppy(other, 'x')");
21547 CheckCorrectThrow("%DeleteProperty_Strict(other, 'x')");
21548 CheckCorrectThrow("%DeleteProperty_Sloppy(other, '1')");
21549 CheckCorrectThrow("%DeleteProperty_Strict(other, '1')");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021550 CheckCorrectThrow("%HasOwnProperty(other, 'x')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021551 CheckCorrectThrow("%HasProperty('x', other)");
21552 CheckCorrectThrow("%PropertyIsEnumerable(other, 'x')");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021553 // PROPERTY_ATTRIBUTES_NONE = 0
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021554 CheckCorrectThrow("%DefineAccessorPropertyUnchecked("
21555 "other, 'x', null, null, 1)");
21556
21557 // Reset the failed access check callback so it does not influence
21558 // the other tests.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021559 isolate->SetFailedAccessCheckCallbackFunction(NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021560}
21561
21562
21563class RequestInterruptTestBase {
21564 public:
21565 RequestInterruptTestBase()
21566 : env_(),
21567 isolate_(env_->GetIsolate()),
21568 sem_(0),
21569 warmup_(20000),
21570 should_continue_(true) {
21571 }
21572
21573 virtual ~RequestInterruptTestBase() { }
21574
21575 virtual void StartInterruptThread() = 0;
21576
21577 virtual void TestBody() = 0;
21578
21579 void RunTest() {
21580 StartInterruptThread();
21581
21582 v8::HandleScope handle_scope(isolate_);
21583
21584 TestBody();
21585
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021586 // Verify we arrived here because interruptor was called
21587 // not due to a bug causing us to exit the loop too early.
21588 CHECK(!should_continue());
21589 }
21590
21591 void WakeUpInterruptor() {
21592 sem_.Signal();
21593 }
21594
21595 bool should_continue() const { return should_continue_; }
21596
21597 bool ShouldContinue() {
21598 if (warmup_ > 0) {
21599 if (--warmup_ == 0) {
21600 WakeUpInterruptor();
21601 }
21602 }
21603
21604 return should_continue_;
21605 }
21606
21607 static void ShouldContinueCallback(
21608 const v8::FunctionCallbackInfo<Value>& info) {
21609 RequestInterruptTestBase* test =
21610 reinterpret_cast<RequestInterruptTestBase*>(
21611 info.Data().As<v8::External>()->Value());
21612 info.GetReturnValue().Set(test->ShouldContinue());
21613 }
21614
21615 LocalContext env_;
21616 v8::Isolate* isolate_;
21617 v8::base::Semaphore sem_;
21618 int warmup_;
21619 bool should_continue_;
21620};
21621
21622
21623class RequestInterruptTestBaseWithSimpleInterrupt
21624 : public RequestInterruptTestBase {
21625 public:
21626 RequestInterruptTestBaseWithSimpleInterrupt() : i_thread(this) { }
21627
21628 virtual void StartInterruptThread() {
21629 i_thread.Start();
21630 }
21631
21632 private:
21633 class InterruptThread : public v8::base::Thread {
21634 public:
21635 explicit InterruptThread(RequestInterruptTestBase* test)
21636 : Thread(Options("RequestInterruptTest")), test_(test) {}
21637
21638 virtual void Run() {
21639 test_->sem_.Wait();
21640 test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
21641 }
21642
21643 static void OnInterrupt(v8::Isolate* isolate, void* data) {
21644 reinterpret_cast<RequestInterruptTestBase*>(data)->
21645 should_continue_ = false;
21646 }
21647
21648 private:
21649 RequestInterruptTestBase* test_;
21650 };
21651
21652 InterruptThread i_thread;
21653};
21654
21655
21656class RequestInterruptTestWithFunctionCall
21657 : public RequestInterruptTestBaseWithSimpleInterrupt {
21658 public:
21659 virtual void TestBody() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021660 Local<Function> func = Function::New(env_.local(), ShouldContinueCallback,
21661 v8::External::New(isolate_, this))
21662 .ToLocalChecked();
21663 CHECK(env_->Global()
21664 ->Set(env_.local(), v8_str("ShouldContinue"), func)
21665 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021666
21667 CompileRun("while (ShouldContinue()) { }");
21668 }
21669};
21670
21671
21672class RequestInterruptTestWithMethodCall
21673 : public RequestInterruptTestBaseWithSimpleInterrupt {
21674 public:
21675 virtual void TestBody() {
21676 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
21677 v8::Local<v8::Template> proto = t->PrototypeTemplate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021678 proto->Set(v8_str("shouldContinue"),
21679 Function::New(env_.local(), ShouldContinueCallback,
21680 v8::External::New(isolate_, this))
21681 .ToLocalChecked());
21682 CHECK(env_->Global()
21683 ->Set(env_.local(), v8_str("Klass"),
21684 t->GetFunction(env_.local()).ToLocalChecked())
21685 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021686
21687 CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
21688 }
21689};
21690
21691
21692class RequestInterruptTestWithAccessor
21693 : public RequestInterruptTestBaseWithSimpleInterrupt {
21694 public:
21695 virtual void TestBody() {
21696 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
21697 v8::Local<v8::Template> proto = t->PrototypeTemplate();
21698 proto->SetAccessorProperty(v8_str("shouldContinue"), FunctionTemplate::New(
21699 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021700 CHECK(env_->Global()
21701 ->Set(env_.local(), v8_str("Klass"),
21702 t->GetFunction(env_.local()).ToLocalChecked())
21703 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021704
21705 CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
21706 }
21707};
21708
21709
21710class RequestInterruptTestWithNativeAccessor
21711 : public RequestInterruptTestBaseWithSimpleInterrupt {
21712 public:
21713 virtual void TestBody() {
21714 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
21715 t->InstanceTemplate()->SetNativeDataProperty(
21716 v8_str("shouldContinue"),
21717 &ShouldContinueNativeGetter,
21718 NULL,
21719 v8::External::New(isolate_, this));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021720 CHECK(env_->Global()
21721 ->Set(env_.local(), v8_str("Klass"),
21722 t->GetFunction(env_.local()).ToLocalChecked())
21723 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021724
21725 CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
21726 }
21727
21728 private:
21729 static void ShouldContinueNativeGetter(
21730 Local<String> property,
21731 const v8::PropertyCallbackInfo<v8::Value>& info) {
21732 RequestInterruptTestBase* test =
21733 reinterpret_cast<RequestInterruptTestBase*>(
21734 info.Data().As<v8::External>()->Value());
21735 info.GetReturnValue().Set(test->ShouldContinue());
21736 }
21737};
21738
21739
21740class RequestInterruptTestWithMethodCallAndInterceptor
21741 : public RequestInterruptTestBaseWithSimpleInterrupt {
21742 public:
21743 virtual void TestBody() {
21744 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
21745 v8::Local<v8::Template> proto = t->PrototypeTemplate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021746 proto->Set(v8_str("shouldContinue"),
21747 Function::New(env_.local(), ShouldContinueCallback,
21748 v8::External::New(isolate_, this))
21749 .ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021750 v8::Local<v8::ObjectTemplate> instance_template = t->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040021751 instance_template->SetHandler(
21752 v8::NamedPropertyHandlerConfiguration(EmptyInterceptor));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021753
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021754 CHECK(env_->Global()
21755 ->Set(env_.local(), v8_str("Klass"),
21756 t->GetFunction(env_.local()).ToLocalChecked())
21757 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021758
21759 CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
21760 }
21761
21762 private:
21763 static void EmptyInterceptor(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040021764 Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021765};
21766
21767
21768class RequestInterruptTestWithMathAbs
21769 : public RequestInterruptTestBaseWithSimpleInterrupt {
21770 public:
21771 virtual void TestBody() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021772 env_->Global()
21773 ->Set(env_.local(), v8_str("WakeUpInterruptor"),
21774 Function::New(env_.local(), WakeUpInterruptorCallback,
21775 v8::External::New(isolate_, this))
21776 .ToLocalChecked())
21777 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021778
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021779 env_->Global()
21780 ->Set(env_.local(), v8_str("ShouldContinue"),
21781 Function::New(env_.local(), ShouldContinueCallback,
21782 v8::External::New(isolate_, this))
21783 .ToLocalChecked())
21784 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021785
21786 i::FLAG_allow_natives_syntax = true;
21787 CompileRun("function loopish(o) {"
21788 " var pre = 10;"
21789 " while (o.abs(1) > 0) {"
21790 " if (o.abs(1) >= 0 && !ShouldContinue()) break;"
21791 " if (pre > 0) {"
21792 " if (--pre === 0) WakeUpInterruptor(o === Math);"
21793 " }"
21794 " }"
21795 "}"
21796 "var i = 50;"
21797 "var obj = {abs: function () { return i-- }, x: null};"
21798 "delete obj.x;"
21799 "loopish(obj);"
21800 "%OptimizeFunctionOnNextCall(loopish);"
21801 "loopish(Math);");
21802
21803 i::FLAG_allow_natives_syntax = false;
21804 }
21805
21806 private:
21807 static void WakeUpInterruptorCallback(
21808 const v8::FunctionCallbackInfo<Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021809 if (!info[0]
21810 ->BooleanValue(info.GetIsolate()->GetCurrentContext())
21811 .FromJust()) {
21812 return;
21813 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021814
21815 RequestInterruptTestBase* test =
21816 reinterpret_cast<RequestInterruptTestBase*>(
21817 info.Data().As<v8::External>()->Value());
21818 test->WakeUpInterruptor();
21819 }
21820
21821 static void ShouldContinueCallback(
21822 const v8::FunctionCallbackInfo<Value>& info) {
21823 RequestInterruptTestBase* test =
21824 reinterpret_cast<RequestInterruptTestBase*>(
21825 info.Data().As<v8::External>()->Value());
21826 info.GetReturnValue().Set(test->should_continue());
21827 }
21828};
21829
21830
21831TEST(RequestInterruptTestWithFunctionCall) {
21832 RequestInterruptTestWithFunctionCall().RunTest();
21833}
21834
21835
21836TEST(RequestInterruptTestWithMethodCall) {
21837 RequestInterruptTestWithMethodCall().RunTest();
21838}
21839
21840
21841TEST(RequestInterruptTestWithAccessor) {
21842 RequestInterruptTestWithAccessor().RunTest();
21843}
21844
21845
21846TEST(RequestInterruptTestWithNativeAccessor) {
21847 RequestInterruptTestWithNativeAccessor().RunTest();
21848}
21849
21850
21851TEST(RequestInterruptTestWithMethodCallAndInterceptor) {
21852 RequestInterruptTestWithMethodCallAndInterceptor().RunTest();
21853}
21854
21855
21856TEST(RequestInterruptTestWithMathAbs) {
21857 RequestInterruptTestWithMathAbs().RunTest();
21858}
21859
21860
Emily Bernierd0a1eb72015-03-24 16:35:39 -040021861class RequestMultipleInterrupts : public RequestInterruptTestBase {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021862 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -040021863 RequestMultipleInterrupts() : i_thread(this), counter_(0) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021864
21865 virtual void StartInterruptThread() {
21866 i_thread.Start();
21867 }
21868
21869 virtual void TestBody() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021870 Local<Function> func = Function::New(env_.local(), ShouldContinueCallback,
21871 v8::External::New(isolate_, this))
21872 .ToLocalChecked();
21873 CHECK(env_->Global()
21874 ->Set(env_.local(), v8_str("ShouldContinue"), func)
21875 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021876
21877 CompileRun("while (ShouldContinue()) { }");
21878 }
21879
21880 private:
21881 class InterruptThread : public v8::base::Thread {
21882 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -040021883 enum { NUM_INTERRUPTS = 10 };
21884 explicit InterruptThread(RequestMultipleInterrupts* test)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021885 : Thread(Options("RequestInterruptTest")), test_(test) {}
21886
21887 virtual void Run() {
21888 test_->sem_.Wait();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040021889 for (int i = 0; i < NUM_INTERRUPTS; i++) {
21890 test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
21891 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021892 }
21893
21894 static void OnInterrupt(v8::Isolate* isolate, void* data) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040021895 RequestMultipleInterrupts* test =
21896 reinterpret_cast<RequestMultipleInterrupts*>(data);
21897 test->should_continue_ = ++test->counter_ < NUM_INTERRUPTS;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021898 }
21899
21900 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -040021901 RequestMultipleInterrupts* test_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021902 };
21903
21904 InterruptThread i_thread;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040021905 int counter_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021906};
21907
21908
Emily Bernierd0a1eb72015-03-24 16:35:39 -040021909TEST(RequestMultipleInterrupts) { RequestMultipleInterrupts().RunTest(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021910
21911
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021912static bool interrupt_was_called = false;
21913
21914
21915void SmallScriptsInterruptCallback(v8::Isolate* isolate, void* data) {
21916 interrupt_was_called = true;
21917}
21918
21919
21920TEST(RequestInterruptSmallScripts) {
21921 LocalContext env;
21922 v8::Isolate* isolate = CcTest::isolate();
21923 v8::HandleScope scope(isolate);
21924
21925 interrupt_was_called = false;
21926 isolate->RequestInterrupt(&SmallScriptsInterruptCallback, NULL);
21927 CompileRun("(function(x){return x;})(1);");
21928 CHECK(interrupt_was_called);
21929}
21930
21931
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021932static Local<Value> function_new_expected_env;
21933static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021934 CHECK(
21935 function_new_expected_env->Equals(info.GetIsolate()->GetCurrentContext(),
21936 info.Data())
21937 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021938 info.GetReturnValue().Set(17);
21939}
21940
21941
21942THREADED_TEST(FunctionNew) {
21943 LocalContext env;
21944 v8::Isolate* isolate = env->GetIsolate();
21945 v8::HandleScope scope(isolate);
21946 Local<Object> data = v8::Object::New(isolate);
21947 function_new_expected_env = data;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021948 Local<Function> func =
21949 Function::New(env.local(), FunctionNewCallback, data).ToLocalChecked();
21950 CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021951 Local<Value> result = CompileRun("func();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021952 CHECK(v8::Integer::New(isolate, 17)->Equals(env.local(), result).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021953 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021954 // Verify function not cached
21955 auto serial_number = handle(
21956 i::Smi::cast(i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*func))
21957 ->shared()
21958 ->get_api_func_data()
21959 ->serial_number()),
21960 i_isolate);
21961 auto cache = i_isolate->function_cache();
21962 CHECK(cache->Lookup(serial_number)->IsTheHole());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021963 // Verify that each Function::New creates a new function instance
21964 Local<Object> data2 = v8::Object::New(isolate);
21965 function_new_expected_env = data2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021966 Local<Function> func2 =
21967 Function::New(env.local(), FunctionNewCallback, data2).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021968 CHECK(!func2->IsNull());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021969 CHECK(!func->Equals(env.local(), func2).FromJust());
21970 CHECK(env->Global()->Set(env.local(), v8_str("func2"), func2).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021971 Local<Value> result2 = CompileRun("func2();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021972 CHECK(v8::Integer::New(isolate, 17)->Equals(env.local(), result2).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021973}
21974
21975
21976TEST(EscapeableHandleScope) {
21977 HandleScope outer_scope(CcTest::isolate());
21978 LocalContext context;
21979 const int runs = 10;
21980 Local<String> values[runs];
21981 for (int i = 0; i < runs; i++) {
21982 v8::EscapableHandleScope inner_scope(CcTest::isolate());
21983 Local<String> value;
21984 if (i != 0) value = v8_str("escape value");
21985 values[i] = inner_scope.Escape(value);
21986 }
21987 for (int i = 0; i < runs; i++) {
21988 Local<String> expected;
21989 if (i != 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021990 CHECK(v8_str("escape value")
21991 ->Equals(context.local(), values[i])
21992 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021993 } else {
21994 CHECK(values[i].IsEmpty());
21995 }
21996 }
21997}
21998
21999
22000static void SetterWhichExpectsThisAndHolderToDiffer(
22001 Local<String>, Local<Value>, const v8::PropertyCallbackInfo<void>& info) {
22002 CHECK(info.Holder() != info.This());
22003}
22004
22005
22006TEST(Regress239669) {
22007 LocalContext context;
22008 v8::Isolate* isolate = context->GetIsolate();
22009 v8::HandleScope scope(isolate);
22010 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
22011 templ->SetAccessor(v8_str("x"), 0, SetterWhichExpectsThisAndHolderToDiffer);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022012 CHECK(context->Global()
22013 ->Set(context.local(), v8_str("P"),
22014 templ->NewInstance(context.local()).ToLocalChecked())
22015 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022016 CompileRun(
22017 "function C1() {"
22018 " this.x = 23;"
22019 "};"
22020 "C1.prototype = P;"
22021 "for (var i = 0; i < 4; i++ ) {"
22022 " new C1();"
22023 "}");
22024}
22025
22026
22027class ApiCallOptimizationChecker {
22028 private:
22029 static Local<Object> data;
22030 static Local<Object> receiver;
22031 static Local<Object> holder;
22032 static Local<Object> callee;
22033 static int count;
22034
22035 static void OptimizationCallback(
22036 const v8::FunctionCallbackInfo<v8::Value>& info) {
22037 CHECK(callee == info.Callee());
22038 CHECK(data == info.Data());
22039 CHECK(receiver == info.This());
22040 if (info.Length() == 1) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022041 CHECK(v8_num(1)
22042 ->Equals(info.GetIsolate()->GetCurrentContext(), info[0])
22043 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022044 }
22045 CHECK(holder == info.Holder());
22046 count++;
22047 info.GetReturnValue().Set(v8_str("returned"));
22048 }
22049
22050 public:
22051 enum SignatureType {
22052 kNoSignature,
22053 kSignatureOnReceiver,
22054 kSignatureOnPrototype
22055 };
22056
22057 void RunAll() {
22058 SignatureType signature_types[] =
22059 {kNoSignature, kSignatureOnReceiver, kSignatureOnPrototype};
22060 for (unsigned i = 0; i < arraysize(signature_types); i++) {
22061 SignatureType signature_type = signature_types[i];
22062 for (int j = 0; j < 2; j++) {
22063 bool global = j == 0;
22064 int key = signature_type +
22065 arraysize(signature_types) * (global ? 1 : 0);
22066 Run(signature_type, global, key);
22067 }
22068 }
22069 }
22070
22071 void Run(SignatureType signature_type, bool global, int key) {
22072 v8::Isolate* isolate = CcTest::isolate();
22073 v8::HandleScope scope(isolate);
22074 // Build a template for signature checks.
22075 Local<v8::ObjectTemplate> signature_template;
22076 Local<v8::Signature> signature;
22077 {
22078 Local<v8::FunctionTemplate> parent_template =
22079 FunctionTemplate::New(isolate);
22080 parent_template->SetHiddenPrototype(true);
22081 Local<v8::FunctionTemplate> function_template
22082 = FunctionTemplate::New(isolate);
22083 function_template->Inherit(parent_template);
22084 switch (signature_type) {
22085 case kNoSignature:
22086 break;
22087 case kSignatureOnReceiver:
22088 signature = v8::Signature::New(isolate, function_template);
22089 break;
22090 case kSignatureOnPrototype:
22091 signature = v8::Signature::New(isolate, parent_template);
22092 break;
22093 }
22094 signature_template = function_template->InstanceTemplate();
22095 }
22096 // Global object must pass checks.
22097 Local<v8::Context> context =
22098 v8::Context::New(isolate, NULL, signature_template);
22099 v8::Context::Scope context_scope(context);
22100 // Install regular object that can pass signature checks.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022101 Local<Object> function_receiver =
22102 signature_template->NewInstance(context).ToLocalChecked();
22103 CHECK(context->Global()
22104 ->Set(context, v8_str("function_receiver"), function_receiver)
22105 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022106 // Get the holder objects.
22107 Local<Object> inner_global =
22108 Local<Object>::Cast(context->Global()->GetPrototype());
22109 // Install functions on hidden prototype object if there is one.
22110 data = Object::New(isolate);
22111 Local<FunctionTemplate> function_template = FunctionTemplate::New(
22112 isolate, OptimizationCallback, data, signature);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022113 Local<Function> function =
22114 function_template->GetFunction(context).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022115 Local<Object> global_holder = inner_global;
22116 Local<Object> function_holder = function_receiver;
22117 if (signature_type == kSignatureOnPrototype) {
22118 function_holder = Local<Object>::Cast(function_holder->GetPrototype());
22119 global_holder = Local<Object>::Cast(global_holder->GetPrototype());
22120 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022121 global_holder->Set(context, v8_str("g_f"), function).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022122 global_holder->SetAccessorProperty(v8_str("g_acc"), function, function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022123 function_holder->Set(context, v8_str("f"), function).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022124 function_holder->SetAccessorProperty(v8_str("acc"), function, function);
22125 // Initialize expected values.
22126 callee = function;
22127 count = 0;
22128 if (global) {
22129 receiver = context->Global();
22130 holder = inner_global;
22131 } else {
22132 holder = function_receiver;
22133 // If not using a signature, add something else to the prototype chain
22134 // to test the case that holder != receiver
22135 if (signature_type == kNoSignature) {
22136 receiver = Local<Object>::Cast(CompileRun(
22137 "var receiver_subclass = {};\n"
22138 "receiver_subclass.__proto__ = function_receiver;\n"
22139 "receiver_subclass"));
22140 } else {
22141 receiver = Local<Object>::Cast(CompileRun(
22142 "var receiver_subclass = function_receiver;\n"
22143 "receiver_subclass"));
22144 }
22145 }
22146 // With no signature, the holder is not set.
22147 if (signature_type == kNoSignature) holder = receiver;
22148 // build wrap_function
22149 i::ScopedVector<char> wrap_function(200);
22150 if (global) {
22151 i::SNPrintF(
22152 wrap_function,
22153 "function wrap_f_%d() { var f = g_f; return f(); }\n"
22154 "function wrap_get_%d() { return this.g_acc; }\n"
22155 "function wrap_set_%d() { return this.g_acc = 1; }\n",
22156 key, key, key);
22157 } else {
22158 i::SNPrintF(
22159 wrap_function,
22160 "function wrap_f_%d() { return receiver_subclass.f(); }\n"
22161 "function wrap_get_%d() { return receiver_subclass.acc; }\n"
22162 "function wrap_set_%d() { return receiver_subclass.acc = 1; }\n",
22163 key, key, key);
22164 }
22165 // build source string
22166 i::ScopedVector<char> source(1000);
22167 i::SNPrintF(
22168 source,
22169 "%s\n" // wrap functions
22170 "function wrap_f() { return wrap_f_%d(); }\n"
22171 "function wrap_get() { return wrap_get_%d(); }\n"
22172 "function wrap_set() { return wrap_set_%d(); }\n"
22173 "check = function(returned) {\n"
22174 " if (returned !== 'returned') { throw returned; }\n"
22175 "}\n"
22176 "\n"
22177 "check(wrap_f());\n"
22178 "check(wrap_f());\n"
22179 "%%OptimizeFunctionOnNextCall(wrap_f_%d);\n"
22180 "check(wrap_f());\n"
22181 "\n"
22182 "check(wrap_get());\n"
22183 "check(wrap_get());\n"
22184 "%%OptimizeFunctionOnNextCall(wrap_get_%d);\n"
22185 "check(wrap_get());\n"
22186 "\n"
22187 "check = function(returned) {\n"
22188 " if (returned !== 1) { throw returned; }\n"
22189 "}\n"
22190 "check(wrap_set());\n"
22191 "check(wrap_set());\n"
22192 "%%OptimizeFunctionOnNextCall(wrap_set_%d);\n"
22193 "check(wrap_set());\n",
22194 wrap_function.start(), key, key, key, key, key, key);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022195 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022196 CompileRun(source.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022197 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022198 CHECK_EQ(9, count);
22199 }
22200};
22201
22202
22203Local<Object> ApiCallOptimizationChecker::data;
22204Local<Object> ApiCallOptimizationChecker::receiver;
22205Local<Object> ApiCallOptimizationChecker::holder;
22206Local<Object> ApiCallOptimizationChecker::callee;
22207int ApiCallOptimizationChecker::count = 0;
22208
22209
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022210TEST(FunctionCallOptimization) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022211 i::FLAG_allow_natives_syntax = true;
22212 ApiCallOptimizationChecker checker;
22213 checker.RunAll();
22214}
22215
22216
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022217TEST(FunctionCallOptimizationMultipleArgs) {
22218 i::FLAG_allow_natives_syntax = true;
22219 LocalContext context;
22220 v8::Isolate* isolate = context->GetIsolate();
22221 v8::HandleScope scope(isolate);
22222 Local<Object> global = context->Global();
22223 Local<v8::Function> function =
22224 Function::New(context.local(), Returns42).ToLocalChecked();
22225 global->Set(context.local(), v8_str("x"), function).FromJust();
22226 CompileRun(
22227 "function x_wrap() {\n"
22228 " for (var i = 0; i < 5; i++) {\n"
22229 " x(1,2,3);\n"
22230 " }\n"
22231 "}\n"
22232 "x_wrap();\n"
22233 "%OptimizeFunctionOnNextCall(x_wrap);"
22234 "x_wrap();\n");
22235}
22236
22237
22238static void ReturnsSymbolCallback(
22239 const v8::FunctionCallbackInfo<v8::Value>& info) {
22240 info.GetReturnValue().Set(v8::Symbol::New(info.GetIsolate()));
22241}
22242
22243
22244TEST(ApiCallbackCanReturnSymbols) {
22245 i::FLAG_allow_natives_syntax = true;
22246 LocalContext context;
22247 v8::Isolate* isolate = context->GetIsolate();
22248 v8::HandleScope scope(isolate);
22249 Local<Object> global = context->Global();
22250 Local<v8::Function> function =
22251 Function::New(context.local(), ReturnsSymbolCallback).ToLocalChecked();
22252 global->Set(context.local(), v8_str("x"), function).FromJust();
22253 CompileRun(
22254 "function x_wrap() {\n"
22255 " for (var i = 0; i < 5; i++) {\n"
22256 " x();\n"
22257 " }\n"
22258 "}\n"
22259 "x_wrap();\n"
22260 "%OptimizeFunctionOnNextCall(x_wrap);"
22261 "x_wrap();\n");
22262}
22263
22264
22265TEST(EmptyApiCallback) {
22266 LocalContext context;
22267 auto isolate = context->GetIsolate();
22268 v8::HandleScope scope(isolate);
22269 auto global = context->Global();
22270 auto function = FunctionTemplate::New(isolate)
22271 ->GetFunction(context.local())
22272 .ToLocalChecked();
22273 global->Set(context.local(), v8_str("x"), function).FromJust();
22274
22275 auto result = CompileRun("x()");
22276 CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
22277
22278 result = CompileRun("x(1,2,3)");
22279 CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
22280
22281 result = CompileRun("x.call(undefined)");
22282 CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
22283
22284 result = CompileRun("x.call(null)");
22285 CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
22286
22287 result = CompileRun("7 + x.call(3) + 11");
22288 CHECK(result->IsInt32());
22289 CHECK_EQ(21, result->Int32Value(context.local()).FromJust());
22290
22291 result = CompileRun("7 + x.call(3, 101, 102, 103, 104) + 11");
22292 CHECK(result->IsInt32());
22293 CHECK_EQ(21, result->Int32Value(context.local()).FromJust());
22294
22295 result = CompileRun("var y = []; x.call(y)");
22296 CHECK(result->IsArray());
22297
22298 result = CompileRun("x.call(y, 1, 2, 3, 4)");
22299 CHECK(result->IsArray());
22300}
22301
22302
22303TEST(SimpleSignatureCheck) {
22304 LocalContext context;
22305 auto isolate = context->GetIsolate();
22306 v8::HandleScope scope(isolate);
22307 auto global = context->Global();
22308 auto sig_obj = FunctionTemplate::New(isolate);
22309 auto sig = v8::Signature::New(isolate, sig_obj);
22310 auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
22311 global->Set(context.local(), v8_str("sig_obj"),
22312 sig_obj->GetFunction(context.local()).ToLocalChecked())
22313 .FromJust();
22314 global->Set(context.local(), v8_str("x"),
22315 x->GetFunction(context.local()).ToLocalChecked())
22316 .FromJust();
22317 CompileRun("var s = new sig_obj();");
22318 {
22319 TryCatch try_catch(isolate);
22320 CompileRun("x()");
22321 CHECK(try_catch.HasCaught());
22322 }
22323 {
22324 TryCatch try_catch(isolate);
22325 CompileRun("x.call(1)");
22326 CHECK(try_catch.HasCaught());
22327 }
22328 {
22329 TryCatch try_catch(isolate);
22330 auto result = CompileRun("s.x = x; s.x()");
22331 CHECK(!try_catch.HasCaught());
22332 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
22333 }
22334 {
22335 TryCatch try_catch(isolate);
22336 auto result = CompileRun("x.call(s)");
22337 CHECK(!try_catch.HasCaught());
22338 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
22339 }
22340}
22341
22342
22343TEST(ChainSignatureCheck) {
22344 LocalContext context;
22345 auto isolate = context->GetIsolate();
22346 v8::HandleScope scope(isolate);
22347 auto global = context->Global();
22348 auto sig_obj = FunctionTemplate::New(isolate);
22349 auto sig = v8::Signature::New(isolate, sig_obj);
22350 for (int i = 0; i < 4; ++i) {
22351 auto temp = FunctionTemplate::New(isolate);
22352 temp->Inherit(sig_obj);
22353 sig_obj = temp;
22354 }
22355 auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
22356 global->Set(context.local(), v8_str("sig_obj"),
22357 sig_obj->GetFunction(context.local()).ToLocalChecked())
22358 .FromJust();
22359 global->Set(context.local(), v8_str("x"),
22360 x->GetFunction(context.local()).ToLocalChecked())
22361 .FromJust();
22362 CompileRun("var s = new sig_obj();");
22363 {
22364 TryCatch try_catch(isolate);
22365 CompileRun("x()");
22366 CHECK(try_catch.HasCaught());
22367 }
22368 {
22369 TryCatch try_catch(isolate);
22370 CompileRun("x.call(1)");
22371 CHECK(try_catch.HasCaught());
22372 }
22373 {
22374 TryCatch try_catch(isolate);
22375 auto result = CompileRun("s.x = x; s.x()");
22376 CHECK(!try_catch.HasCaught());
22377 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
22378 }
22379 {
22380 TryCatch try_catch(isolate);
22381 auto result = CompileRun("x.call(s)");
22382 CHECK(!try_catch.HasCaught());
22383 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
22384 }
22385}
22386
22387
22388TEST(PrototypeSignatureCheck) {
22389 LocalContext context;
22390 auto isolate = context->GetIsolate();
22391 v8::HandleScope scope(isolate);
22392 auto global = context->Global();
22393 auto sig_obj = FunctionTemplate::New(isolate);
22394 sig_obj->SetHiddenPrototype(true);
22395 auto sig = v8::Signature::New(isolate, sig_obj);
22396 auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
22397 global->Set(context.local(), v8_str("sig_obj"),
22398 sig_obj->GetFunction(context.local()).ToLocalChecked())
22399 .FromJust();
22400 global->Set(context.local(), v8_str("x"),
22401 x->GetFunction(context.local()).ToLocalChecked())
22402 .FromJust();
22403 CompileRun("s = {}; s.__proto__ = new sig_obj();");
22404 {
22405 TryCatch try_catch(isolate);
22406 CompileRun("x()");
22407 CHECK(try_catch.HasCaught());
22408 }
22409 {
22410 TryCatch try_catch(isolate);
22411 CompileRun("x.call(1)");
22412 CHECK(try_catch.HasCaught());
22413 }
22414 {
22415 TryCatch try_catch(isolate);
22416 auto result = CompileRun("s.x = x; s.x()");
22417 CHECK(!try_catch.HasCaught());
22418 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
22419 }
22420 {
22421 TryCatch try_catch(isolate);
22422 auto result = CompileRun("x.call(s)");
22423 CHECK(!try_catch.HasCaught());
22424 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
22425 }
22426}
22427
22428
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022429static const char* last_event_message;
22430static int last_event_status;
22431void StoringEventLoggerCallback(const char* message, int status) {
22432 last_event_message = message;
22433 last_event_status = status;
22434}
22435
22436
22437TEST(EventLogging) {
22438 v8::Isolate* isolate = CcTest::isolate();
22439 isolate->SetEventLogger(StoringEventLoggerCallback);
22440 v8::internal::HistogramTimer histogramTimer(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022441 "V8.Test", 0, 10000, v8::internal::HistogramTimer::MILLISECOND, 50,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022442 reinterpret_cast<v8::internal::Isolate*>(isolate));
22443 histogramTimer.Start();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022444 CHECK_EQ(0, strcmp("V8.Test", last_event_message));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022445 CHECK_EQ(0, last_event_status);
22446 histogramTimer.Stop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022447 CHECK_EQ(0, strcmp("V8.Test", last_event_message));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022448 CHECK_EQ(1, last_event_status);
22449}
22450
22451
22452TEST(Promises) {
22453 LocalContext context;
22454 v8::Isolate* isolate = context->GetIsolate();
22455 v8::HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022456
22457 // Creation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022458 Local<v8::Promise::Resolver> pr =
22459 v8::Promise::Resolver::New(context.local()).ToLocalChecked();
22460 Local<v8::Promise::Resolver> rr =
22461 v8::Promise::Resolver::New(context.local()).ToLocalChecked();
22462 Local<v8::Promise> p = pr->GetPromise();
22463 Local<v8::Promise> r = rr->GetPromise();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022464
22465 // IsPromise predicate.
22466 CHECK(p->IsPromise());
22467 CHECK(r->IsPromise());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022468 Local<Value> o = v8::Object::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022469 CHECK(!o->IsPromise());
22470
22471 // Resolution and rejection.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022472 pr->Resolve(context.local(), v8::Integer::New(isolate, 1)).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022473 CHECK(p->IsPromise());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022474 rr->Reject(context.local(), v8::Integer::New(isolate, 2)).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022475 CHECK(r->IsPromise());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022476}
22477
22478
22479TEST(PromiseThen) {
22480 LocalContext context;
22481 v8::Isolate* isolate = context->GetIsolate();
22482 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022483 Local<Object> global = context->Global();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022484
22485 // Creation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022486 Local<v8::Promise::Resolver> pr =
22487 v8::Promise::Resolver::New(context.local()).ToLocalChecked();
22488 Local<v8::Promise::Resolver> qr =
22489 v8::Promise::Resolver::New(context.local()).ToLocalChecked();
22490 Local<v8::Promise> p = pr->GetPromise();
22491 Local<v8::Promise> q = qr->GetPromise();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022492
22493 CHECK(p->IsPromise());
22494 CHECK(q->IsPromise());
22495
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022496 pr->Resolve(context.local(), v8::Integer::New(isolate, 1)).FromJust();
22497 qr->Resolve(context.local(), p).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022498
22499 // Chaining non-pending promises.
22500 CompileRun(
22501 "var x1 = 0;\n"
22502 "var x2 = 0;\n"
22503 "function f1(x) { x1 = x; return x+1 };\n"
22504 "function f2(x) { x2 = x; return x+1 };\n");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022505 Local<Function> f1 = Local<Function>::Cast(
22506 global->Get(context.local(), v8_str("f1")).ToLocalChecked());
22507 Local<Function> f2 = Local<Function>::Cast(
22508 global->Get(context.local(), v8_str("f2")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022509
22510 // Then
22511 CompileRun("x1 = x2 = 0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022512 q->Then(context.local(), f1).ToLocalChecked();
22513 CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
22514 .ToLocalChecked()
22515 ->Int32Value(context.local())
22516 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022517 isolate->RunMicrotasks();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022518 CHECK_EQ(1, global->Get(context.local(), v8_str("x1"))
22519 .ToLocalChecked()
22520 ->Int32Value(context.local())
22521 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022522
22523 // Then
22524 CompileRun("x1 = x2 = 0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022525 pr = v8::Promise::Resolver::New(context.local()).ToLocalChecked();
22526 qr = v8::Promise::Resolver::New(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022527
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022528 qr->Resolve(context.local(), pr).FromJust();
22529 qr->GetPromise()
22530 ->Then(context.local(), f1)
22531 .ToLocalChecked()
22532 ->Then(context.local(), f2)
22533 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022534
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022535 CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
22536 .ToLocalChecked()
22537 ->Int32Value(context.local())
22538 .FromJust());
22539 CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
22540 .ToLocalChecked()
22541 ->Int32Value(context.local())
22542 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022543 isolate->RunMicrotasks();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022544 CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
22545 .ToLocalChecked()
22546 ->Int32Value(context.local())
22547 .FromJust());
22548 CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
22549 .ToLocalChecked()
22550 ->Int32Value(context.local())
22551 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022552
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022553 pr->Resolve(context.local(), v8::Integer::New(isolate, 3)).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022554
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022555 CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
22556 .ToLocalChecked()
22557 ->Int32Value(context.local())
22558 .FromJust());
22559 CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
22560 .ToLocalChecked()
22561 ->Int32Value(context.local())
22562 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022563 isolate->RunMicrotasks();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022564 CHECK_EQ(3, global->Get(context.local(), v8_str("x1"))
22565 .ToLocalChecked()
22566 ->Int32Value(context.local())
22567 .FromJust());
22568 CHECK_EQ(4, global->Get(context.local(), v8_str("x2"))
22569 .ToLocalChecked()
22570 ->Int32Value(context.local())
22571 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022572}
22573
22574
22575TEST(DisallowJavascriptExecutionScope) {
22576 LocalContext context;
22577 v8::Isolate* isolate = context->GetIsolate();
22578 v8::HandleScope scope(isolate);
22579 v8::Isolate::DisallowJavascriptExecutionScope no_js(
22580 isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
22581 CompileRun("2+2");
22582}
22583
22584
22585TEST(AllowJavascriptExecutionScope) {
22586 LocalContext context;
22587 v8::Isolate* isolate = context->GetIsolate();
22588 v8::HandleScope scope(isolate);
22589 v8::Isolate::DisallowJavascriptExecutionScope no_js(
22590 isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
22591 v8::Isolate::DisallowJavascriptExecutionScope throw_js(
22592 isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
22593 { v8::Isolate::AllowJavascriptExecutionScope yes_js(isolate);
22594 CompileRun("1+1");
22595 }
22596}
22597
22598
22599TEST(ThrowOnJavascriptExecution) {
22600 LocalContext context;
22601 v8::Isolate* isolate = context->GetIsolate();
22602 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022603 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022604 v8::Isolate::DisallowJavascriptExecutionScope throw_js(
22605 isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
22606 CompileRun("1+1");
22607 CHECK(try_catch.HasCaught());
22608}
22609
22610
22611TEST(Regress354123) {
22612 LocalContext current;
22613 v8::Isolate* isolate = current->GetIsolate();
22614 v8::HandleScope scope(isolate);
22615
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022616 v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
22617 templ->SetAccessCheckCallback(AccessCounter);
22618 CHECK(current->Global()
22619 ->Set(current.local(), v8_str("friend"),
22620 templ->NewInstance(current.local()).ToLocalChecked())
22621 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022622
22623 // Test access using __proto__ from the prototype chain.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022624 access_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022625 CompileRun("friend.__proto__ = {};");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022626 CHECK_EQ(2, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022627 CompileRun("friend.__proto__;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022628 CHECK_EQ(4, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022629
22630 // Test access using __proto__ as a hijacked function (A).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022631 access_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022632 CompileRun("var p = Object.prototype;"
22633 "var f = Object.getOwnPropertyDescriptor(p, '__proto__').set;"
22634 "f.call(friend, {});");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022635 CHECK_EQ(1, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022636 CompileRun("var p = Object.prototype;"
22637 "var f = Object.getOwnPropertyDescriptor(p, '__proto__').get;"
22638 "f.call(friend);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022639 CHECK_EQ(2, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022640
22641 // Test access using __proto__ as a hijacked function (B).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022642 access_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022643 CompileRun("var f = Object.prototype.__lookupSetter__('__proto__');"
22644 "f.call(friend, {});");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022645 CHECK_EQ(1, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022646 CompileRun("var f = Object.prototype.__lookupGetter__('__proto__');"
22647 "f.call(friend);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022648 CHECK_EQ(2, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022649
22650 // Test access using Object.setPrototypeOf reflective method.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022651 access_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022652 CompileRun("Object.setPrototypeOf(friend, {});");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022653 CHECK_EQ(1, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022654 CompileRun("Object.getPrototypeOf(friend);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022655 CHECK_EQ(2, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022656}
22657
22658
22659TEST(CaptureStackTraceForStackOverflow) {
22660 v8::internal::FLAG_stack_size = 150;
22661 LocalContext current;
22662 v8::Isolate* isolate = current->GetIsolate();
22663 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022664 isolate->SetCaptureStackTraceForUncaughtExceptions(true, 10,
22665 v8::StackTrace::kDetailed);
22666 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022667 CompileRun("(function f(x) { f(x+1); })(0)");
22668 CHECK(try_catch.HasCaught());
22669}
22670
22671
22672TEST(ScriptNameAndLineNumber) {
22673 LocalContext env;
22674 v8::Isolate* isolate = env->GetIsolate();
22675 v8::HandleScope scope(isolate);
22676 const char* url = "http://www.foo.com/foo.js";
22677 v8::ScriptOrigin origin(v8_str(url), v8::Integer::New(isolate, 13));
22678 v8::ScriptCompiler::Source script_source(v8_str("var foo;"), origin);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022679 Local<Script> script =
22680 v8::ScriptCompiler::Compile(env.local(), &script_source).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022681 Local<Value> script_name = script->GetUnboundScript()->GetScriptName();
22682 CHECK(!script_name.IsEmpty());
22683 CHECK(script_name->IsString());
22684 String::Utf8Value utf8_name(script_name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022685 CHECK_EQ(0, strcmp(url, *utf8_name));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022686 int line_number = script->GetUnboundScript()->GetLineNumber(0);
22687 CHECK_EQ(13, line_number);
22688}
22689
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022690void CheckMagicComments(Local<Script> script, const char* expected_source_url,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022691 const char* expected_source_mapping_url) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022692 if (expected_source_url != NULL) {
22693 v8::String::Utf8Value url(script->GetUnboundScript()->GetSourceURL());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022694 CHECK_EQ(0, strcmp(expected_source_url, *url));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022695 } else {
22696 CHECK(script->GetUnboundScript()->GetSourceURL()->IsUndefined());
22697 }
22698 if (expected_source_mapping_url != NULL) {
22699 v8::String::Utf8Value url(
22700 script->GetUnboundScript()->GetSourceMappingURL());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022701 CHECK_EQ(0, strcmp(expected_source_mapping_url, *url));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022702 } else {
22703 CHECK(script->GetUnboundScript()->GetSourceMappingURL()->IsUndefined());
22704 }
22705}
22706
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022707void SourceURLHelper(const char* source, const char* expected_source_url,
22708 const char* expected_source_mapping_url) {
22709 Local<Script> script = v8_compile(source);
22710 CheckMagicComments(script, expected_source_url, expected_source_mapping_url);
22711}
22712
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022713
22714TEST(ScriptSourceURLAndSourceMappingURL) {
22715 LocalContext env;
22716 v8::Isolate* isolate = env->GetIsolate();
22717 v8::HandleScope scope(isolate);
22718 SourceURLHelper("function foo() {}\n"
22719 "//# sourceURL=bar1.js\n", "bar1.js", NULL);
22720 SourceURLHelper("function foo() {}\n"
22721 "//# sourceMappingURL=bar2.js\n", NULL, "bar2.js");
22722
22723 // Both sourceURL and sourceMappingURL.
22724 SourceURLHelper("function foo() {}\n"
22725 "//# sourceURL=bar3.js\n"
22726 "//# sourceMappingURL=bar4.js\n", "bar3.js", "bar4.js");
22727
22728 // Two source URLs; the first one is ignored.
22729 SourceURLHelper("function foo() {}\n"
22730 "//# sourceURL=ignoreme.js\n"
22731 "//# sourceURL=bar5.js\n", "bar5.js", NULL);
22732 SourceURLHelper("function foo() {}\n"
22733 "//# sourceMappingURL=ignoreme.js\n"
22734 "//# sourceMappingURL=bar6.js\n", NULL, "bar6.js");
22735
22736 // SourceURL or sourceMappingURL in the middle of the script.
22737 SourceURLHelper("function foo() {}\n"
22738 "//# sourceURL=bar7.js\n"
22739 "function baz() {}\n", "bar7.js", NULL);
22740 SourceURLHelper("function foo() {}\n"
22741 "//# sourceMappingURL=bar8.js\n"
22742 "function baz() {}\n", NULL, "bar8.js");
22743
22744 // Too much whitespace.
22745 SourceURLHelper("function foo() {}\n"
22746 "//# sourceURL=bar9.js\n"
22747 "//# sourceMappingURL=bar10.js\n", NULL, NULL);
22748 SourceURLHelper("function foo() {}\n"
22749 "//# sourceURL =bar11.js\n"
22750 "//# sourceMappingURL =bar12.js\n", NULL, NULL);
22751
22752 // Disallowed characters in value.
22753 SourceURLHelper("function foo() {}\n"
22754 "//# sourceURL=bar13 .js \n"
22755 "//# sourceMappingURL=bar14 .js \n",
22756 NULL, NULL);
22757 SourceURLHelper("function foo() {}\n"
22758 "//# sourceURL=bar15\t.js \n"
22759 "//# sourceMappingURL=bar16\t.js \n",
22760 NULL, NULL);
22761 SourceURLHelper("function foo() {}\n"
22762 "//# sourceURL=bar17'.js \n"
22763 "//# sourceMappingURL=bar18'.js \n",
22764 NULL, NULL);
22765 SourceURLHelper("function foo() {}\n"
22766 "//# sourceURL=bar19\".js \n"
22767 "//# sourceMappingURL=bar20\".js \n",
22768 NULL, NULL);
22769
22770 // Not too much whitespace.
22771 SourceURLHelper("function foo() {}\n"
22772 "//# sourceURL= bar21.js \n"
22773 "//# sourceMappingURL= bar22.js \n", "bar21.js", "bar22.js");
22774}
22775
22776
22777TEST(GetOwnPropertyDescriptor) {
22778 LocalContext env;
22779 v8::Isolate* isolate = env->GetIsolate();
22780 v8::HandleScope scope(isolate);
22781 CompileRun(
22782 "var x = { value : 13};"
22783 "Object.defineProperty(x, 'p0', {value : 12});"
22784 "Object.defineProperty(x, 'p1', {"
22785 " set : function(value) { this.value = value; },"
22786 " get : function() { return this.value; },"
22787 "});");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022788 Local<Object> x = Local<Object>::Cast(
22789 env->Global()->Get(env.local(), v8_str("x")).ToLocalChecked());
22790 Local<Value> desc =
22791 x->GetOwnPropertyDescriptor(env.local(), v8_str("no_prop"))
22792 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022793 CHECK(desc->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022794 desc =
22795 x->GetOwnPropertyDescriptor(env.local(), v8_str("p0")).ToLocalChecked();
22796 CHECK(v8_num(12)
22797 ->Equals(env.local(), Local<Object>::Cast(desc)
22798 ->Get(env.local(), v8_str("value"))
22799 .ToLocalChecked())
22800 .FromJust());
22801 desc =
22802 x->GetOwnPropertyDescriptor(env.local(), v8_str("p1")).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022803 Local<Function> set =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022804 Local<Function>::Cast(Local<Object>::Cast(desc)
22805 ->Get(env.local(), v8_str("set"))
22806 .ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022807 Local<Function> get =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022808 Local<Function>::Cast(Local<Object>::Cast(desc)
22809 ->Get(env.local(), v8_str("get"))
22810 .ToLocalChecked());
22811 CHECK(v8_num(13)
22812 ->Equals(env.local(),
22813 get->Call(env.local(), x, 0, NULL).ToLocalChecked())
22814 .FromJust());
22815 Local<Value> args[] = {v8_num(14)};
22816 set->Call(env.local(), x, 1, args).ToLocalChecked();
22817 CHECK(v8_num(14)
22818 ->Equals(env.local(),
22819 get->Call(env.local(), x, 0, NULL).ToLocalChecked())
22820 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022821}
22822
22823
22824TEST(Regress411877) {
22825 v8::Isolate* isolate = CcTest::isolate();
22826 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022827 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022828 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022829 object_template->SetAccessCheckCallback(AccessCounter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022830
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022831 v8::Local<Context> context = Context::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022832 v8::Context::Scope context_scope(context);
22833
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022834 CHECK(context->Global()
22835 ->Set(context, v8_str("o"),
22836 object_template->NewInstance(context).ToLocalChecked())
22837 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022838 CompileRun("Object.getOwnPropertyNames(o)");
22839}
22840
22841
22842TEST(GetHiddenPropertyTableAfterAccessCheck) {
22843 v8::Isolate* isolate = CcTest::isolate();
22844 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022845 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022846 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022847 object_template->SetAccessCheckCallback(AccessCounter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022848
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022849 v8::Local<Context> context = Context::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022850 v8::Context::Scope context_scope(context);
22851
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022852 v8::Local<v8::Object> obj =
22853 object_template->NewInstance(context).ToLocalChecked();
22854 obj->Set(context, v8_str("key"), v8_str("value")).FromJust();
22855 obj->Delete(context, v8_str("key")).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022856
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022857 obj->SetPrivate(context, v8::Private::New(isolate, v8_str("hidden key 2")),
22858 v8_str("hidden value 2"))
22859 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022860}
22861
22862
22863TEST(Regress411793) {
22864 v8::Isolate* isolate = CcTest::isolate();
22865 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022866 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022867 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022868 object_template->SetAccessCheckCallback(AccessCounter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022869
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022870 v8::Local<Context> context = Context::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022871 v8::Context::Scope context_scope(context);
22872
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022873 CHECK(context->Global()
22874 ->Set(context, v8_str("o"),
22875 object_template->NewInstance(context).ToLocalChecked())
22876 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022877 CompileRun(
22878 "Object.defineProperty(o, 'key', "
22879 " { get: function() {}, set: function() {} });");
22880}
22881
22882class TestSourceStream : public v8::ScriptCompiler::ExternalSourceStream {
22883 public:
22884 explicit TestSourceStream(const char** chunks) : chunks_(chunks), index_(0) {}
22885
22886 virtual size_t GetMoreData(const uint8_t** src) {
22887 // Unlike in real use cases, this function will never block.
22888 if (chunks_[index_] == NULL) {
22889 return 0;
22890 }
22891 // Copy the data, since the caller takes ownership of it.
22892 size_t len = strlen(chunks_[index_]);
22893 // We don't need to zero-terminate since we return the length.
22894 uint8_t* copy = new uint8_t[len];
22895 memcpy(copy, chunks_[index_], len);
22896 *src = copy;
22897 ++index_;
22898 return len;
22899 }
22900
22901 // Helper for constructing a string from chunks (the compilation needs it
22902 // too).
22903 static char* FullSourceString(const char** chunks) {
22904 size_t total_len = 0;
22905 for (size_t i = 0; chunks[i] != NULL; ++i) {
22906 total_len += strlen(chunks[i]);
22907 }
22908 char* full_string = new char[total_len + 1];
22909 size_t offset = 0;
22910 for (size_t i = 0; chunks[i] != NULL; ++i) {
22911 size_t len = strlen(chunks[i]);
22912 memcpy(full_string + offset, chunks[i], len);
22913 offset += len;
22914 }
22915 full_string[total_len] = 0;
22916 return full_string;
22917 }
22918
22919 private:
22920 const char** chunks_;
22921 unsigned index_;
22922};
22923
22924
22925// Helper function for running streaming tests.
22926void RunStreamingTest(const char** chunks,
22927 v8::ScriptCompiler::StreamedSource::Encoding encoding =
22928 v8::ScriptCompiler::StreamedSource::ONE_BYTE,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022929 bool expected_success = true,
22930 const char* expected_source_url = NULL,
22931 const char* expected_source_mapping_url = NULL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022932 LocalContext env;
22933 v8::Isolate* isolate = env->GetIsolate();
22934 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022935 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022936
22937 v8::ScriptCompiler::StreamedSource source(new TestSourceStream(chunks),
22938 encoding);
22939 v8::ScriptCompiler::ScriptStreamingTask* task =
22940 v8::ScriptCompiler::StartStreamingScript(isolate, &source);
22941
22942 // TestSourceStream::GetMoreData won't block, so it's OK to just run the
22943 // task here in the main thread.
22944 task->Run();
22945 delete task;
22946
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022947 // Possible errors are only produced while compiling.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022948 CHECK_EQ(false, try_catch.HasCaught());
22949
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022950 v8::ScriptOrigin origin(v8_str("http://foo.com"));
22951 char* full_source = TestSourceStream::FullSourceString(chunks);
22952 v8::MaybeLocal<Script> script = v8::ScriptCompiler::Compile(
22953 env.local(), &source, v8_str(full_source), origin);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022954 if (expected_success) {
22955 CHECK(!script.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022956 v8::Local<Value> result(
22957 script.ToLocalChecked()->Run(env.local()).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022958 // All scripts are supposed to return the fixed value 13 when ran.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022959 CHECK_EQ(13, result->Int32Value(env.local()).FromJust());
22960 CheckMagicComments(script.ToLocalChecked(), expected_source_url,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022961 expected_source_mapping_url);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022962 } else {
22963 CHECK(script.IsEmpty());
22964 CHECK(try_catch.HasCaught());
22965 }
22966 delete[] full_source;
22967}
22968
22969
22970TEST(StreamingSimpleScript) {
22971 // This script is unrealistically small, since no one chunk is enough to fill
22972 // the backing buffer of Scanner, let alone overflow it.
22973 const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
22974 NULL};
22975 RunStreamingTest(chunks);
22976}
22977
22978
22979TEST(StreamingBiggerScript) {
22980 const char* chunk1 =
22981 "function foo() {\n"
22982 " // Make this chunk sufficiently long so that it will overflow the\n"
22983 " // backing buffer of the Scanner.\n"
22984 " var i = 0;\n"
22985 " var result = 0;\n"
22986 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
22987 " result = 0;\n"
22988 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
22989 " result = 0;\n"
22990 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
22991 " result = 0;\n"
22992 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
22993 " return result;\n"
22994 "}\n";
22995 const char* chunks[] = {chunk1, "foo(); ", NULL};
22996 RunStreamingTest(chunks);
22997}
22998
22999
23000TEST(StreamingScriptWithParseError) {
23001 // Test that parse errors from streamed scripts are propagated correctly.
23002 {
23003 char chunk1[] =
23004 " // This will result in a parse error.\n"
23005 " var if else then foo";
23006 char chunk2[] = " 13\n";
23007 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23008
23009 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::ONE_BYTE,
23010 false);
23011 }
23012 // Test that the next script succeeds normally.
23013 {
23014 char chunk1[] =
23015 " // This will be parsed successfully.\n"
23016 " function foo() { return ";
23017 char chunk2[] = " 13; }\n";
23018 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23019
23020 RunStreamingTest(chunks);
23021 }
23022}
23023
23024
23025TEST(StreamingUtf8Script) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023026 // We'd want to write \uc481 instead of \xec\x92\x81, but Windows compilers
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023027 // don't like it.
23028 const char* chunk1 =
23029 "function foo() {\n"
23030 " // This function will contain an UTF-8 character which is not in\n"
23031 " // ASCII.\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023032 " var foob\xec\x92\x81r = 13;\n"
23033 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023034 "}\n";
23035 const char* chunks[] = {chunk1, "foo(); ", NULL};
23036 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23037}
23038
23039
23040TEST(StreamingUtf8ScriptWithSplitCharactersSanityCheck) {
23041 // A sanity check to prove that the approach of splitting UTF-8
23042 // characters is correct. Here is an UTF-8 character which will take three
23043 // bytes.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023044 const char* reference = "\xec\x92\x81";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023045 CHECK(3u == strlen(reference)); // NOLINT - no CHECK_EQ for unsigned.
23046
23047 char chunk1[] =
23048 "function foo() {\n"
23049 " // This function will contain an UTF-8 character which is not in\n"
23050 " // ASCII.\n"
23051 " var foob";
23052 char chunk2[] =
23053 "XXXr = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023054 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023055 "}\n";
23056 for (int i = 0; i < 3; ++i) {
23057 chunk2[i] = reference[i];
23058 }
23059 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23060 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23061}
23062
23063
23064TEST(StreamingUtf8ScriptWithSplitCharacters) {
23065 // Stream data where a multi-byte UTF-8 character is split between two data
23066 // chunks.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023067 const char* reference = "\xec\x92\x81";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023068 char chunk1[] =
23069 "function foo() {\n"
23070 " // This function will contain an UTF-8 character which is not in\n"
23071 " // ASCII.\n"
23072 " var foobX";
23073 char chunk2[] =
23074 "XXr = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023075 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023076 "}\n";
23077 chunk1[strlen(chunk1) - 1] = reference[0];
23078 chunk2[0] = reference[1];
23079 chunk2[1] = reference[2];
23080 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23081 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23082}
23083
23084
23085TEST(StreamingUtf8ScriptWithSplitCharactersValidEdgeCases) {
23086 // Tests edge cases which should still be decoded correctly.
23087
23088 // Case 1: a chunk contains only bytes for a split character (and no other
23089 // data). This kind of a chunk would be exceptionally small, but we should
23090 // still decode it correctly.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023091 const char* reference = "\xec\x92\x81";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023092 // The small chunk is at the beginning of the split character
23093 {
23094 char chunk1[] =
23095 "function foo() {\n"
23096 " // This function will contain an UTF-8 character which is not in\n"
23097 " // ASCII.\n"
23098 " var foob";
23099 char chunk2[] = "XX";
23100 char chunk3[] =
23101 "Xr = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023102 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023103 "}\n";
23104 chunk2[0] = reference[0];
23105 chunk2[1] = reference[1];
23106 chunk3[0] = reference[2];
23107 const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
23108 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23109 }
23110 // The small chunk is at the end of a character
23111 {
23112 char chunk1[] =
23113 "function foo() {\n"
23114 " // This function will contain an UTF-8 character which is not in\n"
23115 " // ASCII.\n"
23116 " var foobX";
23117 char chunk2[] = "XX";
23118 char chunk3[] =
23119 "r = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023120 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023121 "}\n";
23122 chunk1[strlen(chunk1) - 1] = reference[0];
23123 chunk2[0] = reference[1];
23124 chunk2[1] = reference[2];
23125 const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
23126 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23127 }
23128 // Case 2: the script ends with a multi-byte character. Make sure that it's
23129 // decoded correctly and not just ignored.
23130 {
23131 char chunk1[] =
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023132 "var foob\xec\x92\x81 = 13;\n"
23133 "foob\xec\x92\x81";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023134 const char* chunks[] = {chunk1, NULL};
23135 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23136 }
23137}
23138
23139
23140TEST(StreamingUtf8ScriptWithSplitCharactersInvalidEdgeCases) {
23141 // Test cases where a UTF-8 character is split over several chunks. Those
23142 // cases are not supported (the embedder should give the data in big enough
23143 // chunks), but we shouldn't crash, just produce a parse error.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023144 const char* reference = "\xec\x92\x81";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023145 char chunk1[] =
23146 "function foo() {\n"
23147 " // This function will contain an UTF-8 character which is not in\n"
23148 " // ASCII.\n"
23149 " var foobX";
23150 char chunk2[] = "X";
23151 char chunk3[] =
23152 "Xr = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023153 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023154 "}\n";
23155 chunk1[strlen(chunk1) - 1] = reference[0];
23156 chunk2[0] = reference[1];
23157 chunk3[0] = reference[2];
23158 const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
23159
23160 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
23161}
23162
23163
23164TEST(StreamingProducesParserCache) {
23165 i::FLAG_min_preparse_length = 0;
23166 const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
23167 NULL};
23168
23169 LocalContext env;
23170 v8::Isolate* isolate = env->GetIsolate();
23171 v8::HandleScope scope(isolate);
23172
23173 v8::ScriptCompiler::StreamedSource source(
23174 new TestSourceStream(chunks),
23175 v8::ScriptCompiler::StreamedSource::ONE_BYTE);
23176 v8::ScriptCompiler::ScriptStreamingTask* task =
23177 v8::ScriptCompiler::StartStreamingScript(
23178 isolate, &source, v8::ScriptCompiler::kProduceParserCache);
23179
23180 // TestSourceStream::GetMoreData won't block, so it's OK to just run the
23181 // task here in the main thread.
23182 task->Run();
23183 delete task;
23184
23185 const v8::ScriptCompiler::CachedData* cached_data = source.GetCachedData();
23186 CHECK(cached_data != NULL);
23187 CHECK(cached_data->data != NULL);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023188 CHECK(!cached_data->rejected);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023189 CHECK_GT(cached_data->length, 0);
23190}
23191
23192
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023193TEST(StreamingWithDebuggingEnabledLate) {
23194 // The streaming parser can only parse lazily, i.e. inner functions are not
23195 // fully parsed. However, we may compile inner functions eagerly when
23196 // debugging. Make sure that we can deal with this when turning on debugging
23197 // after streaming parser has already finished parsing.
23198 i::FLAG_min_preparse_length = 0;
23199 const char* chunks[] = {"with({x:1}) {",
23200 " var foo = function foo(y) {",
23201 " return x + y;",
23202 " };",
23203 " foo(2);",
23204 "}",
23205 NULL};
23206
23207 LocalContext env;
23208 v8::Isolate* isolate = env->GetIsolate();
23209 v8::HandleScope scope(isolate);
23210 v8::TryCatch try_catch(isolate);
23211
23212 v8::ScriptCompiler::StreamedSource source(
23213 new TestSourceStream(chunks),
23214 v8::ScriptCompiler::StreamedSource::ONE_BYTE);
23215 v8::ScriptCompiler::ScriptStreamingTask* task =
23216 v8::ScriptCompiler::StartStreamingScript(isolate, &source);
23217
23218 task->Run();
23219 delete task;
23220
23221 CHECK(!try_catch.HasCaught());
23222
23223 v8::ScriptOrigin origin(v8_str("http://foo.com"));
23224 char* full_source = TestSourceStream::FullSourceString(chunks);
23225
23226 EnableDebugger(isolate);
23227
23228 v8::Local<Script> script =
23229 v8::ScriptCompiler::Compile(env.local(), &source, v8_str(full_source),
23230 origin)
23231 .ToLocalChecked();
23232
23233 Maybe<uint32_t> result =
23234 script->Run(env.local()).ToLocalChecked()->Uint32Value(env.local());
23235 CHECK_EQ(3U, result.FromMaybe(0));
23236
23237 delete[] full_source;
23238
23239 DisableDebugger(isolate);
23240}
23241
23242
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023243TEST(StreamingScriptWithInvalidUtf8) {
23244 // Regression test for a crash: test that invalid UTF-8 bytes in the end of a
23245 // chunk don't produce a crash.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023246 const char* reference = "\xec\x92\x81\x80\x80";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023247 char chunk1[] =
23248 "function foo() {\n"
23249 " // This function will contain an UTF-8 character which is not in\n"
23250 " // ASCII.\n"
23251 " var foobXXXXX"; // Too many bytes which look like incomplete chars!
23252 char chunk2[] =
23253 "r = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023254 " return foob\xec\x92\x81\x80\x80r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023255 "}\n";
23256 for (int i = 0; i < 5; ++i) chunk1[strlen(chunk1) - 5 + i] = reference[i];
23257
23258 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23259 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
23260}
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023261
23262
23263TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit) {
23264 // Regression test: Stream data where there are several multi-byte UTF-8
23265 // characters in a sequence and one of them is split between two data chunks.
23266 const char* reference = "\xec\x92\x81";
23267 char chunk1[] =
23268 "function foo() {\n"
23269 " // This function will contain an UTF-8 character which is not in\n"
23270 " // ASCII.\n"
23271 " var foob\xec\x92\x81X";
23272 char chunk2[] =
23273 "XXr = 13;\n"
23274 " return foob\xec\x92\x81\xec\x92\x81r;\n"
23275 "}\n";
23276 chunk1[strlen(chunk1) - 1] = reference[0];
23277 chunk2[0] = reference[1];
23278 chunk2[1] = reference[2];
23279 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23280 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23281}
23282
23283
23284TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit2) {
23285 // Another regression test, similar to the previous one. The difference is
23286 // that the split character is not the last one in the sequence.
23287 const char* reference = "\xec\x92\x81";
23288 char chunk1[] =
23289 "function foo() {\n"
23290 " // This function will contain an UTF-8 character which is not in\n"
23291 " // ASCII.\n"
23292 " var foobX";
23293 char chunk2[] =
23294 "XX\xec\x92\x81r = 13;\n"
23295 " return foob\xec\x92\x81\xec\x92\x81r;\n"
23296 "}\n";
23297 chunk1[strlen(chunk1) - 1] = reference[0];
23298 chunk2[0] = reference[1];
23299 chunk2[1] = reference[2];
23300 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23301 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23302}
23303
23304
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023305TEST(StreamingWithHarmonyScopes) {
23306 // Don't use RunStreamingTest here so that both scripts get to use the same
23307 // LocalContext and HandleScope.
23308 LocalContext env;
23309 v8::Isolate* isolate = env->GetIsolate();
23310 v8::HandleScope scope(isolate);
23311
23312 // First, run a script with a let variable.
23313 CompileRun("\"use strict\"; let x = 1;");
23314
23315 // Then stream a script which (erroneously) tries to introduce the same
23316 // variable again.
23317 const char* chunks[] = {"\"use strict\"; let x = 2;", NULL};
23318
23319 v8::TryCatch try_catch(isolate);
23320 v8::ScriptCompiler::StreamedSource source(
23321 new TestSourceStream(chunks),
23322 v8::ScriptCompiler::StreamedSource::ONE_BYTE);
23323 v8::ScriptCompiler::ScriptStreamingTask* task =
23324 v8::ScriptCompiler::StartStreamingScript(isolate, &source);
23325 task->Run();
23326 delete task;
23327
23328 // Parsing should succeed (the script will be parsed and compiled in a context
23329 // independent way, so the error is not detected).
23330 CHECK_EQ(false, try_catch.HasCaught());
23331
23332 v8::ScriptOrigin origin(v8_str("http://foo.com"));
23333 char* full_source = TestSourceStream::FullSourceString(chunks);
23334 v8::Local<Script> script =
23335 v8::ScriptCompiler::Compile(env.local(), &source, v8_str(full_source),
23336 origin)
23337 .ToLocalChecked();
23338 CHECK(!script.IsEmpty());
23339 CHECK_EQ(false, try_catch.HasCaught());
23340
23341 // Running the script exposes the error.
23342 CHECK(script->Run(env.local()).IsEmpty());
23343 CHECK(try_catch.HasCaught());
23344 delete[] full_source;
23345}
23346
23347
23348TEST(CodeCache) {
23349 v8::Isolate::CreateParams create_params;
23350 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
23351
23352 const char* source = "Math.sqrt(4)";
23353 const char* origin = "code cache test";
23354 v8::ScriptCompiler::CachedData* cache;
23355
23356 v8::Isolate* isolate1 = v8::Isolate::New(create_params);
23357 {
23358 v8::Isolate::Scope iscope(isolate1);
23359 v8::HandleScope scope(isolate1);
23360 v8::Local<v8::Context> context = v8::Context::New(isolate1);
23361 v8::Context::Scope cscope(context);
23362 v8::Local<v8::String> source_string = v8_str(source);
23363 v8::ScriptOrigin script_origin(v8_str(origin));
23364 v8::ScriptCompiler::Source source(source_string, script_origin);
23365 v8::ScriptCompiler::CompileOptions option =
23366 v8::ScriptCompiler::kProduceCodeCache;
23367 v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked();
23368 int length = source.GetCachedData()->length;
23369 uint8_t* cache_data = new uint8_t[length];
23370 memcpy(cache_data, source.GetCachedData()->data, length);
23371 cache = new v8::ScriptCompiler::CachedData(
23372 cache_data, length, v8::ScriptCompiler::CachedData::BufferOwned);
23373 }
23374 isolate1->Dispose();
23375
23376 v8::Isolate* isolate2 = v8::Isolate::New(create_params);
23377 {
23378 v8::Isolate::Scope iscope(isolate2);
23379 v8::HandleScope scope(isolate2);
23380 v8::Local<v8::Context> context = v8::Context::New(isolate2);
23381 v8::Context::Scope cscope(context);
23382 v8::Local<v8::String> source_string = v8_str(source);
23383 v8::ScriptOrigin script_origin(v8_str(origin));
23384 v8::ScriptCompiler::Source source(source_string, script_origin, cache);
23385 v8::ScriptCompiler::CompileOptions option =
23386 v8::ScriptCompiler::kConsumeCodeCache;
23387 v8::Local<v8::Script> script;
23388 {
23389 i::DisallowCompilation no_compile(
23390 reinterpret_cast<i::Isolate*>(isolate2));
23391 script = v8::ScriptCompiler::Compile(context, &source, option)
23392 .ToLocalChecked();
23393 }
23394 CHECK_EQ(2, script->Run(context)
23395 .ToLocalChecked()
23396 ->ToInt32(context)
23397 .ToLocalChecked()
23398 ->Int32Value(context)
23399 .FromJust());
23400 }
23401 isolate2->Dispose();
23402}
23403
23404
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023405void TestInvalidCacheData(v8::ScriptCompiler::CompileOptions option) {
23406 const char* garbage = "garbage garbage garbage garbage garbage garbage";
23407 const uint8_t* data = reinterpret_cast<const uint8_t*>(garbage);
23408 int length = 16;
23409 v8::ScriptCompiler::CachedData* cached_data =
23410 new v8::ScriptCompiler::CachedData(data, length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023411 CHECK(!cached_data->rejected);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023412 v8::ScriptOrigin origin(v8_str("origin"));
23413 v8::ScriptCompiler::Source source(v8_str("42"), origin, cached_data);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023414 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
23415 v8::Local<v8::Script> script =
23416 v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023417 CHECK(cached_data->rejected);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023418 CHECK_EQ(
23419 42,
23420 script->Run(context).ToLocalChecked()->Int32Value(context).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023421}
23422
23423
23424TEST(InvalidCacheData) {
23425 v8::V8::Initialize();
23426 v8::HandleScope scope(CcTest::isolate());
23427 LocalContext context;
23428 TestInvalidCacheData(v8::ScriptCompiler::kConsumeParserCache);
23429 TestInvalidCacheData(v8::ScriptCompiler::kConsumeCodeCache);
23430}
23431
23432
23433TEST(ParserCacheRejectedGracefully) {
23434 i::FLAG_min_preparse_length = 0;
23435 v8::V8::Initialize();
23436 v8::HandleScope scope(CcTest::isolate());
23437 LocalContext context;
23438 // Produce valid cached data.
23439 v8::ScriptOrigin origin(v8_str("origin"));
23440 v8::Local<v8::String> source_str = v8_str("function foo() {}");
23441 v8::ScriptCompiler::Source source(source_str, origin);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023442 v8::Local<v8::Script> script =
23443 v8::ScriptCompiler::Compile(context.local(), &source,
23444 v8::ScriptCompiler::kProduceParserCache)
23445 .ToLocalChecked();
23446 USE(script);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023447 const v8::ScriptCompiler::CachedData* original_cached_data =
23448 source.GetCachedData();
23449 CHECK(original_cached_data != NULL);
23450 CHECK(original_cached_data->data != NULL);
23451 CHECK(!original_cached_data->rejected);
23452 CHECK_GT(original_cached_data->length, 0);
23453 // Recompiling the same script with it won't reject the data.
23454 {
23455 v8::ScriptCompiler::Source source_with_cached_data(
23456 source_str, origin,
23457 new v8::ScriptCompiler::CachedData(original_cached_data->data,
23458 original_cached_data->length));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023459 v8::Local<v8::Script> script =
23460 v8::ScriptCompiler::Compile(context.local(), &source_with_cached_data,
23461 v8::ScriptCompiler::kConsumeParserCache)
23462 .ToLocalChecked();
23463 USE(script);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023464 const v8::ScriptCompiler::CachedData* new_cached_data =
23465 source_with_cached_data.GetCachedData();
23466 CHECK(new_cached_data != NULL);
23467 CHECK(!new_cached_data->rejected);
23468 }
23469 // Compile an incompatible script with the cached data. The new script doesn't
23470 // have the same starting position for the function as the old one, so the old
23471 // cached data will be incompatible with it and will be rejected.
23472 {
23473 v8::Local<v8::String> incompatible_source_str =
23474 v8_str(" function foo() {}");
23475 v8::ScriptCompiler::Source source_with_cached_data(
23476 incompatible_source_str, origin,
23477 new v8::ScriptCompiler::CachedData(original_cached_data->data,
23478 original_cached_data->length));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023479 v8::Local<v8::Script> script =
23480 v8::ScriptCompiler::Compile(context.local(), &source_with_cached_data,
23481 v8::ScriptCompiler::kConsumeParserCache)
23482 .ToLocalChecked();
23483 USE(script);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023484 const v8::ScriptCompiler::CachedData* new_cached_data =
23485 source_with_cached_data.GetCachedData();
23486 CHECK(new_cached_data != NULL);
23487 CHECK(new_cached_data->rejected);
23488 }
23489}
23490
23491
23492TEST(StringConcatOverflow) {
23493 v8::V8::Initialize();
23494 v8::HandleScope scope(CcTest::isolate());
23495 RandomLengthOneByteResource* r =
23496 new RandomLengthOneByteResource(i::String::kMaxLength);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023497 v8::Local<v8::String> str =
23498 v8::String::NewExternalOneByte(CcTest::isolate(), r).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023499 CHECK(!str.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023500 v8::TryCatch try_catch(CcTest::isolate());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023501 v8::Local<v8::String> result = v8::String::Concat(str, str);
23502 CHECK(result.IsEmpty());
23503 CHECK(!try_catch.HasCaught());
23504}
23505
23506
23507TEST(TurboAsmDisablesNeuter) {
23508 v8::V8::Initialize();
23509 v8::HandleScope scope(CcTest::isolate());
23510 LocalContext context;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023511 bool should_be_neuterable = !i::FLAG_turbo_asm;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023512 const char* load =
23513 "function Module(stdlib, foreign, heap) {"
23514 " 'use asm';"
23515 " var MEM32 = new stdlib.Int32Array(heap);"
23516 " function load() { return MEM32[0]; }"
23517 " return { load: load };"
23518 "}"
23519 "var buffer = new ArrayBuffer(4);"
23520 "Module(this, {}, buffer).load();"
23521 "buffer";
23522
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023523 i::FLAG_turbo_osr = false; // TODO(titzer): test requires eager TF.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023524 v8::Local<v8::ArrayBuffer> result = CompileRun(load).As<v8::ArrayBuffer>();
23525 CHECK_EQ(should_be_neuterable, result->IsNeuterable());
23526
23527 const char* store =
23528 "function Module(stdlib, foreign, heap) {"
23529 " 'use asm';"
23530 " var MEM32 = new stdlib.Int32Array(heap);"
23531 " function store() { MEM32[0] = 0; }"
23532 " return { store: store };"
23533 "}"
23534 "var buffer = new ArrayBuffer(4);"
23535 "Module(this, {}, buffer).store();"
23536 "buffer";
23537
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023538 i::FLAG_turbo_osr = false; // TODO(titzer): test requires eager TF.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023539 result = CompileRun(store).As<v8::ArrayBuffer>();
23540 CHECK_EQ(should_be_neuterable, result->IsNeuterable());
23541}
23542
23543
23544TEST(GetPrototypeAccessControl) {
23545 i::FLAG_allow_natives_syntax = true;
23546 v8::Isolate* isolate = CcTest::isolate();
23547 v8::HandleScope handle_scope(isolate);
23548 LocalContext env;
23549
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023550 v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
23551 obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023552
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023553 CHECK(env->Global()
23554 ->Set(env.local(), v8_str("prohibited"),
23555 obj_template->NewInstance(env.local()).ToLocalChecked())
23556 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023557
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023558 CHECK(CompileRun(
23559 "function f() { return %_GetPrototype(prohibited); }"
23560 "%OptimizeFunctionOnNextCall(f);"
23561 "f();")->IsNull());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023562}
23563
23564
23565TEST(GetPrototypeHidden) {
23566 i::FLAG_allow_natives_syntax = true;
23567 v8::Isolate* isolate = CcTest::isolate();
23568 v8::HandleScope handle_scope(isolate);
23569 LocalContext env;
23570
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023571 Local<FunctionTemplate> t = FunctionTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023572 t->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023573 Local<Object> proto = t->GetFunction(env.local())
23574 .ToLocalChecked()
23575 ->NewInstance(env.local())
23576 .ToLocalChecked();
23577 Local<Object> object = Object::New(isolate);
23578 Local<Object> proto2 = Object::New(isolate);
23579 object->SetPrototype(env.local(), proto).FromJust();
23580 proto->SetPrototype(env.local(), proto2).FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023581
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023582 CHECK(env->Global()->Set(env.local(), v8_str("object"), object).FromJust());
23583 CHECK(env->Global()->Set(env.local(), v8_str("proto"), proto).FromJust());
23584 CHECK(env->Global()->Set(env.local(), v8_str("proto2"), proto2).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023585
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023586 v8::Local<v8::Value> result = CompileRun("%_GetPrototype(object)");
23587 CHECK(result->Equals(env.local(), proto2).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023588
23589 result = CompileRun(
23590 "function f() { return %_GetPrototype(object); }"
23591 "%OptimizeFunctionOnNextCall(f);"
23592 "f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023593 CHECK(result->Equals(env.local(), proto2).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023594}
23595
23596
23597TEST(ClassPrototypeCreationContext) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023598 v8::Isolate* isolate = CcTest::isolate();
23599 v8::HandleScope handle_scope(isolate);
23600 LocalContext env;
23601
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023602 Local<Object> result = Local<Object>::Cast(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023603 CompileRun("'use strict'; class Example { }; Example.prototype"));
23604 CHECK(env.local() == result->CreationContext());
23605}
23606
23607
23608TEST(SimpleStreamingScriptWithSourceURL) {
23609 const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo();\n",
23610 "//# sourceURL=bar2.js\n", NULL};
23611 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
23612 "bar2.js");
23613}
23614
23615
23616TEST(StreamingScriptWithSplitSourceURL) {
23617 const char* chunks[] = {"function foo() { ret", "urn 13; } f",
23618 "oo();\n//# sourceURL=b", "ar2.js\n", NULL};
23619 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
23620 "bar2.js");
23621}
23622
23623
23624TEST(StreamingScriptWithSourceMappingURLInTheMiddle) {
23625 const char* chunks[] = {"function foo() { ret", "urn 13; }\n//#",
23626 " sourceMappingURL=bar2.js\n", "foo();", NULL};
23627 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true, NULL,
23628 "bar2.js");
23629}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023630
23631
23632TEST(NewStringRangeError) {
23633 v8::Isolate* isolate = CcTest::isolate();
23634 v8::HandleScope handle_scope(isolate);
23635 const int length = i::String::kMaxLength + 1;
23636 const int buffer_size = length * sizeof(uint16_t);
23637 void* buffer = malloc(buffer_size);
23638 if (buffer == NULL) return;
23639 memset(buffer, 'A', buffer_size);
23640 {
23641 v8::TryCatch try_catch(isolate);
23642 char* data = reinterpret_cast<char*>(buffer);
23643 CHECK(v8::String::NewFromUtf8(isolate, data, v8::NewStringType::kNormal,
23644 length)
23645 .IsEmpty());
23646 CHECK(!try_catch.HasCaught());
23647 }
23648 {
23649 v8::TryCatch try_catch(isolate);
23650 uint8_t* data = reinterpret_cast<uint8_t*>(buffer);
23651 CHECK(v8::String::NewFromOneByte(isolate, data, v8::NewStringType::kNormal,
23652 length)
23653 .IsEmpty());
23654 CHECK(!try_catch.HasCaught());
23655 }
23656 {
23657 v8::TryCatch try_catch(isolate);
23658 uint16_t* data = reinterpret_cast<uint16_t*>(buffer);
23659 CHECK(v8::String::NewFromTwoByte(isolate, data, v8::NewStringType::kNormal,
23660 length)
23661 .IsEmpty());
23662 CHECK(!try_catch.HasCaught());
23663 }
23664 free(buffer);
23665}
23666
23667
23668TEST(SealHandleScope) {
23669 v8::Isolate* isolate = CcTest::isolate();
23670 v8::HandleScope handle_scope(isolate);
23671 LocalContext env;
23672
23673 v8::SealHandleScope seal(isolate);
23674
23675 // Should fail
23676 v8::Local<v8::Object> obj = v8::Object::New(isolate);
23677
23678 USE(obj);
23679}
23680
23681
23682TEST(SealHandleScopeNested) {
23683 v8::Isolate* isolate = CcTest::isolate();
23684 v8::HandleScope handle_scope(isolate);
23685 LocalContext env;
23686
23687 v8::SealHandleScope seal(isolate);
23688
23689 {
23690 v8::HandleScope handle_scope(isolate);
23691
23692 // Should work
23693 v8::Local<v8::Object> obj = v8::Object::New(isolate);
23694
23695 USE(obj);
23696 }
23697}
23698
23699
23700static bool access_was_called = false;
23701
23702
23703static bool AccessAlwaysAllowedWithFlag(Local<v8::Context> accessing_context,
23704 Local<v8::Object> accessed_object) {
23705 access_was_called = true;
23706 return true;
23707}
23708
23709
23710static bool AccessAlwaysBlockedWithFlag(Local<v8::Context> accessing_context,
23711 Local<v8::Object> accessed_object) {
23712 access_was_called = true;
23713 return false;
23714}
23715
23716
23717TEST(StrongModeAccessCheckAllowed) {
23718 i::FLAG_strong_mode = true;
23719 v8::Isolate* isolate = CcTest::isolate();
23720 v8::HandleScope handle_scope(isolate);
23721 v8::Local<Value> value;
23722 access_was_called = false;
23723
23724 v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
23725
23726 obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
23727 obj_template->SetAccessCheckCallback(AccessAlwaysAllowedWithFlag);
23728
23729 // Create an environment
23730 v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
23731 context0->Enter();
23732 v8::Local<v8::Object> global0 = context0->Global();
23733 global0->Set(context0, v8_str("object"),
23734 obj_template->NewInstance(context0).ToLocalChecked())
23735 .FromJust();
23736 {
23737 v8::TryCatch try_catch(isolate);
23738 value = CompileRun("'use strong'; object.x");
23739 CHECK(!try_catch.HasCaught());
23740 CHECK(!access_was_called);
23741 CHECK_EQ(42, value->Int32Value(context0).FromJust());
23742 }
23743 {
23744 v8::TryCatch try_catch(isolate);
23745 value = CompileRun("'use strong'; object.foo");
23746 CHECK(try_catch.HasCaught());
23747 CHECK(!access_was_called);
23748 }
23749 {
23750 v8::TryCatch try_catch(isolate);
23751 value = CompileRun("'use strong'; object[10]");
23752 CHECK(try_catch.HasCaught());
23753 CHECK(!access_was_called);
23754 }
23755
23756 // Create an environment
23757 v8::Local<Context> context1 = Context::New(isolate);
23758 context1->Enter();
23759 v8::Local<v8::Object> global1 = context1->Global();
23760 global1->Set(context1, v8_str("object"),
23761 obj_template->NewInstance(context1).ToLocalChecked())
23762 .FromJust();
23763 {
23764 v8::TryCatch try_catch(isolate);
23765 value = CompileRun("'use strong'; object.x");
23766 CHECK(!try_catch.HasCaught());
23767 CHECK(access_was_called);
23768 CHECK_EQ(42, value->Int32Value(context1).FromJust());
23769 }
23770 access_was_called = false;
23771 {
23772 v8::TryCatch try_catch(isolate);
23773 value = CompileRun("'use strong'; object.foo");
23774 CHECK(try_catch.HasCaught());
23775 CHECK(access_was_called);
23776 }
23777 access_was_called = false;
23778 {
23779 v8::TryCatch try_catch(isolate);
23780 value = CompileRun("'use strong'; object[10]");
23781 CHECK(try_catch.HasCaught());
23782 CHECK(access_was_called);
23783 }
23784
23785 context1->Exit();
23786 context0->Exit();
23787}
23788
23789
23790TEST(StrongModeAccessCheckBlocked) {
23791 i::FLAG_strong_mode = true;
23792 v8::Isolate* isolate = CcTest::isolate();
23793 v8::HandleScope handle_scope(isolate);
23794 v8::Local<Value> value;
23795 access_was_called = false;
23796
23797 v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
23798
23799 obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
23800 obj_template->SetAccessCheckCallback(AccessAlwaysBlockedWithFlag);
23801
23802 // Create an environment
23803 v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
23804 context0->Enter();
23805 v8::Local<v8::Object> global0 = context0->Global();
23806 global0->Set(context0, v8_str("object"),
23807 obj_template->NewInstance(context0).ToLocalChecked())
23808 .FromJust();
23809 {
23810 v8::TryCatch try_catch(isolate);
23811 value = CompileRun("'use strong'; object.x");
23812 CHECK(!try_catch.HasCaught());
23813 CHECK(!access_was_called);
23814 CHECK_EQ(42, value->Int32Value(context0).FromJust());
23815 }
23816 {
23817 v8::TryCatch try_catch(isolate);
23818 value = CompileRun("'use strong'; object.foo");
23819 CHECK(try_catch.HasCaught());
23820 CHECK(!access_was_called);
23821 }
23822 {
23823 v8::TryCatch try_catch(isolate);
23824 value = CompileRun("'use strong'; object[10]");
23825 CHECK(try_catch.HasCaught());
23826 CHECK(!access_was_called);
23827 }
23828
23829 // Create an environment
23830 v8::Local<Context> context1 = Context::New(isolate);
23831 context1->Enter();
23832 v8::Local<v8::Object> global1 = context1->Global();
23833 global1->Set(context1, v8_str("object"),
23834 obj_template->NewInstance(context1).ToLocalChecked())
23835 .FromJust();
23836 {
23837 v8::TryCatch try_catch(isolate);
23838 value = CompileRun("'use strong'; object.x");
23839 CHECK(try_catch.HasCaught());
23840 CHECK(access_was_called);
23841 }
23842 access_was_called = false;
23843 {
23844 v8::TryCatch try_catch(isolate);
23845 value = CompileRun("'use strong'; object.foo");
23846 CHECK(try_catch.HasCaught());
23847 CHECK(access_was_called);
23848 }
23849 access_was_called = false;
23850 {
23851 v8::TryCatch try_catch(isolate);
23852 value = CompileRun("'use strong'; object[10]");
23853 CHECK(try_catch.HasCaught());
23854 CHECK(access_was_called);
23855 }
23856
23857 context1->Exit();
23858 context0->Exit();
23859}
23860
23861
23862TEST(StrongModeArityCallFromApi) {
23863 i::FLAG_strong_mode = true;
23864 LocalContext env;
23865 v8::Isolate* isolate = env->GetIsolate();
23866 v8::HandleScope scope(isolate);
23867 Local<Function> fun;
23868 {
23869 v8::TryCatch try_catch(isolate);
23870 fun = Local<Function>::Cast(CompileRun(
23871 "function f(x) { 'use strong'; }"
23872 "f"));
23873
23874 CHECK(!try_catch.HasCaught());
23875 }
23876
23877 {
23878 v8::TryCatch try_catch(isolate);
23879 CHECK(fun->Call(env.local(), v8::Undefined(isolate), 0, nullptr).IsEmpty());
23880 CHECK(try_catch.HasCaught());
23881 }
23882
23883 {
23884 v8::TryCatch try_catch(isolate);
23885 v8::Local<Value> args[] = {v8_num(42)};
23886 fun->Call(env.local(), v8::Undefined(isolate), arraysize(args), args)
23887 .ToLocalChecked();
23888 CHECK(!try_catch.HasCaught());
23889 }
23890
23891 {
23892 v8::TryCatch try_catch(isolate);
23893 v8::Local<Value> args[] = {v8_num(42), v8_num(555)};
23894 fun->Call(env.local(), v8::Undefined(isolate), arraysize(args), args)
23895 .ToLocalChecked();
23896 CHECK(!try_catch.HasCaught());
23897 }
23898}
23899
23900
23901TEST(StrongModeArityCallFromApi2) {
23902 i::FLAG_strong_mode = true;
23903 LocalContext env;
23904 v8::Isolate* isolate = env->GetIsolate();
23905 v8::HandleScope scope(isolate);
23906 Local<Function> fun;
23907 {
23908 v8::TryCatch try_catch(isolate);
23909 fun = Local<Function>::Cast(CompileRun(
23910 "'use strong';"
23911 "function f(x) {}"
23912 "f"));
23913
23914 CHECK(!try_catch.HasCaught());
23915 }
23916
23917 {
23918 v8::TryCatch try_catch(isolate);
23919 CHECK(fun->Call(env.local(), v8::Undefined(isolate), 0, nullptr).IsEmpty());
23920 CHECK(try_catch.HasCaught());
23921 }
23922
23923 {
23924 v8::TryCatch try_catch(isolate);
23925 v8::Local<Value> args[] = {v8_num(42)};
23926 fun->Call(env.local(), v8::Undefined(isolate), arraysize(args), args)
23927 .ToLocalChecked();
23928 CHECK(!try_catch.HasCaught());
23929 }
23930
23931 {
23932 v8::TryCatch try_catch(isolate);
23933 v8::Local<Value> args[] = {v8_num(42), v8_num(555)};
23934 fun->Call(env.local(), v8::Undefined(isolate), arraysize(args), args)
23935 .ToLocalChecked();
23936 CHECK(!try_catch.HasCaught());
23937 }
23938}
23939
23940
23941TEST(StrongObjectDelete) {
23942 i::FLAG_strong_mode = true;
23943 LocalContext env;
23944 v8::Isolate* isolate = env->GetIsolate();
23945 v8::HandleScope scope(isolate);
23946 Local<Object> obj;
23947 {
23948 v8::TryCatch try_catch(isolate);
23949 obj = Local<Object>::Cast(CompileRun(
23950 "'use strong';"
23951 "({});"));
23952 CHECK(!try_catch.HasCaught());
23953 }
23954 obj->DefineOwnProperty(env.local(), v8_str("foo"), v8_num(1), v8::None)
23955 .FromJust();
23956 obj->DefineOwnProperty(env.local(), v8_str("2"), v8_num(1), v8::None)
23957 .FromJust();
23958 CHECK(obj->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
23959 CHECK(obj->HasOwnProperty(env.local(), v8_str("2")).FromJust());
23960 CHECK(!obj->Delete(env.local(), v8_str("foo")).FromJust());
23961 CHECK(!obj->Delete(env.local(), 2).FromJust());
23962}
23963
23964
23965static void ExtrasBindingTestRuntimeFunction(
23966 const v8::FunctionCallbackInfo<v8::Value>& args) {
23967 CHECK_EQ(
23968 3,
23969 args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust());
23970 args.GetReturnValue().Set(v8_num(7));
23971}
23972
23973
23974TEST(ExtrasBindingObject) {
23975 v8::Isolate* isolate = CcTest::isolate();
23976 v8::HandleScope handle_scope(isolate);
23977 LocalContext env;
23978
23979 // standalone.gypi ensures we include the test-extra.js file, which should
23980 // export the tested functions.
23981 v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
23982
23983 auto func = binding->Get(env.local(), v8_str("testExtraShouldReturnFive"))
23984 .ToLocalChecked()
23985 .As<v8::Function>();
23986 auto undefined = v8::Undefined(isolate);
23987 auto result = func->Call(env.local(), undefined, 0, {})
23988 .ToLocalChecked()
23989 .As<v8::Number>();
23990 CHECK_EQ(5, result->Int32Value(env.local()).FromJust());
23991
23992 v8::Local<v8::FunctionTemplate> runtimeFunction =
23993 v8::FunctionTemplate::New(isolate, ExtrasBindingTestRuntimeFunction);
23994 binding->Set(env.local(), v8_str("runtime"),
23995 runtimeFunction->GetFunction(env.local()).ToLocalChecked())
23996 .FromJust();
23997 func = binding->Get(env.local(), v8_str("testExtraShouldCallToRuntime"))
23998 .ToLocalChecked()
23999 .As<v8::Function>();
24000 result = func->Call(env.local(), undefined, 0, {})
24001 .ToLocalChecked()
24002 .As<v8::Number>();
24003 CHECK_EQ(7, result->Int32Value(env.local()).FromJust());
24004}
24005
24006
24007TEST(ExperimentalExtras) {
24008 i::FLAG_experimental_extras = true;
24009
24010 v8::Isolate* isolate = CcTest::isolate();
24011 v8::HandleScope handle_scope(isolate);
24012 LocalContext env;
24013
24014 // standalone.gypi ensures we include the test-experimental-extra.js file,
24015 // which should export the tested functions.
24016 v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
24017
24018 auto func =
24019 binding->Get(env.local(), v8_str("testExperimentalExtraShouldReturnTen"))
24020 .ToLocalChecked()
24021 .As<v8::Function>();
24022 auto undefined = v8::Undefined(isolate);
24023 auto result = func->Call(env.local(), undefined, 0, {})
24024 .ToLocalChecked()
24025 .As<v8::Number>();
24026 CHECK_EQ(10, result->Int32Value(env.local()).FromJust());
24027
24028 v8::Local<v8::FunctionTemplate> runtimeFunction =
24029 v8::FunctionTemplate::New(isolate, ExtrasBindingTestRuntimeFunction);
24030 binding->Set(env.local(), v8_str("runtime"),
24031 runtimeFunction->GetFunction(env.local()).ToLocalChecked())
24032 .FromJust();
24033 func = binding->Get(env.local(),
24034 v8_str("testExperimentalExtraShouldCallToRuntime"))
24035 .ToLocalChecked()
24036 .As<v8::Function>();
24037 result = func->Call(env.local(), undefined, 0, {})
24038 .ToLocalChecked()
24039 .As<v8::Number>();
24040 CHECK_EQ(7, result->Int32Value(env.local()).FromJust());
24041}
24042
24043
24044TEST(ExtrasUtilsObject) {
24045 LocalContext context;
24046 v8::Isolate* isolate = context->GetIsolate();
24047 v8::HandleScope handle_scope(isolate);
24048
24049 LocalContext env;
24050 v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
24051
24052 auto func = binding->Get(env.local(), v8_str("testExtraCanUseUtils"))
24053 .ToLocalChecked()
24054 .As<v8::Function>();
24055 auto undefined = v8::Undefined(isolate);
24056 auto result = func->Call(env.local(), undefined, 0, {})
24057 .ToLocalChecked()
24058 .As<v8::Object>();
24059
24060 auto private_symbol = result->Get(env.local(), v8_str("privateSymbol"))
24061 .ToLocalChecked()
24062 .As<v8::Symbol>();
24063 i::Handle<i::Symbol> ips = v8::Utils::OpenHandle(*private_symbol);
24064 CHECK_EQ(true, ips->IsPrivate());
24065
24066 CompileRun("var result = 0; function store(x) { result = x; }");
24067 auto store = CompileRun("store").As<v8::Function>();
24068
24069 auto fulfilled_promise = result->Get(env.local(), v8_str("fulfilledPromise"))
24070 .ToLocalChecked()
24071 .As<v8::Promise>();
24072 fulfilled_promise->Then(env.local(), store).ToLocalChecked();
24073 isolate->RunMicrotasks();
24074 CHECK_EQ(1, CompileRun("result")->Int32Value(env.local()).FromJust());
24075
24076 auto fulfilled_promise_2 =
24077 result->Get(env.local(), v8_str("fulfilledPromise2"))
24078 .ToLocalChecked()
24079 .As<v8::Promise>();
24080 fulfilled_promise_2->Then(env.local(), store).ToLocalChecked();
24081 isolate->RunMicrotasks();
24082 CHECK_EQ(2, CompileRun("result")->Int32Value(env.local()).FromJust());
24083
24084 auto rejected_promise = result->Get(env.local(), v8_str("rejectedPromise"))
24085 .ToLocalChecked()
24086 .As<v8::Promise>();
24087 rejected_promise->Catch(env.local(), store).ToLocalChecked();
24088 isolate->RunMicrotasks();
24089 CHECK_EQ(3, CompileRun("result")->Int32Value(env.local()).FromJust());
24090}
24091
24092
24093TEST(Map) {
24094 v8::Isolate* isolate = CcTest::isolate();
24095 v8::HandleScope handle_scope(isolate);
24096 LocalContext env;
24097
24098 v8::Local<v8::Map> map = v8::Map::New(isolate);
24099 CHECK(map->IsObject());
24100 CHECK(map->IsMap());
24101 CHECK(map->GetPrototype()->StrictEquals(CompileRun("Map.prototype")));
24102 CHECK_EQ(0U, map->Size());
24103
24104 v8::Local<v8::Value> val = CompileRun("new Map([[1, 2], [3, 4]])");
24105 CHECK(val->IsMap());
24106 map = v8::Local<v8::Map>::Cast(val);
24107 CHECK_EQ(2U, map->Size());
24108
24109 v8::Local<v8::Array> contents = map->AsArray();
24110 CHECK_EQ(4U, contents->Length());
24111 CHECK_EQ(
24112 1,
24113 contents->Get(env.local(), 0).ToLocalChecked().As<v8::Int32>()->Value());
24114 CHECK_EQ(
24115 2,
24116 contents->Get(env.local(), 1).ToLocalChecked().As<v8::Int32>()->Value());
24117 CHECK_EQ(
24118 3,
24119 contents->Get(env.local(), 2).ToLocalChecked().As<v8::Int32>()->Value());
24120 CHECK_EQ(
24121 4,
24122 contents->Get(env.local(), 3).ToLocalChecked().As<v8::Int32>()->Value());
24123
24124 CHECK_EQ(2U, map->Size());
24125
24126 CHECK(map->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
24127 CHECK(map->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
24128
24129 CHECK(!map->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
24130 CHECK(!map->Has(env.local(), map).FromJust());
24131
24132 CHECK_EQ(2, map->Get(env.local(), v8::Integer::New(isolate, 1))
24133 .ToLocalChecked()
24134 ->Int32Value(env.local())
24135 .FromJust());
24136 CHECK_EQ(4, map->Get(env.local(), v8::Integer::New(isolate, 3))
24137 .ToLocalChecked()
24138 ->Int32Value(env.local())
24139 .FromJust());
24140
24141 CHECK(map->Get(env.local(), v8::Integer::New(isolate, 42))
24142 .ToLocalChecked()
24143 ->IsUndefined());
24144
24145 CHECK(!map->Set(env.local(), map, map).IsEmpty());
24146 CHECK_EQ(3U, map->Size());
24147 CHECK(map->Has(env.local(), map).FromJust());
24148
24149 CHECK(map->Delete(env.local(), map).FromJust());
24150 CHECK_EQ(2U, map->Size());
24151 CHECK(!map->Has(env.local(), map).FromJust());
24152 CHECK(!map->Delete(env.local(), map).FromJust());
24153
24154 map->Clear();
24155 CHECK_EQ(0U, map->Size());
24156}
24157
24158
24159TEST(Set) {
24160 v8::Isolate* isolate = CcTest::isolate();
24161 v8::HandleScope handle_scope(isolate);
24162 LocalContext env;
24163
24164 v8::Local<v8::Set> set = v8::Set::New(isolate);
24165 CHECK(set->IsObject());
24166 CHECK(set->IsSet());
24167 CHECK(set->GetPrototype()->StrictEquals(CompileRun("Set.prototype")));
24168 CHECK_EQ(0U, set->Size());
24169
24170 v8::Local<v8::Value> val = CompileRun("new Set([1, 2])");
24171 CHECK(val->IsSet());
24172 set = v8::Local<v8::Set>::Cast(val);
24173 CHECK_EQ(2U, set->Size());
24174
24175 v8::Local<v8::Array> keys = set->AsArray();
24176 CHECK_EQ(2U, keys->Length());
24177 CHECK_EQ(1,
24178 keys->Get(env.local(), 0).ToLocalChecked().As<v8::Int32>()->Value());
24179 CHECK_EQ(2,
24180 keys->Get(env.local(), 1).ToLocalChecked().As<v8::Int32>()->Value());
24181
24182 CHECK_EQ(2U, set->Size());
24183
24184 CHECK(set->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
24185 CHECK(set->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
24186
24187 CHECK(!set->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
24188 CHECK(!set->Has(env.local(), set).FromJust());
24189
24190 CHECK(!set->Add(env.local(), set).IsEmpty());
24191 CHECK_EQ(3U, set->Size());
24192 CHECK(set->Has(env.local(), set).FromJust());
24193
24194 CHECK(set->Delete(env.local(), set).FromJust());
24195 CHECK_EQ(2U, set->Size());
24196 CHECK(!set->Has(env.local(), set).FromJust());
24197 CHECK(!set->Delete(env.local(), set).FromJust());
24198
24199 set->Clear();
24200 CHECK_EQ(0U, set->Size());
24201}
24202
24203
24204TEST(CompatibleReceiverCheckOnCachedICHandler) {
24205 v8::Isolate* isolate = CcTest::isolate();
24206 v8::HandleScope scope(isolate);
24207 v8::Local<v8::FunctionTemplate> parent = FunctionTemplate::New(isolate);
24208 v8::Local<v8::Signature> signature = v8::Signature::New(isolate, parent);
24209 auto returns_42 =
24210 v8::FunctionTemplate::New(isolate, Returns42, Local<Value>(), signature);
24211 parent->PrototypeTemplate()->SetAccessorProperty(v8_str("age"), returns_42);
24212 v8::Local<v8::FunctionTemplate> child = v8::FunctionTemplate::New(isolate);
24213 child->Inherit(parent);
24214 LocalContext env;
24215 CHECK(env->Global()
24216 ->Set(env.local(), v8_str("Child"),
24217 child->GetFunction(env.local()).ToLocalChecked())
24218 .FromJust());
24219
24220 // Make sure there's a compiled stub for "Child.prototype.age" in the cache.
24221 CompileRun(
24222 "var real = new Child();\n"
24223 "for (var i = 0; i < 3; ++i) {\n"
24224 " real.age;\n"
24225 "}\n");
24226
24227 // Check that the cached stub is never used.
24228 ExpectInt32(
24229 "var fake = Object.create(Child.prototype);\n"
24230 "var result = 0;\n"
24231 "function test(d) {\n"
24232 " if (d == 3) return;\n"
24233 " try {\n"
24234 " fake.age;\n"
24235 " result = 1;\n"
24236 " } catch (e) {\n"
24237 " }\n"
24238 " test(d+1);\n"
24239 "}\n"
24240 "test(0);\n"
24241 "result;\n",
24242 0);
24243}
24244
24245class FutexInterruptionThread : public v8::base::Thread {
24246 public:
24247 explicit FutexInterruptionThread(v8::Isolate* isolate)
24248 : Thread(Options("FutexInterruptionThread")), isolate_(isolate) {}
24249
24250 virtual void Run() {
24251 // Wait a bit before terminating.
24252 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
24253 isolate_->TerminateExecution();
24254 }
24255
24256 private:
24257 v8::Isolate* isolate_;
24258};
24259
24260
24261TEST(FutexInterruption) {
24262 i::FLAG_harmony_sharedarraybuffer = true;
24263 v8::Isolate* isolate = CcTest::isolate();
24264 v8::HandleScope scope(isolate);
24265 LocalContext env;
24266
24267 FutexInterruptionThread timeout_thread(isolate);
24268
24269 v8::TryCatch try_catch(CcTest::isolate());
24270 timeout_thread.Start();
24271
24272 CompileRun(
24273 "var ab = new SharedArrayBuffer(4);"
24274 "var i32a = new Int32Array(ab);"
24275 "Atomics.futexWait(i32a, 0, 0);");
24276 CHECK(try_catch.HasTerminated());
24277 timeout_thread.Join();
24278}
24279
24280
24281TEST(EstimatedContextSize) {
24282 v8::Isolate* isolate = CcTest::isolate();
24283 v8::HandleScope scope(isolate);
24284 LocalContext env;
24285 CHECK(50000 < env->EstimatedSize());
24286}
24287
24288
24289static int nb_uncaught_exception_callback_calls = 0;
24290
24291
24292bool NoAbortOnUncaughtException(v8::Isolate* isolate) {
24293 ++nb_uncaught_exception_callback_calls;
24294 return false;
24295}
24296
24297
24298TEST(AbortOnUncaughtExceptionNoAbort) {
24299 v8::Isolate* isolate = CcTest::isolate();
24300 v8::HandleScope handle_scope(isolate);
24301 v8::Local<v8::ObjectTemplate> global_template =
24302 v8::ObjectTemplate::New(isolate);
24303 LocalContext env(NULL, global_template);
24304
24305 i::FLAG_abort_on_uncaught_exception = true;
24306 isolate->SetAbortOnUncaughtExceptionCallback(NoAbortOnUncaughtException);
24307
24308 CompileRun("function boom() { throw new Error(\"boom\") }");
24309
24310 v8::Local<v8::Object> global_object = env->Global();
24311 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
24312 global_object->Get(env.local(), v8_str("boom")).ToLocalChecked());
24313
24314 CHECK(foo->Call(env.local(), global_object, 0, NULL).IsEmpty());
24315
24316 CHECK_EQ(1, nb_uncaught_exception_callback_calls);
24317}
24318
24319
24320TEST(AccessCheckedIsConcatSpreadable) {
24321 i::FLAG_harmony_concat_spreadable = true;
24322 v8::Isolate* isolate = CcTest::isolate();
24323 HandleScope scope(isolate);
24324 LocalContext env;
24325
24326 // Object with access check
24327 Local<ObjectTemplate> spreadable_template = v8::ObjectTemplate::New(isolate);
24328 spreadable_template->SetAccessCheckCallback(AccessBlocker);
24329 spreadable_template->Set(v8::Symbol::GetIsConcatSpreadable(isolate),
24330 v8::Boolean::New(isolate, true));
24331 Local<Object> object =
24332 spreadable_template->NewInstance(env.local()).ToLocalChecked();
24333
24334 allowed_access = true;
24335 CHECK(env->Global()->Set(env.local(), v8_str("object"), object).FromJust());
24336 object->Set(env.local(), v8_str("length"), v8_num(2)).FromJust();
24337 object->Set(env.local(), 0U, v8_str("a")).FromJust();
24338 object->Set(env.local(), 1U, v8_str("b")).FromJust();
24339
24340 // Access check is allowed, and the object is spread
24341 CompileRun("var result = [].concat(object)");
24342 ExpectTrue("Array.isArray(result)");
24343 ExpectString("result[0]", "a");
24344 ExpectString("result[1]", "b");
24345 ExpectTrue("result.length === 2");
24346 ExpectTrue("object[Symbol.isConcatSpreadable]");
24347
24348 // If access check fails, the value of @@isConcatSpreadable is ignored
24349 allowed_access = false;
24350 CompileRun("var result = [].concat(object)");
24351 ExpectTrue("Array.isArray(result)");
24352 ExpectTrue("result[0] === object");
24353 ExpectTrue("result.length === 1");
24354 ExpectTrue("object[Symbol.isConcatSpreadable] === undefined");
24355}
24356
24357
24358TEST(AccessCheckedToStringTag) {
24359 i::FLAG_harmony_tostring = true;
24360 v8::Isolate* isolate = CcTest::isolate();
24361 HandleScope scope(isolate);
24362 LocalContext env;
24363
24364 // Object with access check
24365 Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
24366 object_template->SetAccessCheckCallback(AccessBlocker);
24367 Local<Object> object =
24368 object_template->NewInstance(env.local()).ToLocalChecked();
24369
24370 allowed_access = true;
24371 env->Global()->Set(env.local(), v8_str("object"), object).FromJust();
24372 object->Set(env.local(), v8::Symbol::GetToStringTag(isolate), v8_str("hello"))
24373 .FromJust();
24374
24375 // Access check is allowed, and the toStringTag is read
24376 CompileRun("var result = Object.prototype.toString.call(object)");
24377 ExpectString("result", "[object hello]");
24378 ExpectString("object[Symbol.toStringTag]", "hello");
24379
24380 // ToString through the API should succeed too.
24381 String::Utf8Value result_allowed(
24382 object->ObjectProtoToString(env.local()).ToLocalChecked());
24383 CHECK_EQ(0, strcmp(*result_allowed, "[object hello]"));
24384
24385 // If access check fails, the value of @@toStringTag is ignored
24386 allowed_access = false;
24387 CompileRun("var result = Object.prototype.toString.call(object)");
24388 ExpectString("result", "[object Object]");
24389 ExpectTrue("object[Symbol.toStringTag] === undefined");
24390
24391 // ToString through the API should also fail.
24392 String::Utf8Value result_denied(
24393 object->ObjectProtoToString(env.local()).ToLocalChecked());
24394 CHECK_EQ(0, strcmp(*result_denied, "[object Object]"));
24395}
24396
24397
24398TEST(ObjectTemplateIntrinsics) {
24399 v8::Isolate* isolate = CcTest::isolate();
24400 v8::HandleScope scope(isolate);
24401 LocalContext env;
24402
24403 Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
24404 object_template->SetIntrinsicDataProperty(v8_str("values"),
24405 v8::kArrayProto_values);
24406 Local<Object> object =
24407 object_template->NewInstance(env.local()).ToLocalChecked();
24408
24409 CHECK(env->Global()->Set(env.local(), v8_str("obj1"), object).FromJust());
24410 ExpectString("typeof obj1.values", "function");
24411
24412 auto values = Local<Function>::Cast(
24413 object->Get(env.local(), v8_str("values")).ToLocalChecked());
24414 auto fn = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*values));
24415 auto ctx = v8::Utils::OpenHandle(*env.local());
24416 CHECK_EQ(fn->GetCreationContext(), *ctx);
24417
24418 {
24419 LocalContext env2;
24420 Local<Object> object2 =
24421 object_template->NewInstance(env2.local()).ToLocalChecked();
24422 CHECK(
24423 env2->Global()->Set(env2.local(), v8_str("obj2"), object2).FromJust());
24424 ExpectString("typeof obj2.values", "function");
24425 CHECK_NE(*object->Get(env2.local(), v8_str("values")).ToLocalChecked(),
24426 *object2->Get(env2.local(), v8_str("values")).ToLocalChecked());
24427
24428 auto values2 = Local<Function>::Cast(
24429 object2->Get(env2.local(), v8_str("values")).ToLocalChecked());
24430 auto fn2 = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*values2));
24431 auto ctx2 = v8::Utils::OpenHandle(*env2.local());
24432 CHECK_EQ(fn2->GetCreationContext(), *ctx2);
24433 }
24434}
24435
24436
24437TEST(Proxy) {
24438 i::FLAG_harmony_proxies = true;
24439 LocalContext context;
24440 v8::Isolate* isolate = CcTest::isolate();
24441 v8::HandleScope scope(isolate);
24442 v8::Local<v8::Object> target = CompileRun("({})").As<v8::Object>();
24443 v8::Local<v8::Object> handler = CompileRun("({})").As<v8::Object>();
24444
24445 v8::Local<v8::Proxy> proxy =
24446 v8::Proxy::New(context.local(), target, handler).ToLocalChecked();
24447 CHECK(proxy->IsProxy());
24448 CHECK(!target->IsProxy());
24449 CHECK(!proxy->IsRevoked());
24450 CHECK(proxy->GetTarget()->SameValue(target));
24451 CHECK(proxy->GetHandler()->SameValue(handler));
24452
24453 proxy->Revoke();
24454 CHECK(proxy->IsProxy());
24455 CHECK(!target->IsProxy());
24456 CHECK(proxy->IsRevoked());
24457 CHECK(proxy->GetTarget()->SameValue(target));
24458 CHECK(proxy->GetHandler()->IsNull());
24459}